diff --git a/README.md b/README.md index d23167d..27de432 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ new Vue({ - dynamically hide [files](https://github.com/ctf0/Laravel-Media-Manager/wiki/Hide-Files-With-Extension) - dynamically hide [folders](https://github.com/ctf0/Laravel-Media-Manager/wiki/Hide-Folders) - toggle between `random names` & `original names` for uploaded files -- download selected ***"including bulk selection"*** +- download selected ["including bulk selection"](https://github.com/ctf0/Laravel-Media-Manager/wiki/Download-Files-as-a-ZipFile) - directly copy selected file link - use manager [from modal with ease](https://github.com/ctf0/Laravel-Media-Manager/wiki/Use-The-Manager-From-A-Modal) - auto scroll to selected item when using (left/up, right/down, home, end) diff --git a/logs/v2.3.3.txt b/logs/v2.3.3.txt deleted file mode 100644 index 765351f..0000000 --- a/logs/v2.3.3.txt +++ /dev/null @@ -1,29 +0,0 @@ -# New - -- much better styling all over -- now selected file will be reselected when reopening the manager, same as with folders. -- for icons, we’ve moved to https://github.com/Justineo/vue-awesome instead of fw font -- add flip animation for numbers change. -- add extra button for pdf preview to open in new tab, same as images -- now you can preview text files as well -- new animation for search not found & new one for loading files as well -- item box is now bigger on mobile instead of the narrow lock on desktop. -- select last uploaded item after upload instead of first item in the files list - -# Fix - -- fix not showing selected file info after clearing search -- fix not showing total count when no file is selected -- fix pdf preview being too narrow -- fix an issue related to view composer was occurring on new installation -- fix git ignoring vendor folders. - -# Wiki - -- add note about sqlite requirement for files lock/unlock option. -- https://github.com/ctf0/Laravel-Media-Manager/wiki/Customization---Optimization - -# Update - -- update assets -- update readme \ No newline at end of file diff --git a/logs/v2.3.4.txt b/logs/v2.3.4.txt new file mode 100644 index 0000000..f25c777 --- /dev/null +++ b/logs/v2.3.4.txt @@ -0,0 +1,17 @@ +# Edits + +- in image preview, click the name to copy its url. +- move upload panel bg patterns to its own branch to minimize package size. +- more cleanup. +- uploading new items while the manager is already uploading is now disabled, also the call to update the files list will run only once at the end of the upload to minimize the load on the server. + +# Bulk Select + +- show total selected items size +- show folders nested items count +- fix not being able to manually deselect last item in bulk list +- show items size when deleting + total if more than one +- if you want you can now download a zip file with all the selected files instead of separate ones. https://github.com/ctf0/Laravel-Media-Manager/wiki/Download-Files-as-a-ZipFile + +- update readme +- update assets \ No newline at end of file diff --git a/src/resources/assets/js/components/media.vue b/src/resources/assets/js/components/media.vue index 7b325b3..84d1043 100644 --- a/src/resources/assets/js/components/media.vue +++ b/src/resources/assets/js/components/media.vue @@ -8,6 +8,7 @@ import Restriction from './mixins/restriction' import Utilities from './mixins/utils' import Watchers from './mixins/watch' import Computed from './mixins/computed' +import Download from './mixins/download' import Bounty from 'vue-bounty' @@ -23,6 +24,7 @@ export default { Restriction, Utilities, Computed, + Download, Watchers ], props: [ @@ -75,7 +77,12 @@ export default { new_folder_name: null, new_filename: null, active_modal: null, - navDirection: '' + + navDirection: null, + gradients: [ + 'linear-gradient(45deg,#6FE594,#27A47C)', + 'linear-gradient(45deg,#F1467A,#FB949E)' + ] } }, created() { @@ -120,6 +127,7 @@ export default { let counter = 0 let progress = 0 let increaseBy = 0 + let last = null new Dropzone('#new-upload', { createImageThumbnails: false, @@ -140,22 +148,24 @@ export default { }, successmultiple(files, res) { res.data.map((item) => { - item.success - ? manager.showNotif(`${manager.trans('upload_success')} "${item.message}"`) - : manager.showNotif(item.message, 'danger') + if (item.success) { + manager.showNotif(`${manager.trans('upload_success')} "${item.message}"`) + last = item.message + } else { + manager.showNotif(item.message, 'danger') + } }) - - res.data.length - ? manager.getFiles(manager.folders, null, res.data[res.data.length - 1].message) - : manager.getFiles(manager.folders) }, errormultiple(files, res) { manager.showNotif(res, 'danger') }, queuecomplete() { manager.uploadStart = false - manager.toggleUploadPanel() manager.uploadProgress = 0 + + last + ? manager.getFiles(manager.folders, null, last) + : manager.getFiles(manager.folders) } }) }, @@ -221,7 +231,7 @@ export default { // file upload if (keycode(e) == 'u') { - this.toggleUploadPanel() + this.$refs.upload.click() } } /* end of no bulk selection */ @@ -311,8 +321,6 @@ export default { this.selectedFileIs('folder') ? this.folderWarning = true : this.folderWarning = false - - this.$refs.confirm_delete.innerText = this.selectedFile.name } if (this.bulkItemsCount) { diff --git a/src/resources/assets/js/components/mixins/bulk.js b/src/resources/assets/js/components/mixins/bulk.js index bf5de0c..edf2aa7 100644 --- a/src/resources/assets/js/components/mixins/bulk.js +++ b/src/resources/assets/js/components/mixins/bulk.js @@ -13,8 +13,12 @@ export default { this.bulkList.splice(this.bulkList.indexOf(file), 1) - // select prev item - this.selectedFile = this.bulkList[this.bulkItemsCount - 1] + if (this.bulkItemsCount) { + // select prev item + this.selectedFile = this.bulkList[this.bulkItemsCount - 1] + } else { + this.resetInput(['selectedFile', 'currentFileIndex']) + } }, selectFirstInBulkList() { let list = this.bulkList diff --git a/src/resources/assets/js/components/mixins/computed.js b/src/resources/assets/js/components/mixins/computed.js index cd8e4e7..d223dde 100644 --- a/src/resources/assets/js/components/mixins/computed.js +++ b/src/resources/assets/js/components/mixins/computed.js @@ -1,5 +1,8 @@ export default { computed: { + filesList() { + return this.$refs.filesList.$el.children + }, allFiles() { if (this.filteredItemsCount) { return this.filterdList @@ -7,35 +10,51 @@ export default { return this.files.items }, - filteredItemsCount() { - if (typeof this.filterdList !== 'undefined' && this.filterdList.length > 0) { - return this.filterdList.length - } - }, allItemsCount() { if (typeof this.allFiles !== 'undefined' && this.allFiles.length > 0) { return this.allFiles.length } }, - filesList() { - return this.$refs.filesList.$el.children + filteredItemsCount() { + if (typeof this.filterdList !== 'undefined' && this.filterdList.length > 0) { + return this.filterdList.length + } }, + + // bulk bulkItemsCount() { if (typeof this.bulkList !== 'undefined' && this.bulkList.length > 0) { return this.bulkList.length } }, - uploadPanelImg() { - if (this.uploadToggle) { - let list = this.uploadPanelImgList - let url = list[Math.floor(Math.random() * list.length)] + bulkItemsSize() { + let count = 0 - return { - 'background-image': `url("${url}")` + this.bulkList.map((item) => {count += item.size}) + + return this.getFileSize(count) + }, + bulkItemsChild() { + let bulk = this.bulkItemsCount + + if (bulk) { + if (bulk == 1 && !this.selectedFileIs('folder')) { + return } + + let count = 0 + + this.bulkList.map((item) => { + let list = item.items + + if (list) { + count += list + } + }) + + return count } }, - // this is made so we can still use move/delete // incase we have multiple files selected // and one or more of them is locked @@ -43,6 +62,22 @@ export default { return this.lockedList.length ? this.bulkList.filter((e) => {return !this.lockedList.includes(e.path)}) : this.bulkList + }, + + // upload panel + uploadPanelImg() { + if (this.uploadToggle) { + let imgs = this.uploadPanelImgList + let grds = this.gradients + + let url = imgs[Math.floor(Math.random() * imgs.length)] + let color = grds[Math.floor(Math.random() * grds.length)] + + return { + '--gradient': color, + 'background-image': `url("${url}")` + } + } } } } diff --git a/src/resources/assets/js/components/mixins/download.js b/src/resources/assets/js/components/mixins/download.js new file mode 100644 index 0000000..7589c28 --- /dev/null +++ b/src/resources/assets/js/components/mixins/download.js @@ -0,0 +1,61 @@ +// for normal download +require('./../../vendor/download.min') + +// for zip download +const JSZip = require('jszip') +const JSZipUtils = require('jszip-utils') +const FileSaver = require('file-saver') + +export default { + methods: { + // download + saveFile(item) { + if (this.isBulkSelecting()) { + return typeof JSZip != 'undefined' + ? this.zipFiles(this.bulkList) + : this.downloadFiles(this.bulkList) + } + + this.downloadFiles([item]) + this.showNotif(`"${item.name}" ${this.trans('downloaded')}`) + }, + downloadFiles(list) { + list.forEach((e) => { + downloadFile(e.path) + }) + this.showNotif('All Done') + }, + zipFiles(list) { + let zip = new JSZip() + let count = 0 + + let folders = this.folders + let folder_name = folders.length + ? folders[folders.length - 1] + : 'media_manager' + + list.forEach((e) => { + JSZipUtils.getBinaryContent(e.path, (err, data) => { + if (err) { + console.error(err) + this.showNotif(this.trans('ajax_error'), 'danger') + } + + zip.file(e.name, data, {binary:true}) + count++ + + if (count == list.length) { + zip.generateAsync({ + type:'blob', + compression: 'DEFLATE', + platform: 'UNIX' + }).then((content) => { + FileSaver.saveAs(content, `${folder_name}.zip`) + this.showNotif(`"${folder_name}.zip" ${this.trans('downloaded')}`) + }) + } + }) + }) + } + } +} diff --git a/src/resources/assets/js/components/mixins/form.js b/src/resources/assets/js/components/mixins/form.js index 1069fe0..55cac68 100644 --- a/src/resources/assets/js/components/mixins/form.js +++ b/src/resources/assets/js/components/mixins/form.js @@ -3,9 +3,13 @@ export default { /* Main */ getFiles(folders = '/', prev_folder = null, prev_file = null) { - this.toggleLoading() this.noFiles('hide') - this.loadingFiles('show') + + if (!this.loading_files) { + this.toggleLoading() + this.loadingFiles('show') + } + this.resetInput(['searchFor', 'sortBy', 'currentFilterName', 'selectedFile', 'currentFileIndex']) if (folders !== '/') { @@ -78,9 +82,9 @@ export default { } setTimeout(() => { - this.toggleInfo = true this.toggleLoading() this.loadingFiles('hide') + this.toggleInfo = true }, 500) // scroll to prev selected item diff --git a/src/resources/assets/js/components/mixins/utils.js b/src/resources/assets/js/components/mixins/utils.js index 90285e5..d80759c 100644 --- a/src/resources/assets/js/components/mixins/utils.js +++ b/src/resources/assets/js/components/mixins/utils.js @@ -1,5 +1,3 @@ -require('./../../vendor/download.min') - export default { methods: { isLastItem(item, list) { @@ -153,20 +151,6 @@ export default { }, /* Ops */ - // download - saveFile(item) { - if (this.isBulkSelecting()) { - this.bulkList.forEach((e) => { - downloadFile(e.path) - }) - - return this.showNotif('All Done') - } - - downloadFile(item.path) - return this.showNotif(`"${item.name}" ${this.trans('downloaded')}`) - }, - // copy to clipboard copyLink(path) { this.linkCopied = true diff --git a/src/resources/assets/js/components/mixins/watch.js b/src/resources/assets/js/components/mixins/watch.js index d4d965a..b8eb67c 100644 --- a/src/resources/assets/js/components/mixins/watch.js +++ b/src/resources/assets/js/components/mixins/watch.js @@ -60,6 +60,14 @@ export default { }) } }, + uploadStart(val) { + if (val) { + this.toggleUploadPanel() + this.toggleLoading() + this.noFiles('hide') + this.loadingFiles('show') + } + }, // ls randomNames(val) { diff --git a/src/resources/assets/js/manager.js b/src/resources/assets/js/manager.js index d838cb4..8ca8c63 100644 --- a/src/resources/assets/js/manager.js +++ b/src/resources/assets/js/manager.js @@ -12,17 +12,16 @@ Vue.use(require('vue-tippy'), { arrow: true, touchHold: true, inertia: true, - performance: true -}) -window.addEventListener('scroll', function () { - const poppers = document.querySelectorAll('.tippy-popper') - - for (const popper of poppers) { - const tooltip = popper._reference._tippy - - if (tooltip.state.visible) { - tooltip.popperInstance.disableEventListeners() - tooltip.hide() + performance: true, + flipDuration: 0, + popperOptions: { + modifiers: { + preventOverflow: { + enabled: false + }, + hide: { + enabled: false + } } } }) diff --git a/src/resources/assets/sass/media.scss b/src/resources/assets/sass/media.scss index 12b626b..fb00e01 100644 --- a/src/resources/assets/sass/media.scss +++ b/src/resources/assets/sass/media.scss @@ -42,6 +42,7 @@ transition: all 0.3s ease-in-out; border-radius: 5px; background-repeat: repeat; + background-position: center; &::before { position: absolute; @@ -52,9 +53,9 @@ content: ''; transition: all 0.3s ease-in-out; transform: translate(-50%, -50%); + opacity: 0.8; border-radius: 100vw; - background-color: orangered; - mix-blend-mode: difference; + background-image: var(--gradient); } &:hover { @@ -65,7 +66,7 @@ } } - .__dz-message { + .dz-message { font-weight: 400; position: relative; margin: 0; @@ -97,7 +98,7 @@ } #uploadProgress { - margin-bottom: 15px; + margin: 1rem 0; border-radius: 100vw; } @@ -434,29 +435,40 @@ flex-direction: row-reverse; justify-content: space-evenly; margin-top: 3rem; - text-align: center; color: darken($active_theme, 50%); > div { - flex: 1; + text-align: center; &:not(:first-of-type) { border-right: 1px solid darken($active_theme, 10%); } + &:not(:only-of-type) { + flex: 1; + transition: all 0.3s; + } + &:only-of-type { - padding-right: 0.75rem; - text-align: right; + margin-left: auto; } + } - .title { - line-height: 1; - margin: 0 !important; - color: darken($active_theme, 50%); + .__right-count-bulk { + span.icon, + span.is-5 { + position: relative; + bottom: 6px; + } + } - svg { - fill: darken($active_theme, 50%); - } + .title { + line-height: 1; + margin: 0 !important; + color: darken($active_theme, 50%); + + svg { + fill: darken($active_theme, 50%); } } } @@ -496,10 +508,10 @@ } } -.__modal-delete-text * { - font-weight: 500; - color: $blue; - fill: $blue; +.__modal-delete-total { + margin-top: 1rem; + padding-top: 1rem; + text-align: right; } .__modal-folder-warning { @@ -581,9 +593,8 @@ } &:only-of-type { - padding-right: 0; - padding-left: 0.75rem; - text-align: left; + margin-right: auto; + margin-left: 0; } } } diff --git a/src/resources/views/_manager.blade.php b/src/resources/views/_manager.blade.php index aede50f..39449d0 100644 --- a/src/resources/views/_manager.blade.php +++ b/src/resources/views/_manager.blade.php @@ -32,6 +32,8 @@ {{-- upload --}}