Added rudimentary EEPROM file uploading support to the forum post editor.
This commit is contained in:
parent
e909b2ffda
commit
521a8fb0d1
4 changed files with 389 additions and 4 deletions
104
assets/css/misuzu/eeprom.css
Normal file
104
assets/css/misuzu/eeprom.css
Normal 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;
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
Misuzu.Forum.Editor = {};
|
||||
Misuzu.Forum.Editor.allowWindowClose = false;
|
||||
Misuzu.Forum.Editor.init = function() {
|
||||
var postingForm = $q('.js-forum-posting');
|
||||
const postingForm = $q('.js-forum-posting');
|
||||
if(!postingForm)
|
||||
return;
|
||||
|
||||
var postingButtons = postingForm.querySelector('.js-forum-posting-buttons'),
|
||||
const postingButtons = postingForm.querySelector('.js-forum-posting-buttons'),
|
||||
postingText = postingForm.querySelector('.js-forum-posting-text'),
|
||||
postingParser = postingForm.querySelector('.js-forum-posting-parser'),
|
||||
postingPreview = postingForm.querySelector('.js-forum-posting-preview'),
|
||||
|
@ -15,6 +15,277 @@ Misuzu.Forum.Editor.init = function() {
|
|||
markdownButtons = $q('.forum__post__actions--markdown'),
|
||||
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.
|
||||
postingButtons.firstElementChild.addEventListener('click', function() {
|
||||
Misuzu.Forum.Editor.allowWindowClose = true;
|
||||
|
|
|
@ -154,6 +154,10 @@ Template::set('globals', [
|
|||
'site_url' => $cfg->getValue('site.url', IConfig::T_STR),
|
||||
'site_twitter' => $cfg->getValue('social.twitter', 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);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{% set is_opening = not is_reply or posting_post.is_opening_post|default(false) %}
|
||||
|
||||
{% 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[mode]', posting_mode) }}
|
||||
{{ input_csrf() }}
|
||||
|
@ -43,7 +43,7 @@
|
|||
</div>
|
||||
{% 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__background"></div>
|
||||
<div class="forum__post__info__content">
|
||||
|
@ -176,4 +176,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% if globals.eeprom.path is not empty %}
|
||||
<script type="text/javascript">
|
||||
const peepPath = '{{ globals.eeprom.path }}', peepApp = '{{ globals.eeprom.app }}';
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in a new issue