const m = require('mithril') const Authentication = require('./authentication') const api = require('./api') const Input = require('./input') const lang = require('./lang') const videos = require('./videos') const Upload = { oninit: function(vnode) { Authentication.requiresLogin() this.error = '' let d = new Date() d.setDate(d.getDate() - d.getDay()) d.setHours(11) d.setMinutes(0) d.setSeconds(0) d.setMilliseconds(0) this.cacheVideo = null this.cacheImage = null this.uploading = null this.form = { title: 'Sunnudagssamkoma', date: d, file: null, banner: null, metadata: { speaker: '', }, } }, uploadvideo: 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.form.file) this.error = lang.upload_missing_file // Video file missing if (!this.form.banner) this.error = lang.upload_missing_banner // Video file missing if (this.error) return false api.sendRequest({ method: 'GET', url: '/api/auth/uploadToken', body: this.form, }) .then(res => { if (this.cacheImage?.file === this.form.banner) { return this.cacheImage } var data = new FormData() data.append('file', this.form.banner) data.append('preview', JSON.stringify({ "out": "base64", "format": "avif", "resize": { "width": 360, "height": 203, "fit": "cover", "withoutEnlargement": true, "kernel": "mitchell" }, "avif": { "quality": 50, "effort": 9 } })) data.append('medium', JSON.stringify({ "format": "avif", "resize": { "width": 1280, "height": 720, "fit": "cover", "withoutEnlargement": true, "kernel": "mitchell" }, "avif": { "quality": 75, "effort": 3 } })) return api.sendRequest({ method: 'POST', url: res.resize + '?token=' + res.token, body: data, }) .then(banner => { this.cacheImage = { file: this.form.banner, medium: { filename: banner.medium.filename, path: banner.medium.path, }, preview: { base64: banner.preview.base64, }, } api.sendRequest({ method: 'DELETE', url: res.resize.replace('resize', banner.filename) + '?token=' + res.token, }).catch(err => console.log(err)) return res }) }) .then(res => { if (this.cacheVideo?.file === this.form.file) { return this.cacheVideo } return api.uploadFileProgress({ url: res.path + '?token=' + res.token, }, this.form.file, (xhr, progress, perSecond) => { this.uploading = { progress, xhr, perSecond } m.redraw() }) }) .then(res => { this.cacheVideo = { file: this.form.file, filename: res.filename, path: res.path, } this.uploading = null return api.sendRequest({ method: 'PUT', url: '/api/auth/articles/0', 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: { filename: res.filename, path: res.path, type: this.form.file.type, size: this.form.file.size, }, banner: { filename: this.cacheImage.medium.filename, path: this.cacheImage.medium.path, type: 'image/avif', size: this.form.file.size, preview: { base64: this.cacheImage.preview.base64, }, }, }, }) }) .then(res => { console.log(res) videos.refreshTree() m.route.set('/browse') }) .catch((error) => { this.uploading = null if (!error) return this.error = lang.format(lang.upload_error, error.message) // Error while uploading: }) return false }, cancelUpload(e) { e.stopPropagation() this.uploading.xhr.abortRequest() this.uploading = null return false }, view: function(vnode) { return [ m('div.page.page-upload', [ m('div.modal', [ m('form', { onsubmit: this.uploadvideo.bind(this, vnode), }, [ m('h3', 'Upload new video'), this.error ? m('p.error', this.error) : null, 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(Input, { label: 'Video', type: 'file', accept: '.webm', utility: 'file', button: 'fa-video', form: this.form, formKey: 'file', }), m(Input, { label: 'Mynd', type: 'file', accept: 'image/*', utility: 'image', form: this.form, formKey: 'banner', }), m('p.separator', 'Optional'), m(Input, { label: 'Speaker', form: this.form.metadata, formKey: 'speaker', }), m('input.spinner', { hidden: api.loading, type: 'submit', value: 'Begin upload', }), api.loading ? m('div.loading-spinner') : null, this.uploading ? [ m('p', `${Math.floor(this.uploading.progress)}% (${this.uploading.perSecond}/s)`), m('.loading-bar', { style: `--progress: ${this.uploading.progress}%` }), m('button.button.button-alert', { onclick: this.cancelUpload.bind(this), }, 'Cancel upload'), ] : null, ]), ]), m('footer', lang.mformat( lang.unsplash, // Photo by X on Y m('a', { href: 'https://unsplash.com/@guzmanbarquin?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash', target: '_blank' }, 'Guzmán Barquín'), m('a', { href: 'https://unsplash.com/photos/sea-under-full-moon-Qd688l1yDOI?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash', target: '_blank' }, 'Unsplash'), )), ]), ] }, } module.exports = Upload