From c564ecc23f9191272b72e768e4f50d0aa49bf955 Mon Sep 17 00:00:00 2001 From: Quentin Renard Date: Tue, 17 Mar 2020 02:16:06 -0400 Subject: [PATCH] Add new options to medias and files form fields - filesizeMax, on the files field, to prevent selecting a file which filesize is above provided value in mb - widthMin. on the medias field, to prevent selecting an image which width is below provided value in px - heightMin. on the medias field, to prevent selecting an image which height is below provided value in px --- frontend/js/components/ItemList.vue | 15 +++++-- frontend/js/components/MediaField.vue | 8 ++++ frontend/js/components/files/FileField.vue | 4 ++ .../js/components/media-library/MediaGrid.vue | 11 ++++- .../components/media-library/MediaLibrary.vue | 43 ++++++++++++------- .../js/mixins/mediaLibrary/mediaLibrary.js | 4 ++ frontend/js/plugins/A17Config.js | 3 ++ frontend/js/store/modules/media-library.js | 24 +++++++++++ frontend/js/store/mutations/media-library.js | 6 +++ src/Models/File.php | 1 + views/partials/form/_files.blade.php | 4 +- views/partials/form/_medias.blade.php | 6 +++ 12 files changed, 108 insertions(+), 21 deletions(-) diff --git a/frontend/js/components/ItemList.vue b/frontend/js/components/ItemList.vue index b962d4bc6..5a2dd3d95 100755 --- a/frontend/js/components/ItemList.vue +++ b/frontend/js/components/ItemList.vue @@ -11,11 +11,14 @@ - + @@ -73,7 +76,8 @@ return Object.keys(firstItem).filter(key => { // exclude columns here return ![ 'id', 'name', 'thumbnail', 'src', 'original', 'edit', - 'crop', 'deleteUrl', 'updateUrl', 'updateBulkUrl', 'deleteBulkUrl', 'endpointType' + 'crop', 'deleteUrl', 'updateUrl', 'updateBulkUrl', + 'deleteBulkUrl', 'endpointType', 'filesizeInMb' ].includes(key) && typeof firstItem[key] === 'string' // only strings }) }, @@ -146,6 +150,11 @@ &:hover { background-color: $color__f--bg; } + + &.s--disabled { + color: $color__button_greyed--bg; + pointer-events: none; + } } .itemlist__row:first-child { diff --git a/frontend/js/components/MediaField.vue b/frontend/js/components/MediaField.vue index 34e828183..3b53d6db3 100755 --- a/frontend/js/components/MediaField.vue +++ b/frontend/js/components/MediaField.vue @@ -151,6 +151,14 @@ activeCrop: { type: Boolean, default: true + }, + widthMin: { + type: Number, + default: 0 + }, + heightMin: { + type: Number, + default: 0 } }, data: function () { diff --git a/frontend/js/components/files/FileField.vue b/frontend/js/components/files/FileField.vue index 1bab4bc7d..098784f03 100644 --- a/frontend/js/components/files/FileField.vue +++ b/frontend/js/components/files/FileField.vue @@ -63,6 +63,10 @@ fieldNote: { type: String, default: '' + }, + filesizeMax: { + type: Number, + default: 0 } }, data: () => { diff --git a/frontend/js/components/media-library/MediaGrid.vue b/frontend/js/components/media-library/MediaGrid.vue index ff52a94a4..56845f0d8 100755 --- a/frontend/js/components/media-library/MediaGrid.vue +++ b/frontend/js/components/media-library/MediaGrid.vue @@ -7,7 +7,11 @@
- +
@@ -157,6 +161,11 @@ opacity: 0.85; } } + + &.s--disabled { + pointer-events: none; + opacity: 0.2; + } } .s--loading { diff --git a/frontend/js/components/media-library/MediaLibrary.vue b/frontend/js/components/media-library/MediaLibrary.vue index 864e623ab..db52aecca 100755 --- a/frontend/js/components/media-library/MediaLibrary.vue +++ b/frontend/js/components/media-library/MediaLibrary.vue @@ -50,10 +50,10 @@
- - Loading…
@@ -145,7 +145,7 @@ return { loading: false, maxPage: 20, - fullMedias: [], + mediaItems: [], selectedMedias: [], gridHeight: 0, page: this.initialPage, @@ -155,6 +155,14 @@ } }, computed: { + renderedMediaItems: function () { + return this.mediaItems.map((item) => { + item.disabled = (this.filesizeMax > 0 && item.filesizeInMb > this.filesizeMax) + || (this.widthMin > 0 && item.width < this.widthMin) + || (this.heightMin > 0 && item.height < this.heightMin) + return item + }) + }, currentTypeObject: function () { return this.types.find((type) => { return type.value === this.type @@ -190,6 +198,9 @@ ...mapState({ connector: state => state.mediaLibrary.connector, max: state => state.mediaLibrary.max, + filesizeMax: state => state.mediaLibrary.filesizeMax, + widthMin: state => state.mediaLibrary.widthMin, + heightMin: state => state.mediaLibrary.heightMin, type: state => state.mediaLibrary.type, // image, video, file types: state => state.mediaLibrary.types, strict: state => state.mediaLibrary.strict, @@ -199,7 +210,7 @@ }, watch: { type: function () { - this.clearFullMedias() + this.clearMediaItems() this.gridLoaded = false } }, @@ -236,7 +247,7 @@ }, addMedia: function (media) { // add media in first position of the available media - this.fullMedias.unshift(media) + this.mediaItems.unshift(media) this.$store.commit(MEDIA_LIBRARY.INCREMENT_MEDIA_TYPE_TOTAL, this.type) // select it this.updateSelectedMedias(media.id) @@ -254,8 +265,8 @@ if (shift && this.selectedMedias.length > 0) { const lastSelectedMedia = this.selectedMedias[this.selectedMedias.length - 1] - const lastSelectedMediaIndex = this.fullMedias.findIndex((media) => media.id === lastSelectedMedia.id) - const selectedMediaIndex = this.fullMedias.findIndex((media) => media.id === id) + const lastSelectedMediaIndex = this.mediaItems.findIndex((media) => media.id === lastSelectedMedia.id) + const selectedMediaIndex = this.mediaItems.findIndex((media) => media.id === id) if (selectedMediaIndex === -1 && lastSelectedMediaIndex === -1) return let start = null @@ -268,7 +279,7 @@ end = lastSelectedMediaIndex } - const selectedMedias = this.fullMedias.slice(start, end) + const selectedMedias = this.mediaItems.slice(start, end) selectedMedias.forEach((media) => { if (this.selectedMedias.length >= this.max && this.max > 0) return @@ -278,7 +289,7 @@ } }) } else { - const mediaToSelect = this.fullMedias.filter(function (media) { + const mediaToSelect = this.mediaItems.filter(function (media) { return media.id === id }) @@ -322,16 +333,16 @@ mediasIds.forEach(() => { this.$store.commit(MEDIA_LIBRARY.DECREMENT_MEDIA_TYPE_TOTAL, this.type) }) - this.fullMedias = this.fullMedias.filter((media) => { + this.mediaItems = this.mediaItems.filter((media) => { return !this.selectedMedias.includes(media) || keepSelectedMedias.includes(media) }) this.selectedMedias = keepSelectedMedias - if (this.fullMedias.length <= 40) { + if (this.mediaItems.length <= 40) { this.reloadGrid() } }, - clearFullMedias: function () { - this.fullMedias.splice(0) + clearMediaItems: function () { + this.mediaItems.splice(0) }, reloadGrid: function () { this.loading = true @@ -350,8 +361,8 @@ api.get(this.endpoint, formdata, (resp) => { // add medias here resp.data.items.forEach(item => { - if (!this.fullMedias.find(media => media.id === item.id)) { - this.fullMedias.push(item) + if (!this.mediaItems.find(media => media.id === item.id)) { + this.mediaItems.push(item) } }) this.maxPage = resp.data.maxPage || 1 @@ -376,7 +387,7 @@ // when changing filters, reset the page to 1 this.page = 1 - this.clearFullMedias() + this.clearMediaItems() this.clearSelectedMedias() if (el.scrollTop === 0) { diff --git a/frontend/js/mixins/mediaLibrary/mediaLibrary.js b/frontend/js/mixins/mediaLibrary/mediaLibrary.js index 667f2201e..967a486e2 100644 --- a/frontend/js/mixins/mediaLibrary/mediaLibrary.js +++ b/frontend/js/mixins/mediaLibrary/mediaLibrary.js @@ -13,6 +13,10 @@ export default { this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_TYPE, this.type) this.$store.commit(MEDIA_LIBRARY.UPDATE_REPLACE_INDEX, index) this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_MAX, max) + this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_MODE, true) + this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_FILESIZE_MAX, this.filesizeMax || 0) + this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_WIDTH_MIN, this.widthMin || 0) + this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_HEIGHT_MIN, this.heightMin || 0) if (this.$root.$refs.mediaLibrary) this.$root.$refs.mediaLibrary.open() } } diff --git a/frontend/js/plugins/A17Config.js b/frontend/js/plugins/A17Config.js index 2e3ef8d6e..c40876594 100644 --- a/frontend/js/plugins/A17Config.js +++ b/frontend/js/plugins/A17Config.js @@ -89,6 +89,9 @@ const A17Config = { this.$store.commit(MEDIA_LIBRARY.RESET_MEDIA_TYPE) // reset to first available type this.$store.commit(MEDIA_LIBRARY.UPDATE_REPLACE_INDEX, -1) // we are not replacing an image here this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_MAX, 0) // set max to 0 + this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_FILESIZE_MAX, 0) // set filesize max to 0 + this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_WIDTH_MIN, 0) // set width min to 0 + this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_HEIGHT_MIN, 0) // set height min to 0 this.$store.commit(MEDIA_LIBRARY.UPDATE_MEDIA_MODE, false) // set the strict to false (you can change the active type) if (this.$root.$refs.mediaLibrary) this.$root.$refs.mediaLibrary.open() diff --git a/frontend/js/store/modules/media-library.js b/frontend/js/store/modules/media-library.js index cc47de5f6..054ff7d60 100644 --- a/frontend/js/store/modules/media-library.js +++ b/frontend/js/store/modules/media-library.js @@ -34,6 +34,21 @@ const state = { * @type {number} */ max: 0, + /** + * Define the maximum filesize allowed to attach in a field from the media library + * @type {number} + */ + filesizeMax: 0, + /** + * Define the min image width allowed to attach in a field from the media library + * @type {number} + */ + widthMin: 0, + /** + * Define the min image height allowed to attach in a field from the media library + * @type {number} + */ + heightMin: 0, /** * Restrict the media library navigation between type * @type {Boolean} @@ -173,6 +188,15 @@ const mutations = { [MEDIA_LIBRARY.UPDATE_MEDIA_MAX] (state, newValue) { state.max = Math.max(0, newValue) }, + [MEDIA_LIBRARY.UPDATE_MEDIA_FILESIZE_MAX] (state, newValue) { + state.filesizeMax = Math.max(0, newValue) + }, + [MEDIA_LIBRARY.UPDATE_MEDIA_WIDTH_MIN] (state, newValue) { + state.widthMin = Math.max(0, newValue) + }, + [MEDIA_LIBRARY.UPDATE_MEDIA_HEIGHT_MIN] (state, newValue) { + state.heightMin = Math.max(0, newValue) + }, [MEDIA_LIBRARY.SET_MEDIA_METADATAS] (state, metadatas) { const connector = metadatas.media.context const medias = state.selected[connector] diff --git a/frontend/js/store/mutations/media-library.js b/frontend/js/store/mutations/media-library.js index a659688c0..ddb146a63 100644 --- a/frontend/js/store/mutations/media-library.js +++ b/frontend/js/store/mutations/media-library.js @@ -11,6 +11,9 @@ export const DONE_UPLOAD_MEDIA = 'doneUploadMedia' export const ERROR_UPLOAD_MEDIA = 'errorUploadMedia' export const DESTROY_SPECIFIC_MEDIA = 'destroyMediasInSelected' export const UPDATE_MEDIA_MAX = 'updateMediaMax' +export const UPDATE_MEDIA_FILESIZE_MAX = 'updateMediaFilesizeMax' +export const UPDATE_MEDIA_WIDTH_MIN = 'updateMediaWidthMin' +export const UPDATE_MEDIA_HEIGHT_MIN = 'updateMediaHeightMin' export const UPDATE_MEDIA_TYPE = 'updateMediaType' export const RESET_MEDIA_TYPE = 'resetMediaType' export const SET_MEDIA_CROP = 'setMediaCrop' @@ -33,6 +36,9 @@ export default { ERROR_UPLOAD_MEDIA, DESTROY_SPECIFIC_MEDIA, UPDATE_MEDIA_MAX, + UPDATE_MEDIA_FILESIZE_MAX, + UPDATE_MEDIA_WIDTH_MIN, + UPDATE_MEDIA_HEIGHT_MIN, UPDATE_MEDIA_TYPE, RESET_MEDIA_TYPE, SET_MEDIA_CROP, diff --git a/src/Models/File.php b/src/Models/File.php index 757d8adef..6331aa565 100755 --- a/src/Models/File.php +++ b/src/Models/File.php @@ -33,6 +33,7 @@ public function toCmsArray() 'src' => FileService::getUrl($this->uuid), 'original' => FileService::getUrl($this->uuid), 'size' => $this->size, + 'filesizeInMb' => number_format($this->attributes['size'] / 1048576, 2), ]; } diff --git a/views/partials/form/_files.blade.php b/views/partials/form/_files.blade.php index 5f0857ec0..9c997471f 100644 --- a/views/partials/form/_files.blade.php +++ b/views/partials/form/_files.blade.php @@ -3,6 +3,7 @@ $itemLabel = $itemLabel ?? strtolower($label); $note = $note ?? 'Add' . ($max > 1 ? " up to $max $itemLabel" : ' one ' . Str::singular($itemLabel)); $fieldNote = $fieldNote ?? ''; + $filesizeMax = $filesizeMax ?? 0; @endphp true]) note: '{{ $note }}', fieldNote: '{{ $fieldNote }}', - max: {{ $max }} + max: {{ $max }}, + filesizeMax: {{ $filesizeMax }} }" > diff --git a/views/partials/form/_medias.blade.php b/views/partials/form/_medias.blade.php index da9fe20f9..6e2ea0968 100644 --- a/views/partials/form/_medias.blade.php +++ b/views/partials/form/_medias.blade.php @@ -10,6 +10,8 @@ $captionMaxLength = $captionMaxLength ?? false; $extraMetadatas = $extraMetadatas ?? false; $multiple = $max > 1 || $max == 0; + $widthMin = $widthMin ?? 0; + $heightMin = $heightMin ?? 0; @endphp @if (config('twill.media_library.translated_form_fields', $translated ?? false) && ($translated ?? true)) @@ -19,6 +21,8 @@ label: '{{ $label }}', cropContext: '{{ $name }}', max: {{ $max }}, + widthMin: {{ $widthMin }}, + heightMin: {{ $heightMin }}, @if ($extraMetadatas) extraMetadatas: {{ json_encode($extraMetadatas) }}, @endif @if ($altTextMaxLength) altTextMaxLength: {{ $altTextMaxLength }}, @endif @if ($captionMaxLength) captionMaxLength: {{ $captionMaxLength }}, @endif @@ -44,6 +48,8 @@ @if($multiple)