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 = {};
|
||||||
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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
Loading…
Reference in a new issue