Added rudimentary EEPROM file uploading support to the forum post editor.

This commit is contained in:
flash 2023-03-09 21:05:37 +00:00
parent e909b2ffda
commit 521a8fb0d1
4 changed files with 389 additions and 4 deletions

View file

@ -0,0 +1,104 @@
.eeprom-widget {
background-color: var(--container-colour);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
text-shadow: 0 1px 4px #000;
display: flex;
min-height: 50px;
}
.eeprom-widget-form {
display: flex;
text-align: center;
justify-content: center;
align-items: center;
flex: 0 0 auto;
min-width: 154px; /* same width as sidebar */
background-color: #aaa1;
transition: background-color .2s;
}
.eeprom-widget-form-input {
display: none;
visibility: hidden;
}
.eeprom-widget-form-text {
font-size: 1.4em;
line-height: 1.5em;
}
.eeprom-widget-form:focus,
.eeprom-widget-form:hover {
background-color: #fff1;
}
.eeprom-widget-form:active {
background-color: #ccc1;
}
.eeprom-widget-history {
overflow-y: auto;
scrollbar-width: thin;
}
.eeprom-widget-history-items {
display: flex;
padding: 0 3px;
}
.eeprom-widget-file {
margin: 4px 1px;
padding-top: 2px; /* adjust for the progress bar */
border: 1px solid var(--accent-colour);
border-radius: 2px;
overflow: hidden;
width: 200px;
flex: 0 0 auto;
}
.eeprom-widget-file-fail {
--accent-color: #c00;
}
.eeprom-widget-file-info {
padding: 0 2px;
}
.eeprom-widget-file-name {
color: #fff;
text-decoration: none;
}
.eeprom-widget-file-name-value {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.eeprom-widget-file-name:hover,
.eeprom-widget-file-name:focus {
text-decoration: underline;
}
.eeprom-widget-file-progress {
font-size: .9em;
line-height: 1.4em;
text-align: right;
padding: 0 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.eeprom-widget-file-progress a {
color: var(--accent-colour);
text-decoration: none;
}
.eeprom-widget-file-progress a:hover,
.eeprom-widget-file-progress a:focus {
text-decoration: underline;
}
.eeprom-widget-file-bar {
width: 100%;
height: 2px;
display: flex;
justify-content: flex-start;
align-items: flex-end;
}
.eeprom-widget-file-bar-fill {
width: 0%;
height: 2px;
background-color: var(--accent-colour);
transition: width .1s, height .1s;
}
.eeprom-widget-file-done .eeprom-widget-file-bar-fill {
height: 0;
}

View file

@ -1,11 +1,11 @@
Misuzu.Forum.Editor = {}; Misuzu.Forum.Editor = {};
Misuzu.Forum.Editor.allowWindowClose = false; Misuzu.Forum.Editor.allowWindowClose = false;
Misuzu.Forum.Editor.init = function() { Misuzu.Forum.Editor.init = function() {
var postingForm = $q('.js-forum-posting'); const postingForm = $q('.js-forum-posting');
if(!postingForm) if(!postingForm)
return; return;
var postingButtons = postingForm.querySelector('.js-forum-posting-buttons'), const postingButtons = postingForm.querySelector('.js-forum-posting-buttons'),
postingText = postingForm.querySelector('.js-forum-posting-text'), postingText = postingForm.querySelector('.js-forum-posting-text'),
postingParser = postingForm.querySelector('.js-forum-posting-parser'), postingParser = postingForm.querySelector('.js-forum-posting-parser'),
postingPreview = postingForm.querySelector('.js-forum-posting-preview'), postingPreview = postingForm.querySelector('.js-forum-posting-preview'),
@ -15,6 +15,277 @@ Misuzu.Forum.Editor.init = function() {
markdownButtons = $q('.forum__post__actions--markdown'), markdownButtons = $q('.forum__post__actions--markdown'),
markupButtons = $qa('.forum__post__action--tag'); markupButtons = $qa('.forum__post__action--tag');
// Initialise EEPROM, code sucks ass but it's getting nuked soon again anyway
if(typeof peepPath === 'string')
document.body.appendChild($e({
tag: 'script',
attrs: {
src: peepPath + '/eeprom.js',
charset: 'utf-8',
type: 'text/javascript',
onload: function() {
const eepromClient = new EEPROM(peepApp, peepPath + '/uploads', '');
const eepromHistory = $e({
attrs: {
className: 'eeprom-widget-history-items',
},
});
const eepromHandleFileUpload = function(file) {
const uploadElemNameValue = $e({
attrs: {
className: 'eeprom-widget-file-name-value',
title: file.name,
},
child: file.name,
});
const uploadElemName = $e({
tag: 'a',
attrs: {
className: 'eeprom-widget-file-name',
target: '_blank',
},
child: uploadElemNameValue,
});
const uploadElemProgressText = $e({
attrs: {
className: 'eeprom-widget-file-progress',
},
child: 'Please wait...',
});
const uploadElemProgressBarValue = $e({
attrs: {
className: 'eeprom-widget-file-bar-fill',
style: {
width: '0%',
},
},
});
const uploadElem = $e({
attrs: {
className: 'eeprom-widget-file',
},
child: [
{
attrs: {
className: 'eeprom-widget-file-info',
},
child: [
uploadElemName,
uploadElemProgressText,
],
},
{
attrs: {
className: 'eeprom-widget-file-bar',
},
child: uploadElemProgressBarValue,
},
],
});
if(eepromHistory.children.length > 0)
$ib(eepromHistory.firstChild, uploadElem);
else
eepromHistory.appendChild(uploadElem);
const explodeUploadElem = function() {
$r(uploadElem);
};
const uploadTask = eepromClient.createUpload(file);
uploadTask.onProgress = function(progressInfo) {
const progressValue = progressInfo.progress.toString() + '%';
uploadElemProgressBarValue.style.width = progressValue;
uploadElemProgressText.textContent = progressValue + ' (' + (progressInfo.total - progressInfo.loaded).toString() + ' bytes remaining)';
};
uploadTask.onFailure = function(errorInfo) {
if(!errorInfo.userAborted) {
let errorText = 'Was unable to upload file.';
switch(errorInfo.error) {
case EEPROM.ERR_INVALID:
errorText = 'Upload request was invalid.';
break;
case EEPROM.ERR_AUTH:
errorText = 'Upload authentication failed, refresh and try again.';
break;
case EEPROM.ERR_ACCESS:
errorText = 'You\'re not allowed to upload files.';
break;
case EEPROM.ERR_GONE:
errorText = 'Upload client has a configuration error or the server is gone.';
break;
case EEPROM.ERR_DMCA:
errorText = 'This file has been uploaded before and was removed for copyright reasons, you cannot upload this file.';
break;
case EEPROM.ERR_SERVER:
errorText = 'Upload server returned a critical error, try again later.';
break;
case EEPROM.ERR_SIZE:
if(errorInfo.maxSize < 1)
errorText = 'Selected file is too large.';
else {
const _t = ['bytes', 'KB', 'MB', 'GB', 'TB'],
_i = parseInt(Math.floor(Math.log(errorInfo.maxSize) / Math.log(1024))),
_s = Math.round(errorInfo.maxSize / Math.pow(1024, _i), 2);
errorText = 'Upload may not be larger than %1 %2.'.replace('%1', _s).replace('%2', _t[_i]);
}
break;
}
uploadElem.classList.add('eeprom-widget-file-fail');
uploadElemProgressText.textContent = errorText;
Misuzu.showMessageBox(errorText, 'Upload Error');
}
};
uploadTask.onComplete = function(fileInfo) {
const parserMode = parseInt(postingParser.value);
let insertText = location.protocol + fileInfo.url;
if(parserMode == 1) { // bbcode
if(fileInfo.isImage())
insertText = '[img]' + fileInfo.url + '[/img]';
else if(fileInfo.isAudio())
insertText = '[audio]' + fileInfo.url + '[/audio]';
else if(fileInfo.isVideo())
insertText = '[video]' + fileInfo.url + '[/video]';
} else if(parserMode == 2) { // markdown
if(fileInfo.isMedia())
insertText = '![](' + fileInfo.url + ')';
}
uploadElem.classList.add('eeprom-widget-file-done');
uploadElemName.href = fileInfo.url;
uploadElemProgressText.textContent = '';
const insertTheLinkIntoTheBoxEx2 = function() {
// should be more intelligent than just ploinking a space in front
$insertTags(postingText, ' ' + insertText, '');
postingText.value = postingText.value.trim();
};
uploadElemProgressText.appendChild($e({
tag: 'a',
attrs: {
href: 'javascript:void(0);',
onclick: function() { insertTheLinkIntoTheBoxEx2(); },
},
child: 'Insert',
}));
uploadElemProgressText.appendChild($t(' '));
uploadElemProgressText.appendChild($e({
tag: 'a',
attrs: {
href: 'javascript:void(0);',
onclick: function() {
eepromClient.deleteUpload(fileInfo).start();
explodeUploadElem();
},
},
child: 'Delete',
}));
insertTheLinkIntoTheBoxEx2();
};
uploadTask.start();
};
const eepromFormInput = $e({
tag: 'input',
attrs: {
type: 'file',
multiple: 'multiple',
className: 'eeprom-widget-form-input',
onchange: function(ev) {
const files = this.files;
for(const file of files)
eepromHandleFileUpload(file);
this.value = '';
},
},
});
const eepromForm = $e({
tag: 'label',
attrs: {
className: 'eeprom-widget-form',
},
child: [
eepromFormInput,
{
attrs: {
className: 'eeprom-widget-form-text',
},
child: 'Select Files...',
}
],
});
const eepromWidget = $e({
attrs: {
className: 'eeprom-widget',
},
child: [
eepromForm,
{
attrs: {
className: 'eeprom-widget-history',
},
child: eepromHistory,
},
],
});
postingForm.appendChild(eepromWidget);
postingText.addEventListener('paste', function(ev) {
if(ev.clipboardData && ev.clipboardData.files.length > 0) {
ev.preventDefault();
const files = ev.clipboardData.files;
for(const file of files)
eepromHandleFileUpload(file);
}
});
document.body.addEventListener('dragenter', function(ev) {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('dragover', function(ev) {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('dragleave', function(ev) {
ev.preventDefault();
ev.stopPropagation();
});
document.body.addEventListener('drop', function(ev) {
ev.preventDefault();
ev.stopPropagation();
if(ev.dataTransfer && ev.dataTransfer.files.length > 0) {
const files = ev.dataTransfer.files;
for(const file of files)
eepromHandleFileUpload(file);
}
});
},
onerror: function(ev) {
console.error('Failed to initialise EEPROM: ', ev);
},
},
}));
// hack: don't prompt user when hitting submit, really need to make this not stupid. // hack: don't prompt user when hitting submit, really need to make this not stupid.
postingButtons.firstElementChild.addEventListener('click', function() { postingButtons.firstElementChild.addEventListener('click', function() {
Misuzu.Forum.Editor.allowWindowClose = true; Misuzu.Forum.Editor.allowWindowClose = true;

View file

@ -154,6 +154,10 @@ Template::set('globals', [
'site_url' => $cfg->getValue('site.url', IConfig::T_STR), 'site_url' => $cfg->getValue('site.url', IConfig::T_STR),
'site_twitter' => $cfg->getValue('social.twitter', IConfig::T_STR), 'site_twitter' => $cfg->getValue('social.twitter', IConfig::T_STR),
'site_chat' => $cfg->getValue('sockChat.chatPath.normal', IConfig::T_STR), 'site_chat' => $cfg->getValue('sockChat.chatPath.normal', IConfig::T_STR),
'eeprom' => [
'path' => $cfg->getValue('eeprom.path', IConfig::T_STR),
'app' => $cfg->getValue('eeprom.app', IConfig::T_STR),
],
]); ]);
Template::addPath(MSZ_TEMPLATES); Template::addPath(MSZ_TEMPLATES);

View file

@ -8,7 +8,7 @@
{% set is_opening = not is_reply or posting_post.is_opening_post|default(false) %} {% set is_opening = not is_reply or posting_post.is_opening_post|default(false) %}
{% block content %} {% block content %}
<form method="post" action="{{ url('forum-' ~ (is_reply ? 'post' : 'topic') ~ '-create') }}"> <form method="post" action="{{ url('forum-' ~ (is_reply ? 'post' : 'topic') ~ '-create') }}" class="js-forum-posting">
{{ input_hidden('post[' ~ (is_reply ? 'topic' : 'forum') ~ ']', is_reply ? posting_topic.topic_id : posting_forum.forum_id) }} {{ input_hidden('post[' ~ (is_reply ? 'topic' : 'forum') ~ ']', is_reply ? posting_topic.topic_id : posting_forum.forum_id) }}
{{ input_hidden('post[mode]', posting_mode) }} {{ input_hidden('post[mode]', posting_mode) }}
{{ input_csrf() }} {{ input_csrf() }}
@ -43,7 +43,7 @@
</div> </div>
{% endif %} {% endif %}
<div class="container forum__post js-forum-posting" style="{{ posting_post.poster_colour|default(current_user.colour)|html_colour('--accent-colour') }}"> <div class="container forum__post" style="{{ posting_post.poster_colour|default(current_user.colour)|html_colour('--accent-colour') }}">
<div class="forum__post__info"> <div class="forum__post__info">
<div class="forum__post__info__background"></div> <div class="forum__post__info__background"></div>
<div class="forum__post__info__content"> <div class="forum__post__info__content">
@ -176,4 +176,10 @@
</div> </div>
</div> </div>
</form> </form>
{% if globals.eeprom.path is not empty %}
<script type="text/javascript">
const peepPath = '{{ globals.eeprom.path }}', peepApp = '{{ globals.eeprom.app }}';
</script>
{% endif %}
{% endblock %} {% endblock %}