From 04164a09e8f46fa4accd874798c7c818300c1618 Mon Sep 17 00:00:00 2001 From: Philipp Daun Date: Wed, 7 Aug 2024 15:06:52 +0200 Subject: [PATCH 1/3] Send mimetype and duration with asset resource --- src/Assets/Asset.php | 4 ++-- src/Http/Resources/CP/Assets/Asset.php | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 938d53de95d..1f79073d8d5 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -1071,12 +1071,12 @@ protected function defaultAugmentedRelations() return $this->selectedQueryRelations; } - private function hasDimensions() + public function hasDimensions() { return $this->isImage() || $this->isSvg() || $this->isVideo(); } - private function hasDuration() + public function hasDuration() { return $this->isAudio() || $this->isVideo(); } diff --git a/src/Http/Resources/CP/Assets/Asset.php b/src/Http/Resources/CP/Assets/Asset.php index 4e0ff2c4375..7b7e0045288 100644 --- a/src/Http/Resources/CP/Assets/Asset.php +++ b/src/Http/Resources/CP/Assets/Asset.php @@ -23,6 +23,7 @@ public function toArray($request) 'size' => Str::fileSizeForHumans($this->size()), 'lastModified' => $this->lastModified()->inPreferredFormat(), 'lastModifiedRelative' => $this->lastModified()->diffForHumans(), + 'mimeType' => $this->mimeType(), 'isImage' => $this->isImage(), 'isSvg' => $this->isSvg(), 'isAudio' => $this->isAudio(), @@ -31,10 +32,21 @@ public function toArray($request) 'isPdf' => $this->isPdf(), 'isPreviewable' => $this->isPreviewable(), - $this->mergeWhen($this->isImage() || $this->isSvg(), function () { + $this->mergeWhen($this->hasDimensions(), function () { return [ 'width' => $this->width(), 'height' => $this->height(), + ]; + }), + + $this->mergeWhen($this->hasDuration(), function () { + return [ + 'duration' => $this->duration(), + ]; + }), + + $this->mergeWhen($this->isImage() || $this->isSvg(), function () { + return [ 'preview' => $this->previewUrl(), 'thumbnail' => $this->thumbnailUrl('small'), ]; From bebfecad4fe4cf9a7904eb0334ef5de43ad7fdbf Mon Sep 17 00:00:00 2001 From: Philipp Daun Date: Wed, 7 Aug 2024 15:43:17 +0200 Subject: [PATCH 2/3] Provide asset data as hidden fields --- .../js/components/assets/Editor/Editor.vue | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/resources/js/components/assets/Editor/Editor.vue b/resources/js/components/assets/Editor/Editor.vue index e551c953083..f7c7e574250 100644 --- a/resources/js/components/assets/Editor/Editor.vue +++ b/resources/js/components/assets/Editor/Editor.vue @@ -330,11 +330,6 @@ export default { this.$axios.get(url).then(response => { const data = response.data.data; this.asset = data; - - // If there are no fields, it will be an empty array when PHP encodes - // it into JSON on the server. We'll ensure it's always an object. - this.values = _.isArray(data.values) ? {} : data.values; - this.meta = data.meta; this.actionUrl = data.actionUrl; this.actions = data.actions; @@ -347,10 +342,41 @@ export default { .flatten(true) .value(); + // If there are no fields, it will be an empty array when PHP encodes + // it into JSON on the server. We'll ensure it's always an object. + const blueprintValues = _.isArray(data.values) ? {} : data.values; + const assetValues = _.chain(this.asset) + .pick(['filename', 'basename', 'extension', 'path', 'mimeType', 'width', 'height', 'duration']) + .omit(_.pluck(this.fields, 'handle')) + .value(); + + // Merge asset file data with asset blueprint data + this.values = { ...assetValues, ...blueprintValues }; + + // Append hidden fields to blueprint to allow field conditions + const hiddenFields = Object.keys(assetValues).map(handle => this.createHiddenField(handle)); + this.fieldset = this.extendBlueprintFields(this.fieldset, hiddenFields); + this.loading = false; }); }, + createHiddenField(handle) { + return { + handle, + display: handle, + type: 'text', + if: { 'internal_should_not_exist_in_blueprint': 'equals true' } + }; + }, + + extendBlueprintFields(blueprint, fields) { + const extended = clone(blueprint); + const existingFields = data_get(extended, 'tabs.0.sections.0.fields'); + existingFields?.push(...fields); + return extended; + }, + openFocalPointEditor() { this.showFocalPointEditor = true; }, From 67c141cc6b2173828e48377464af6afc6906493f Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Mon, 21 Oct 2024 17:17:52 -0400 Subject: [PATCH 3/3] introduce extra values concept rather than hacking in hidden fields --- .../js/components/assets/Editor/Editor.vue | 39 +++++-------------- .../field-conditions/ValidatorMixin.js | 2 +- resources/js/components/publish/Container.vue | 6 +++ resources/js/components/publish/Fields.vue | 4 ++ .../js/tests/FieldConditionsValidator.test.js | 15 ++++++- 5 files changed, 34 insertions(+), 32 deletions(-) diff --git a/resources/js/components/assets/Editor/Editor.vue b/resources/js/components/assets/Editor/Editor.vue index f7c7e574250..ea80ed29bd8 100644 --- a/resources/js/components/assets/Editor/Editor.vue +++ b/resources/js/components/assets/Editor/Editor.vue @@ -126,6 +126,7 @@ :name="publishContainer" :blueprint="fieldset" :values="values" + :extra-values="extraValues" :meta="meta" :errors="errors" @updated="values = { ...$event, focus: values.focus }" @@ -204,6 +205,7 @@ import FocalPointEditor from './FocalPointEditor.vue'; import PdfViewer from './PdfViewer.vue'; import PublishFields from '../../publish/Fields.vue'; import HasHiddenFields from '../../publish/HasHiddenFields'; +import pick from 'underscore/modules/pick'; export default { @@ -245,6 +247,7 @@ export default { asset: null, publishContainer: 'asset', values: {}, + extraValues: {}, meta: {}, fields: null, fieldset: null, @@ -330,6 +333,11 @@ export default { this.$axios.get(url).then(response => { const data = response.data.data; this.asset = data; + + // If there are no fields, it will be an empty array when PHP encodes + // it into JSON on the server. We'll ensure it's always an object. + this.values = _.isArray(data.values) ? {} : data.values; + this.meta = data.meta; this.actionUrl = data.actionUrl; this.actions = data.actions; @@ -342,41 +350,12 @@ export default { .flatten(true) .value(); - // If there are no fields, it will be an empty array when PHP encodes - // it into JSON on the server. We'll ensure it's always an object. - const blueprintValues = _.isArray(data.values) ? {} : data.values; - const assetValues = _.chain(this.asset) - .pick(['filename', 'basename', 'extension', 'path', 'mimeType', 'width', 'height', 'duration']) - .omit(_.pluck(this.fields, 'handle')) - .value(); - - // Merge asset file data with asset blueprint data - this.values = { ...assetValues, ...blueprintValues }; - - // Append hidden fields to blueprint to allow field conditions - const hiddenFields = Object.keys(assetValues).map(handle => this.createHiddenField(handle)); - this.fieldset = this.extendBlueprintFields(this.fieldset, hiddenFields); + this.extraValues = pick(this.asset, ['filename', 'basename', 'extension', 'path', 'mimeType', 'width', 'height', 'duration']); this.loading = false; }); }, - createHiddenField(handle) { - return { - handle, - display: handle, - type: 'text', - if: { 'internal_should_not_exist_in_blueprint': 'equals true' } - }; - }, - - extendBlueprintFields(blueprint, fields) { - const extended = clone(blueprint); - const existingFields = data_get(extended, 'tabs.0.sections.0.fields'); - existingFields?.push(...fields); - return extended; - }, - openFocalPointEditor() { this.showFocalPointEditor = true; }, diff --git a/resources/js/components/field-conditions/ValidatorMixin.js b/resources/js/components/field-conditions/ValidatorMixin.js index 770dd499b5f..2e3c1c96b77 100644 --- a/resources/js/components/field-conditions/ValidatorMixin.js +++ b/resources/js/components/field-conditions/ValidatorMixin.js @@ -25,7 +25,7 @@ export default { } // Use validation to determine whether field should be shown. - let validator = new Validator(field, this.values, dottedFieldPath, this.$store, this.storeName); + let validator = new Validator(field, {...this.values, ...this.extraValues}, dottedFieldPath, this.$store, this.storeName); let passes = validator.passesConditions(); // If the field is configured to always save, never omit value. diff --git a/resources/js/components/publish/Container.vue b/resources/js/components/publish/Container.vue index 6feb8efc383..5429ac52060 100644 --- a/resources/js/components/publish/Container.vue +++ b/resources/js/components/publish/Container.vue @@ -25,6 +25,10 @@ export default { type: Object, default: () => {} }, + extraValues: { + type: Object, + default: () => {} + }, meta: { type: Object, default: () => {} @@ -78,6 +82,7 @@ export default { const initial = { blueprint: _.clone(this.blueprint), values: _.clone(this.values), + extraValues: _.clone(this.extraValues), meta: _.clone(this.meta), localizedFields: _.clone(this.localizedFields), site: this.site, @@ -97,6 +102,7 @@ export default { state: { blueprint: initial.blueprint, values: initial.values, + extraValues: initial.extraValues, hiddenFields: {}, jsonSubmittingFields: [], revealerFields: [], diff --git a/resources/js/components/publish/Fields.vue b/resources/js/components/publish/Fields.vue index e7aa4c0418b..da0de216440 100644 --- a/resources/js/components/publish/Fields.vue +++ b/resources/js/components/publish/Fields.vue @@ -58,6 +58,10 @@ export default { return this.state.values; }, + extraValues() { + return this.state.extraValues || {}; + }, + meta() { return this.state.meta; }, diff --git a/resources/js/tests/FieldConditionsValidator.test.js b/resources/js/tests/FieldConditionsValidator.test.js index 08a1bc260ab..af54ca38c6c 100644 --- a/resources/js/tests/FieldConditionsValidator.test.js +++ b/resources/js/tests/FieldConditionsValidator.test.js @@ -64,7 +64,8 @@ const Fields = new Vue({ data() { return { storeName: 'base', - values: {} + values: {}, + extraValues: {}, } }, methods: { @@ -78,6 +79,9 @@ const Fields = new Vue({ } Store.commit('publish/base/setValues', storeValues); }, + setExtraValues(values) { + this.extraValues = values; + }, setStoreValues(values) { Store.commit('publish/base/setValues', values); }, @@ -106,6 +110,7 @@ let showFieldIf = function (conditions=null, dottedFieldPath=null) { afterEach(() => { Fields.values = {}; + Fields.extraValues = {}; Store.commit('publish/base/reset'); }); @@ -1010,3 +1015,11 @@ test('it properly omits nested revealer-hidden fields when multiple conditions a // Though this third venue is hidden by a revealer, it's also disabled by a regular toggle condition, so it should actually be omitted... expect(Store.state.publish.base.hiddenFields['nested.event_venue_three'].omitValue).toBe(true); }); + +test('it can use extra values in conditions', () => { + Fields.setValues({}); + Fields.setExtraValues({hello: 'world'}); + + expect(showFieldIf({hello: 'world'})).toBe(true); + expect(showFieldIf({hello: 'there'})).toBe(false); +});