nfp_sites/nfp_moe/app/admin/editpage.js

263 lines
7.4 KiB
JavaScript

const FileUpload = require('./fileupload')
const PageTree = require('../page_tree')
const api = require('../api')
const Editor = require('./editor')
const EditPage = {
oninit: function(vnode) {
this.loading = false
this.showLoading = null
this.data = {
page: null,
}
this.pages = [{id: null, name: 'Frontpage'}]
this.pages = this.pages.concat(PageTree.getFlatTree())
this.newBanner = null
this.newMedia = null
this.editor = null
this.fetchPage(vnode)
},
onbeforeupdate: function(vnode) {
if (this.lastid !== m.route.param('id')) {
this.fetchPage(vnode)
}
},
fetchPage: function(vnode) {
this.lastid = m.route.param('id')
return this.requestPage(
api.sendRequest({
method: 'GET',
url: '/api/auth/pages/' + (this.lastid === 'add' ? '0' : this.lastid),
})
)
},
requestPage: function(data) {
this.error = ''
if (this.showLoading) {
clearTimeout(this.showLoading)
}
if (this.data.page) {
this.showLoading = setTimeout(() => {
this.showLoading = null
this.loading = true
m.redraw()
}, 150)
} else {
this.loading = true
}
data
.then((result) => {
this.data = result
if (this.data.page.id) {
document.title = 'Editing: ' + this.data.page.name + ' - Admin NFP Moe'
this.editedPath = true
} else {
document.title = 'Create Page - Admin NFP Moe'
}
}, (err) => {
this.error = err.message
})
.then(() => {
clearTimeout(this.showLoading)
this.showLoading = null
this.loading = false
m.redraw()
})
},
updateValue: function(name, e) {
this.data.page[name] = e.currentTarget.value
if (name === 'path') {
this.editedPath = true
} else if (name === 'name' && !this.editedPath) {
this.data.page.path = this.data.page.name.toLowerCase().replace(/ /g, '-')
}
},
updateParent: function(e) {
this.data.page.parent_id = Number(e.currentTarget.value) || null
},
mediaUploaded: function(type, file) {
if (type === 'banner') {
this.newBanner = file
} else {
this.newMedia = file
}
},
mediaRemoved: function(type) {
this.data.page['remove_' + type] = true
this.data.page[type + '_prefix'] = null
},
save: function(vnode, e) {
e.preventDefault()
if (!this.data.page.name) {
this.error = 'Name is missing'
} else if (!this.data.page.path) {
this.error = 'Path is missing'
} else {
this.error = ''
}
if (this.error) return
let formData = new FormData()
if (this.newBanner) {
formData.append('banner', this.newBanner.file)
}
if (this.newMedia) {
formData.append('media', this.newMedia.file)
}
if (this.data.page.id) {
formData.append('id', this.data.page.id)
}
formData.append('name', this.data.page.name)
formData.append('parent_id', this.data.page.parent_id || null)
formData.append('path', this.data.page.path)
formData.append('remove_banner', this.data.page.remove_banner ? true : false)
formData.append('remove_media', this.data.page.remove_media ? true : false)
this.loading = true
this.requestPage(
this.editor.save()
.then(body => {
formData.append('content', JSON.stringify(body))
return api.sendRequest({
method: 'PUT',
url: '/api/auth/pages/' + (this.lastid === 'add' ? '0' : this.lastid),
body: formData,
})
})
.then(data => {
if (!data.page.id) {
throw new Error('Something went wrong with saving, try again later')
} else if (this.lastid === 'add') {
this.lastid = data.page.id.toString()
m.route.set('/admin/pages/' + data.page.id)
}
return PageTree.refreshTree().then(() => {
this.pages = [{id: null, name: 'Frontpage'}]
this.pages = this.pages.concat(PageTree.getFlatTree())
return data
})
})
)
},
view: function(vnode) {
const bannerImage = this.data.page && this.data.page.banner_prefix
? this.data.page.banner_prefix + '_large.avif'
: null
const mediaImage = this.data.page && this.data.page.media_prefix
? this.data.page.media_prefix + '_large.avif'
: null
return [
this.loading && !this.data.page
? m('div.admin-spinner.loading-spinner')
: null,
this.data.page
? m('div.admin-wrapper', [
this.loading
? m('div.loading-spinner')
: null,
m('div.admin-actions', this.data.page.id
? [
m('span', 'Actions:'),
m(m.route.Link, { href: '/page/' + this.data.page.path }, 'View page'),
]
: null),
m('article.editarticle', [
m('header', m('h1',
(this.data.page.id ? 'Edit ' : 'Create Page ') + (this.data.page.name || '(untitled)')
)
),
m('div.error', {
hidden: !this.error,
onclick: () => { vnode.state.error = '' },
}, this.error),
m(FileUpload, {
height: 300,
onfile: this.mediaUploaded.bind(this, 'banner'),
ondelete: this.mediaRemoved.bind(this, 'banner'),
media: bannerImage,
}),
m(FileUpload, {
class: 'cover',
useimg: true,
onfile: this.mediaUploaded.bind(this, 'media'),
ondelete: this.mediaRemoved.bind(this, 'media'),
media: mediaImage,
}),
m('form.editarticle.content', {
onsubmit: this.save.bind(this, vnode),
}, [
m('label', 'Parent'),
m('select', {
onchange: this.updateParent.bind(this),
}, this.pages.filter(item => !this.data.page || item.id !== this.data.page.id).map((item) => {
return m('option', {
value: item.id || 0,
selected: item.id === this.data.page.parent_id
}, item.name)
})),
m('div.input-row', [
m('div.input-group', [
m('label', 'Name'),
m('input', {
type: 'text',
value: this.data.page.name,
oninput: this.updateValue.bind(this, 'name'),
}),
]),
m('div.input-group', [
m('label', 'Path'),
m('input', {
type: 'text',
value: this.data.page.path,
oninput: this.updateValue.bind(this, 'path'),
}),
]),
]),
m('label', 'Description'),
m(Editor, {
oncreate: (subnode) => {
this.editor = subnode.state.editor
},
contentdata: this.data.page.content,
}),
m('div', {
hidden: !this.data.page.name || !this.data.page.path
}, [
m('input', {
type: 'submit',
value: 'Save',
}),
]),
]),
]),
])
: m('div.error', {
hidden: !this.error,
onclick: () => { this.fetchPage(vnode) },
}, this.error),,
]
},
}
module.exports = EditPage