const m = require('mithril') const api = require('./api') const Authentication = require('./authentication') const Input = require('./input') const lang = require('./lang') const videos = require('./videos') const HoldButton = require('./holdbutton') const Article = { oninit: function(vnode) { this.error = '' this.path = '' this.data = null this.editing = false this.cacheImage = null this.form = { title: 'Sunnudagssamkoma', date: new Date(), banner: null, metadata: { speaker: '', }, } this.onbeforeupdate(vnode) }, onbeforeupdate: function(vnode) { let path = m.route.param('year').padStart(4, '0') + '-' + m.route.param('month').padStart(2, '0') + '-' + m.route.param('path') if (this.path === path) return this.fetchArticle(vnode, path) }, fetchArticle: function(vnode, path) { this.error = '' this.data = null this.path = path this.cacheImage = null this.editing = false api.sendRequest({ method: 'GET', url: '/api/articles/' + this.path, }) .then((result) => { this.data = result.article this.gotArticle(vnode) }, (err) => { this.error = err.message }) }, gotArticle: function(vnode) { if (!this.data) { return this.error = 'Article not found' } this.form.title = this.data.name this.form.date = new Date(this.data.publish_at) this.form.banner = this.data.banner_path this.form.metadata.speaker = this.data.content.speaker }, updatevideo: function(vnode, e) { this.error = '' if (!this.form.title) this.error = lang.upload_missing_title // Title is missing if (!this.form.date) this.error = lang.upload_missing_date // Date is missing if (this.error) return false let promise = Promise.resolve() if (Authentication.currentUser && (typeof(this.form.banner) !== 'string' && this.cacheImage?.file !== this.form.banner)) { promise = api.sendRequest({ method: 'GET', url: '/api/auth/uploadToken', }) .then(res => { return api.uploadBanner(this.form.banner, res) .then(imageData => { this.cacheImage = imageData if (this.data.banner_path) { api.sendRequest({ method: 'DELETE', url: res.delete + this.data.banner_path.slice(this.data.banner_path.lastIndexOf('/') + 1) + '?token=' + res.token, }).catch(err => console.error(err)) } return res }) }) } promise.then(() => { return api.sendRequest({ method: 'PUT', url: '/api/auth/articles/' + this.data.id, body: { name: this.form.title, page_id: 'null', path: this.form.date.toISOString().replace('T', '_').replace(/:/g, '').split('.')[0], content: JSON.stringify(this.form.metadata), publish_at: this.form.date, admin_id: Authentication.getTokenDecoded().user_id, is_featured: false, media: null, banner: this.cacheImage ? { filename: this.cacheImage.medium.filename, path: this.cacheImage.medium.path, type: 'image/avif', size: this.cacheImage.size, preview: { base64: this.cacheImage.preview.base64, }, } : null, }, }) }) .then(res => { this.fetchArticle(vnode, this.path) }) .catch((error) => { console.error(error) this.error = lang.format(lang.article_error, error.message) // Error while saving: }) return false }, deletevideo: function(vnode) { api.sendRequest({ method: 'GET', url: '/api/auth/uploadToken', body: this.form, }) .then(res => { return Promise.all([ this.data.banner_path ? api.sendRequest({ method: 'DELETE', url: res.delete + this.data.banner_path.slice(this.data.banner_path.lastIndexOf('/') + 1) + '?token=' + res.token, }).catch(err => console.error(err)) : Promise.resolve(), this.data.media_path ? api.sendRequest({ method: 'DELETE', url: res.delete + this.data.media_path.slice(this.data.media_path.lastIndexOf('/') + 1) + '?token=' + res.token, }).catch(err => console.error(err)) : Promise.resolve(), ]) }) .then(() => { return api.sendRequest({ method: 'DELETE', url: '/api/auth/articles/' + this.data.id, }) }) .then(res => { videos.removeArticle(this.data.id) m.route.set('/') }) .catch((error) => { if (!error) return this.error = lang.format(lang.delete_error, error.message) // Error while uploading: }) }, view: function(vnode) { return [ api.loading && !this.data ? m('div.loading-spinner') : null, this.data ? [ this.data.media_path ? [ m('.player', [ m('video', { crossorigin: '', controls: true, preload: 'none', poster: this.data.banner_path || '/assets/placeholder.avif', }, [ m('source', { src: this.data.media_path }) ]), ]), ] : null, this.editing ? m('form.article', { onsubmit: this.updatevideo.bind(this, vnode), }, [ m('div.form-row', [ m('div.form-columns', [ m(Input, { label: '', type: 'file', accept: 'image/*', utility: 'image', form: this.form, formKey: 'banner', }), ]), m('div.form-columns.article-name', [ m(Input, { label: 'Title', form: this.form, formKey: 'title', }), m(Input, { label: 'Date (dd.mm.yyyy)', type: 'text', utility: 'datetime', form: this.form, formKey: 'date', }), ]), ]), m('p.separator', 'Optional'), m(Input, { label: 'Speaker', form: this.form.metadata, formKey: 'speaker', }), this.error ? m('div.full-error', this.error) : null, m('div.row', [ m('input.spinner', { hidden: api.loading, type: 'submit', value: lang.edit, }), m('div.filler', { hidden: api.loading, }), api.loading ? m('div.loading-spinner') : null, m(HoldButton, { class: 'button spinner', onclick: () => this.deletevideo(vnode), hidden: api.loading, text: lang.delete, }), ]), ]) : m('div.article', [ m('h1', this.data.name), m('p', [ lang.printdate(this.form.date), ]), m('div.table', [ m('div.table-row', [ m('div.table-item', lang.article_speaker), m('div.table-item', this.data.content.speaker || '...'), ]), ]), Authentication.currentUser?.rank >= 10 ? m('button.button', { onclick: () => this.editing = true },lang.edit) : null, ]), ] : [ this.error ? m('div.full-error', this.error) : null, ], ] }, } module.exports = Article