From 8734baf85e5a6018067001739a54d2cd87b6fb4d Mon Sep 17 00:00:00 2001 From: Are0h Date: Wed, 18 May 2022 16:41:25 -0700 Subject: [PATCH] Fix for #76, editing upload que Whew it took a bit but now the upload que on the page edit page is editable. You can add and remove files as needed without having to add all your files at once, which us how it previously worked. Still needs to be tested a bit but the plumbing is up and running. Also removed a stray php format config as it is no longer needed. --- brain/data/Render.php | 7 +- brain/views/dash/page-edit.twig | 42 ++++++-- phpcs.xml | 156 ---------------------------- public/assets/css/dash.css | 9 ++ public/assets/scripts/Start.js | 166 ++++++++++++++++++----------- src/com/actions/PageActions.js | 2 +- src/com/ui/FileManager.js | 178 ++++++++++++++++++++++---------- src/styles/main/_posts.scss | 9 ++ 8 files changed, 282 insertions(+), 287 deletions(-) delete mode 100644 phpcs.xml diff --git a/brain/data/Render.php b/brain/data/Render.php index 77bc2fd..d0be3a6 100644 --- a/brain/data/Render.php +++ b/brain/data/Render.php @@ -10,13 +10,9 @@ use function _\find; class Render { public $loader; - public $twig; - public $pageInfo; - public $menu; - public $background; public function __construct() @@ -37,7 +33,8 @@ class Render 'baseURL' => $settings['global']['base_url'], ]; //move global theme image assets to public folder - foreach (new \DirectoryIterator('../content/themes/' . $this->theme . '/assets/images/global/') as $file + foreach ( + new \DirectoryIterator('../content/themes/' . $this->theme . '/assets/images/global/') as $file ) { if ($file->isDot()) { continue; diff --git a/brain/views/dash/page-edit.twig b/brain/views/dash/page-edit.twig index 4ed0428..2477ed9 100644 --- a/brain/views/dash/page-edit.twig +++ b/brain/views/dash/page-edit.twig @@ -36,7 +36,7 @@ {% endblock %} {% block stylesheets %} - + {% endblock %} {% block mainContent %} @@ -66,18 +66,30 @@
{% if media|length > 1 %} {% for item in media %} + {% set fileName = item.file|split('/') %} {% if item.type == "mp4" %} -
+ +
+ +
{% else %} -
+
+ +
{% endif %} {% endfor %} {% else %} {% if media[0] != '' %} + {% set fileName = media[0].file|split('/') %} {% if media[0].type == "mp4" %} -
+
+ +
+ {% else %} -
+
+ +
{% endif %} {% else %} {% endif %} @@ -88,18 +100,28 @@
{% if files|length > 1 %} {% for item in files %} + {% set fileName = item.file|split('/') %} {% if item.type == "mp3" %} -
+
+ +
{% else %} -
+
+ +
{% endif %} {% endfor %} {% else %} {% if files[0] != '' %} + {% set fileName = files[0].file|split('/') %} {% if files[0].type == "mp3" %} -
+
+ +
{% else %} -
+
+ +
{% endif %} {% else %} @@ -172,5 +194,5 @@ {% endblock %} {% block javascripts %} - + {% endblock %} diff --git a/phpcs.xml b/phpcs.xml deleted file mode 100644 index 15ba3a9..0000000 --- a/phpcs.xml +++ /dev/null @@ -1,156 +0,0 @@ - - - The coding standard for PHP_CodeSniffer itself. - - autoload.php - bin - scripts - src - tests - - */src/Standards/*/Tests/*\.(inc|css|js)$ - */tests/Core/*/*\.(inc|css|js)$ - - - - - - - - - error - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - error - - - - - error - - - - - tests/bootstrap\.php - - - - - tests/Core/Tokenizer/StableCommentWhitespaceWinTest\.php - - - \ No newline at end of file diff --git a/public/assets/css/dash.css b/public/assets/css/dash.css index 9241abc..a5ebd7d 100644 --- a/public/assets/css/dash.css +++ b/public/assets/css/dash.css @@ -3409,6 +3409,15 @@ select { #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list { padding: 10px 0 0; } +#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-images-list button.media-remove, +#post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list button.media-remove { + height: 35px; + width: 30px; + background: #f64747; + color: #efebe3; + float: right; + margin: 5px 5px 0; +} #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-images-list .img-item, #post-edit-index #post-edit-index-wrapper #post-feature #page-file-manager #page-file-wrapper #page-files-list .img-item { height: 150px; diff --git a/public/assets/scripts/Start.js b/public/assets/scripts/Start.js index cf103da..c30e136 100644 --- a/public/assets/scripts/Start.js +++ b/public/assets/scripts/Start.js @@ -1810,7 +1810,7 @@ class PostActions { if (files.length > 0 && files != null) for(var i = 0; i < files.length; i++){ var file = files[i]; if (file.type.match('image.*') || file.type.match('video.mp4') || file.type.match('audio.mpeg') || file.type.match('application.pdf') || file.type.match('text.plain') || file.type.match('text.rtf')) pageInfo.append('page_files[]', file, file.name); - else reject('Not an image file'); + else reject('Not an image file: ' + file.type); } else //check to see if image exists if (document.getElementById('featured-image')) { @@ -5424,6 +5424,20 @@ class FileManager { this.files = []; this.sortedFiles = []; this.storage = []; + this.mediaSort = _sortablejsDefault.default.create(this.imageList, { + animation: 150, + onUpdate: ()=>{ + notify.alert('REINDEXING MEDIA', null); + this.updateFiles(); + } + }); + this.fileSort = _sortablejsDefault.default.create(this.fileList, { + animation: 150, + onUpdate: ()=>{ + notify.alert('REINDEXING FILES', null); + this.updateFiles(); + } + }); this.start(); } // methods @@ -5435,38 +5449,9 @@ class FileManager { , false); this.input.addEventListener('change', (e)=>this.handleFileActions(e) , false); - _sortablejsDefault.default.create(this.imageList, { - onUpdate: (e)=>{ - notify.alert('REINDEXING FILES', null); - let currentFiles = []; //store current list - let items = e.target.children; - for(let index = 0; index < items.length; index++){ - var item = items[index]; - let url = ''; - if (item.className == 'img-item') url = item.style.backgroundImage.slice(4, -1).replace(/"/g, ''); - else url = item.getAttribute('data-source'); - currentFiles.push({ - earl: url - }); - } - this.reindexFiles(currentFiles, 0); - } - }); - _sortablejsDefault.default.create(this.fileList, { - onUpdate: (e)=>{ - notify.alert('REINDEXING FILES', null); - let currentFiles = []; - let items = e.target.children; - for(let index = 0; index < items.length; index++){ - var item = items[index]; - let url = item.getAttribute('data-source'); - currentFiles.push({ - earl: url - }); - } - this.reindexFiles(currentFiles, 0); - } - }); + var removeMedia = document.querySelectorAll('.media-remove'); + for(var i = 0, length = removeMedia.length; i < length; i++)removeMedia[i].addEventListener('click', (e)=>this.removeFile(e, 'media') + , false); } getFiles() { return this.files; @@ -5475,28 +5460,37 @@ class FileManager { let count = sortOrder.length; if (step == 0) this.files = []; var utils = new _dataUtilsDefault.default(); - var path = sortOrder[step].earl.split('/'); utils.imgLoad(sortOrder[step].earl).then((blob)=>{ var fresh = new File([ blob - ], path[6], { + ], sortOrder[step].fileName, { type: blob.type }); + console.log('FRESH', fresh); this.files.push(fresh); - if (this.files.length <= count - 1) this.reindexFiles(sortOrder, ++step); - else notify.alert('FILES READY TO UPLOAD', true); + var limit = count - 1; + if (this.files.length <= limit) { + step = step + 1; + this.reindexFiles(sortOrder, step); + } else notify.alert('FILES READY TO UPLOAD', true); }); } sortFiles(files) { - var self = this; - this.files = []; //clear files array - this.imageList.innerHTML = ''; - this.fileList.innerHTML = ''; + var self = this; //this.files = []; //clear files array + //this.imageList.innerHTML = ''; + //this.fileList.innerHTML = ''; for(var i = 0, file1; file1 = files[i]; i++){ var reader = new FileReader(); // Closure to capture the file information reader.onload = ((theFile)=>{ return function(f) { - // sort files + //create remove button object + var remove = document.createElement('button'); + remove.className = 'media-remove'; + remove.innerHTML = 'X'; + remove.addEventListener('click', (e)=>self.removeFile(e, 'media') + , false); //get counts for lists + var mediaCount = self.imageList.childNodes.length; + var fileCount = self.fileList.childNodes.length; // sort files switch(theFile.type){ case 'image/jpg': case 'image/jpeg': @@ -5504,13 +5498,12 @@ class FileManager { case 'image/svg': case 'image/png': //create element and add to list - var image = document.createElement('img'); - image.src = f.target.result; - image.title = escape(theFile.name); + //var image = document.createElement('img'); + //image.src = f.target.result; + //image.title = escape(theFile.name); var span = document.createElement('div'); span.style.background = 'url(' + f.target.result + ') no-repeat center center / cover'; - span.className = 'img-item'; - image.setAttribute('id', i); + span.className = 'img-item'; //image.setAttribute('id', i); self.storage.push([ { id: 'page_image' + i, @@ -5519,22 +5512,33 @@ class FileManager { name: escape(theFile.name) } ]); - self.imageList.appendChild(span); //add to files list - self.files.push(theFile); + if (mediaCount < 0) mediaCount = 0; + span.setAttribute('id', mediaCount); + remove.setAttribute('id', mediaCount); + span.setAttribute('data-file-name', theFile.name); + span.appendChild(remove); + self.imageList.appendChild(span); break; case 'video/mp4': var video = document.createElement('div'); video.className = 'video-item'; video.setAttribute('data-source', f.target.result); + if (mediaCount < 0) mediaCount = 0; + video.setAttribute('id', mediaCount); + remove.setAttribute('id', mediaCount); + video.setAttribute('data-file-name', theFile.name); + video.appendChild(remove); self.imageList.appendChild(video); - self.files.push(theFile); break; case 'audio/mpeg': var sound = document.createElement('div'); sound.className = 'audio-item'; sound.setAttribute('data-source', f.target.result); + sound.setAttribute('id', fileCount); + remove.setAttribute('id', fileCount); + sound.setAttribute('data-file-name', theFile.name); + sound.appendChild(remove); self.fileList.appendChild(sound); - self.files.push(theFile); break; case 'application/pdf': case 'text/plain': @@ -5542,31 +5546,75 @@ class FileManager { var file = document.createElement('div'); file.className = 'file-item'; file.setAttribute('data-source', f.target.result); + file.setAttribute('id', fileCount); + remove.setAttribute('id', fileCount); + file.setAttribute('data-file-name', theFile.name); + file.appendChild(remove); self.fileList.appendChild(file); - self.files.push(theFile); break; } }; })(file1); // Read in the image file as a data URL. reader.readAsDataURL(file1); - } + } //give the script a beat to add the child nodes, then update it all + setTimeout(()=>{ + self.updateFiles(); + }, 50); } // event handlers //-------------------------- - handleFileActions(e) { - e.stopPropagation(); - e.preventDefault(); + updateFiles() { + let currentFiles = []; //store current list + let items = []; //get files from media and files list + for(let index = 0; index < this.imageList.childNodes.length; index++)items.push(this.imageList.childNodes[index]); + for(let index1 = 0; index1 < this.fileList.childNodes.length; index1++)items.push(this.fileList.childNodes[index1]); + for(let index2 = 0; index2 < items.length; index2++){ + var item = items[index2]; + let url = ''; + if (item.className == 'img-item') url = item.style.backgroundImage.slice(4, -1).replace(/"/g, ''); + else url = item.getAttribute('data-source'); + currentFiles.push({ + earl: url, + fileName: item.getAttribute('data-file-name') + }); + } + this.reindexFiles(currentFiles, 0); + } + removeFile(e) { + var list = []; + switch(e.target.parentNode.className){ + case 'img-item': + case 'video-item': + list = this.imageList; + break; + case 'audio-item': + case 'file-item': + list = this.fileList; + break; + } + for(let index = 0; index < list.childNodes.length; index++){ + let media = list.childNodes[index]; + if (media.id == e.target.id) { + list.removeChild(media); + notify.alert('REINDEXING MEDIA', null); + this.updateFiles(); + } + } + } + handleFileActions(e1) { + e1.stopPropagation(); + e1.preventDefault(); let self = this; let rawList = []; let sortedList = []; let notOnTheList = []; - switch(e.type){ + switch(e1.type){ case 'dragover': - e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. + e1.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. break; case 'change': case 'drop': - e.type == 'drop' ? rawList = e.dataTransfer.files : rawList = e.target.files; + e1.type == 'drop' ? rawList = e1.dataTransfer.files : rawList = e1.target.files; for(var i = 0, f; f = rawList[i]; i++)// check witch files are cool to upload if (this.accetableFiles.includes(f.type)) sortedList.push(f); else notOnTheList.push(f); diff --git a/src/com/actions/PageActions.js b/src/com/actions/PageActions.js index b128ef4..9399a5e 100644 --- a/src/com/actions/PageActions.js +++ b/src/com/actions/PageActions.js @@ -71,7 +71,7 @@ export default class PostActions { ) { pageInfo.append('page_files[]', file, file.name); } else { - reject('Not an image file'); + reject('Not an image file: ' + file.type); } } } else { diff --git a/src/com/ui/FileManager.js b/src/com/ui/FileManager.js index e6631ac..b0917a4 100644 --- a/src/com/ui/FileManager.js +++ b/src/com/ui/FileManager.js @@ -26,6 +26,20 @@ export default class FileManager { this.files = []; this.sortedFiles = []; this.storage = []; + this.mediaSort = Sortable.create(this.imageList, { + animation: 150, + onUpdate: () => { + notify.alert('REINDEXING MEDIA', null); + this.updateFiles(); + } + }); + this.fileSort = Sortable.create(this.fileList, { + animation: 150, + onUpdate: () => { + notify.alert('REINDEXING FILES', null); + this.updateFiles(); + } + }); this.start(); } //-------------------------- @@ -35,46 +49,15 @@ export default class FileManager { this.upload.addEventListener('dragover', e => this.handleFileActions(e), false); this.upload.addEventListener('drop', e => this.handleFileActions(e), false); this.input.addEventListener('change', e => this.handleFileActions(e), false); - - Sortable.create(this.imageList, { - onUpdate: e => { - notify.alert('REINDEXING FILES', null); - let currentFiles = []; //store current list - let items = e.target.children; - for (let index = 0; index < items.length; index++) { - var item = items[index]; - let url = ''; - if (item.className == 'img-item') { - url = item.style.backgroundImage.slice(4, -1).replace(/"/g, ''); - } else { - url = item.getAttribute('data-source'); - } - - currentFiles.push({ - earl: url - }); - } - this.reindexFiles(currentFiles, 0); - } - }); - - Sortable.create(this.fileList, { - onUpdate: e => { - notify.alert('REINDEXING FILES', null); - let currentFiles = []; - let items = e.target.children; - for (let index = 0; index < items.length; index++) { - var item = items[index]; - let url = item.getAttribute('data-source'); - currentFiles.push({ - earl: url - }); - } - this.reindexFiles(currentFiles, 0); - } - }); + var removeMedia = document.querySelectorAll('.media-remove'); + for (var i = 0, length = removeMedia.length; i < length; i++) { + removeMedia[i].addEventListener( + 'click', + e => this.removeFile(e, 'media'), + false + ); + } } - getFiles() { return this.files; } @@ -83,12 +66,14 @@ export default class FileManager { let count = sortOrder.length; if (step == 0) this.files = []; var utils = new DataUtils(); - var path = sortOrder[step].earl.split('/'); utils.imgLoad(sortOrder[step].earl).then(blob => { - var fresh = new File([blob], path[6], { type: blob.type }); + var fresh = new File([blob], sortOrder[step].fileName, { type: blob.type }); + console.log('FRESH', fresh); this.files.push(fresh); - if (this.files.length <= count - 1) { - this.reindexFiles(sortOrder, ++step); + var limit = count - 1; + if (this.files.length <= limit) { + step = step + 1; + this.reindexFiles(sortOrder, step); } else { notify.alert('FILES READY TO UPLOAD', true); } @@ -97,15 +82,27 @@ export default class FileManager { sortFiles(files) { var self = this; - this.files = []; //clear files array - this.imageList.innerHTML = ''; - this.fileList.innerHTML = ''; + //this.files = []; //clear files array + //this.imageList.innerHTML = ''; + //this.fileList.innerHTML = ''; for (var i = 0, file; (file = files[i]); i++) { var reader = new FileReader(); // Closure to capture the file information - reader.onload = (theFile => { return function (f) { + //create remove button object + var remove = document.createElement('button'); + remove.className = 'media-remove'; + remove.innerHTML = 'X'; + remove.addEventListener( + 'click', + e => self.removeFile(e, 'media'), + false + ); + //get counts for lists + var mediaCount = self.imageList.childNodes.length; + var fileCount = self.fileList.childNodes.length; + // sort files switch (theFile.type) { case 'image/jpg': @@ -114,16 +111,17 @@ export default class FileManager { case 'image/svg': case 'image/png': //create element and add to list - var image = document.createElement('img'); - image.src = f.target.result; - image.title = escape(theFile.name); + //var image = document.createElement('img'); + //image.src = f.target.result; + //image.title = escape(theFile.name); var span = document.createElement('div'); span.style.background = 'url(' + f.target.result + ') no-repeat center center / cover'; span.className = 'img-item'; - image.setAttribute('id', i); + + //image.setAttribute('id', i); self.storage.push([ { id: 'page_image' + i, @@ -132,24 +130,34 @@ export default class FileManager { name: escape(theFile.name) } ]); + if (mediaCount < 0) mediaCount = 0; + span.setAttribute('id', mediaCount); + remove.setAttribute('id', mediaCount); + span.setAttribute('data-file-name', theFile.name); + span.appendChild(remove); self.imageList.appendChild(span); - //add to files list - self.files.push(theFile); break; case 'video/mp4': var video = document.createElement('div'); video.className = 'video-item'; video.setAttribute('data-source', f.target.result); + if (mediaCount < 0) mediaCount = 0; + video.setAttribute('id', mediaCount); + remove.setAttribute('id', mediaCount); + video.setAttribute('data-file-name', theFile.name); + video.appendChild(remove); self.imageList.appendChild(video); - self.files.push(theFile); break; case 'audio/mpeg': var sound = document.createElement('div'); sound.className = 'audio-item'; sound.setAttribute('data-source', f.target.result); + sound.setAttribute('id', fileCount); + remove.setAttribute('id', fileCount); + sound.setAttribute('data-file-name', theFile.name); + sound.appendChild(remove); self.fileList.appendChild(sound); - self.files.push(theFile); break; case 'application/pdf': case 'text/plain': @@ -157,8 +165,11 @@ export default class FileManager { var file = document.createElement('div'); file.className = 'file-item'; file.setAttribute('data-source', f.target.result); + file.setAttribute('id', fileCount); + remove.setAttribute('id', fileCount); + file.setAttribute('data-file-name', theFile.name); + file.appendChild(remove); self.fileList.appendChild(file); - self.files.push(theFile); break; } }; @@ -166,11 +177,66 @@ export default class FileManager { // Read in the image file as a data URL. reader.readAsDataURL(file); } + //give the script a beat to add the child nodes, then update it all + setTimeout(() => { + self.updateFiles(); + }, 50); } //-------------------------- // event handlers //-------------------------- + updateFiles() { + let currentFiles = []; //store current list + let items = []; + //get files from media and files list + for (let index = 0; index < this.imageList.childNodes.length; index++) { + items.push(this.imageList.childNodes[index]); + } + + for (let index = 0; index < this.fileList.childNodes.length; index++) { + items.push(this.fileList.childNodes[index]); + } + + for (let index = 0; index < items.length; index++) { + var item = items[index]; + let url = ''; + if (item.className == 'img-item') { + url = item.style.backgroundImage.slice(4, -1).replace(/"/g, ''); + } else { + url = item.getAttribute('data-source'); + } + currentFiles.push({ + earl: url, + fileName: item.getAttribute('data-file-name') + }); + } + this.reindexFiles(currentFiles, 0); + } + + removeFile(e) { + var list = []; + switch (e.target.parentNode.className) { + case 'img-item': + case 'video-item': + list = this.imageList; + + break; + case 'audio-item': + case 'file-item': + list = this.fileList; + break; + } + for (let index = 0; index < list.childNodes.length; index++) { + let media = list.childNodes[index]; + if (media.id == e.target.id) { + list.removeChild(media); + notify.alert('REINDEXING MEDIA', null); + this.updateFiles(); + } + } + } + handleFileActions(e) { e.stopPropagation(); e.preventDefault(); diff --git a/src/styles/main/_posts.scss b/src/styles/main/_posts.scss index 92666e0..16c15d8 100644 --- a/src/styles/main/_posts.scss +++ b/src/styles/main/_posts.scss @@ -393,6 +393,15 @@ #page-files-list { padding: 10px 0 0; + button.media-remove { + height: 35px; + width: 30px; + background: $event-lame; + color: $white; + float: right; + margin: 5px 5px 0; + } + .img-item { height: 150px; width: 23.8%;