nfp_sites/app/admin/editarticle.js

292 lines
8.5 KiB
JavaScript
Raw Normal View History

2019-09-13 13:33:10 +00:00
const m = require('mithril')
const Authentication = require('../authentication')
const FileUpload = require('../widgets/fileupload')
const Froala = require('./froala')
const { Tree } = require('../api/page')
2019-09-14 19:03:38 +00:00
const { uploadFile } = require('../api/file')
const Fileinfo = require('../widgets/fileinfo')
2019-09-13 13:33:10 +00:00
const { createArticle, updateArticle, getArticle } = require('../api/article')
const EditArticle = {
getFroalaOptions: function() {
return {
theme: 'gray',
heightMin: 150,
videoUpload: false,
imageUploadURL: '/api/media',
imageManagerLoadURL: '/api/media',
imageManagerDeleteMethod: 'DELETE',
imageManagerDeleteURL: '/api/media',
events: {
'imageManager.beforeDeleteImage': function(img) {
this.opts.imageManagerDeleteURL = '/api/media/' + img.data('id')
},
},
requestHeaders: {
'Authorization': 'Bearer ' + Authentication.getToken(),
},
}
},
oninit: function(vnode) {
2019-09-14 19:03:38 +00:00
this.froala = null
this.loadedFroala = Froala.loadedFroala
if (!this.loadedFroala) {
Froala.createFroalaScript()
.then(function() {
vnode.state.loadedFroala = true
m.redraw()
})
}
this.fetchArticle(vnode)
},
onupdate: function(vnode) {
if (this.lastid !== m.route.param('id')) {
this.fetchArticle(vnode)
}
},
fetchArticle: function(vnode) {
this.lastid = m.route.param('id')
this.loading = this.lastid !== 'add'
this.creating = this.lastid === 'add'
2019-09-13 13:33:10 +00:00
this.loadingFile = false
this.error = ''
this.article = {
name: '',
path: '',
description: '',
media: null,
banner: null,
2019-09-14 19:03:38 +00:00
files: [],
2019-09-13 13:33:10 +00:00
}
this.editedPath = false
this.froala = null
this.loadedFroala = Froala.loadedFroala
2019-09-14 19:03:38 +00:00
if (this.lastid !== 'add') {
getArticle(this.lastid)
2019-09-13 13:33:10 +00:00
.then(function(result) {
vnode.state.editedPath = true
vnode.state.article = result
})
.catch(function(err) {
vnode.state.error = err.message
})
.then(function() {
vnode.state.loading = false
m.redraw()
})
}
},
updateValue: function(name, e) {
this.article[name] = e.currentTarget.value
if (name === 'path') {
this.editedPath = true
} else if (name === 'name' && !this.editedPath) {
this.article.path = this.article.name.toLowerCase().replace(/ /g, '-')
}
},
updateParent: function(e) {
this.article.parent_id = Number(e.currentTarget.value)
if (this.article.parent_id === -1) {
this.article.parent_id = null
}
},
2019-09-14 19:03:38 +00:00
mediaUploaded: function(type, media) {
2019-09-13 13:33:10 +00:00
this.article[type] = media
},
2019-09-14 19:03:38 +00:00
mediaRemoved: function(type) {
this.article[type] = null
},
2019-09-13 13:33:10 +00:00
save: function(vnode, e) {
e.preventDefault()
if (!this.article.name) {
this.error = 'Name is missing'
} else if (!this.article.path) {
this.error = 'Path is missing'
2019-09-14 19:03:38 +00:00
} else {
this.error = ''
2019-09-13 13:33:10 +00:00
}
if (this.error) return
this.article.description = vnode.state.froala && vnode.state.froala.html.get() || this.article.description
this.loading = true
let promise
if (this.article.id) {
promise = updateArticle(this.article.id, {
name: this.article.name,
path: this.article.path,
parent_id: this.article.parent_id,
description: this.article.description,
banner_id: this.article.banner && this.article.banner.id,
media_id: this.article.media && this.article.media.id,
})
} else {
promise = createArticle({
name: this.article.name,
path: this.article.path,
parent_id: this.article.parent_id,
description: this.article.description,
banner_id: this.article.banner && this.article.banner.id,
media_id: this.article.media && this.article.media.id,
})
}
promise.then(function(res) {
if (vnode.state.article.id) {
res.media = vnode.state.article.media
res.banner = vnode.state.article.banner
2019-09-14 19:03:38 +00:00
res.files = vnode.state.article.files
2019-09-13 13:33:10 +00:00
vnode.state.article = res
} else {
m.route.set('/admin/articles/' + res.id)
}
})
.catch(function(err) {
vnode.state.error = err.message
})
.then(function() {
vnode.state.loading = false
m.redraw()
})
},
uploadFile(vnode, event) {
if (!event.target.files[0]) return
vnode.state.error = ''
vnode.state.loadingFile = true
2019-09-14 19:03:38 +00:00
uploadFile(this.article.id, event.target.files[0])
.then(function(res) {
vnode.state.article.files.push(res)
})
.catch(function(err) {
vnode.state.error = err.message
})
.then(function() {
event.target.value = null
vnode.state.loadingFile = false
m.redraw()
})
2019-09-13 13:33:10 +00:00
},
getFlatTree: function() {
let out = [{id: null, name: '-- Frontpage --'}]
Tree.forEach(function(page) {
out.push({ id: page.id, name: page.name })
if (page.children.length) {
page.children.forEach(function(sub) {
out.push({ id: sub.id, name: page.name + ' -> ' + sub.name })
})
}
})
return out
},
view: function(vnode) {
const parents = this.getFlatTree()
return (
this.loading ?
m('div.loading-spinner')
: m('div.admin-wrapper', [
m('div.admin-actions', this.article.id
? [
m('span', 'Actions:'),
m(m.route.Link, { href: '/article/' + this.article.path }, 'View article'),
]
: null),
m('article.editarticle', [
m('header', m('h1', this.creating ? 'Create Article' : 'Edit ' + (this.article.name || '(untitled)'))),
m('div.error', {
hidden: !this.error,
2019-09-14 19:03:38 +00:00
onclick: function() { vnode.state.error = '' },
2019-09-13 13:33:10 +00:00
}, this.error),
m(FileUpload, {
2019-09-14 19:03:38 +00:00
onupload: this.mediaUploaded.bind(this, 'banner'),
2019-09-13 13:33:10 +00:00
onerror: function(e) { vnode.state.error = e },
2019-09-14 19:03:38 +00:00
ondelete: this.mediaRemoved.bind(this, 'banner'),
2019-09-13 13:33:10 +00:00
media: this.article && this.article.banner,
}),
m(FileUpload, {
class: 'cover',
useimg: true,
2019-09-14 19:03:38 +00:00
onupload: this.mediaUploaded.bind(this, 'media'),
ondelete: this.mediaRemoved.bind(this, 'media'),
2019-09-13 13:33:10 +00:00
onerror: function(e) { vnode.state.error = e },
media: this.article && this.article.media,
}),
m('form.editarticle.content', {
onsubmit: this.save.bind(this, vnode),
}, [
m('label', 'Parent'),
m('select', {
onchange: this.updateParent.bind(this),
}, parents.map(function(item) { return m('option', { value: item.id || -1, selected: item.id === vnode.state.article.parent_id }, item.name) })),
m('label', 'Name'),
m('input', {
type: 'text',
value: this.article.name,
oninput: this.updateValue.bind(this, 'name'),
}),
m('label', 'Description'),
(
this.loadedFroala ?
m('div', {
oncreate: function(div) {
vnode.state.froala = new FroalaEditor(div.dom, EditArticle.getFroalaOptions(), function() {
vnode.state.froala.html.set(vnode.state.article.description)
})
},
})
: null
),
m('label', 'Path'),
m('input', {
type: 'text',
value: this.article.path,
oninput: this.updateValue.bind(this, 'path'),
}),
m('div.loading-spinner', { hidden: this.loadedFroala }),
m('input', {
type: 'submit',
value: 'Save',
}),
]),
2019-09-14 19:03:38 +00:00
this.article.files.length
? m('files', [
m('h4', 'Files'),
this.article.files.map(function(item) { return m(Fileinfo, { file: item }) }),
])
: null,
this.article.id
? m('div.fileupload', [
'Add file',
m('input', {
accept: '*',
type: 'file',
onchange: this.uploadFile.bind(this, vnode),
}),
(vnode.state.loadingFile ? m('div.loading-spinner') : null),
])
: null,
2019-09-13 13:33:10 +00:00
]),
])
)
},
}
module.exports = EditArticle