Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7347be8
wip
jasonvarga May 7, 2025
aa52810
wip
jasonvarga May 7, 2025
4c06a26
Remove WithField component and usages. All of the changes in componen…
jasonvarga May 7, 2025
c2899eb
Remove unused prop. Maybe it'll come back if we ever need it
jasonvarga May 7, 2025
a988d8f
Show sidebar when space allows
jasonvarga May 7, 2025
4690fee
Merge branch 'ui' into publish-forms
jasonvarga May 8, 2025
6b22ac3
expect the store injected directly
jasonvarga May 12, 2025
70d20c5
Move logic to class so it can be used from composition api more easily
jasonvarga May 12, 2025
2bc5772
wip ...
jasonvarga May 12, 2025
d7fdd83
Tabs with errors get highlighted
jasonvarga May 12, 2025
113199b
tooltip can provide markdown as a prop
jasonvarga May 12, 2025
a97f401
Replicator no longer needs to pass previews
jasonvarga May 12, 2025
52723e2
Dirty state can be tracked
jasonvarga May 13, 2025
186e3f1
Save pipeline
jasonvarga May 13, 2025
541f33f
Add Statamic.$dirty
jasonvarga May 13, 2025
5a5c386
Remove all the revision related code from term publish form. It's nev…
jasonvarga May 13, 2025
ef3f167
Merge branch 'ui' into publish-forms
jasonvarga May 16, 2025
fe70fc7
remove withfield from combobox
jasonvarga May 16, 2025
e69acb6
Update field ...
jasonvarga May 16, 2025
e892496
Label has a for prop
jasonvarga May 16, 2025
5d66fdb
wip ...
jasonvarga May 16, 2025
bc26980
use new stuff on entries publish form
jasonvarga May 16, 2025
df544d0
When values prop change, update the stores values without bubbling an…
jasonvarga May 19, 2025
c84ede7
Only update the value if it changed.
jasonvarga May 19, 2025
54d412c
Also set extra values from response
jasonvarga May 19, 2025
09d2403
Wire up entry publish form to new save pipeline
jasonvarga May 19, 2025
976a1e7
handle error
jasonvarga May 19, 2025
a1702e9
wire up generic form components
jasonvarga May 19, 2025
09b601a
Pass required to field label
jasonvarga May 19, 2025
5f6442e
Delete test component
jasonvarga May 19, 2025
963e8b0
meta
jasonvarga May 19, 2025
4424433
wip ...
jasonvarga May 20, 2025
7e03472
Rename NewSet back to Set
jasonvarga May 20, 2025
e7c0a02
rename icons
jasonvarga May 20, 2025
4cedb3b
Merge branch 'ui' into publish-forms
jasonvarga May 20, 2025
8a63c2e
get by without the localizable icon
jasonvarga May 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions resources/js/bootstrap/statamic.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import Echo from '../components/Echo';
import Permission from '../components/Permission';
import autosize from 'autosize';
import DateFormatter from '@statamic/components/DateFormatter.js';
import wait from '@statamic/util/wait.js';

let bootingCallbacks = [];
let bootedCallbacks = [];
Expand Down Expand Up @@ -110,6 +111,18 @@ export default {
return this.$app.config.globalProperties.$theme;
},

get $fieldActions() {
return this.$app.config.globalProperties.$fieldActions;
},

get $dirty() {
return this.$app.config.globalProperties.$dirty;
},

get $events() {
return this.$app.config.globalProperties.$events;
},

get user() {
return this.$config.get('user');
},
Expand Down Expand Up @@ -189,9 +202,7 @@ export default {
return permissions.includes('super') || permissions.includes(permission);
},
$wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
return wait(ms);
},
});

Expand Down
460 changes: 167 additions & 293 deletions resources/js/components/entries/PublishForm.vue

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions resources/js/components/field-conditions/ShowField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Validator from '@statamic/components/field-conditions/Validator.js';
import { data_get } from '@statamic/bootstrap/globals.js';
import { nextTick } from 'vue';

export default class {
constructor(store, values, extraValues) {
this.store = store;
this.values = values;
this.extraValues = extraValues;
}

showField(field, dottedKey) {
let dottedFieldPath = dottedKey || field.handle;
let dottedPrefix = dottedKey ? dottedKey.replace(new RegExp('\.' + field.handle + '$'), '') : '';

// If we know the field is to permanently hidden, bypass validation.
if (field.visibility === 'hidden' || this.shouldForceHiddenField(dottedFieldPath)) {
this.setHiddenFieldState({
dottedKey: dottedFieldPath,
hidden: 'force',
omitValue: false,
});

return false;
}

// Use validation to determine whether field should be shown.
let validator = new Validator(field, { ...this.values, ...this.extraValues }, dottedFieldPath, this.store);
let passes = validator.passesConditions();

// If the field is configured to always save, never omit value.
if (field.always_save === true) {
this.setHiddenFieldState({
dottedKey: dottedFieldPath,
hidden: !passes,
omitValue: false,
});

return passes;
}

// Ensure DOM is updated to ensure all revealers are properly loaded and tracked before committing to store.
nextTick(() => {
this.setHiddenFieldState({
dottedKey: dottedFieldPath,
hidden: !passes,
omitValue: field.type === 'revealer' || !validator.passesNonRevealerConditions(dottedPrefix),
});
});

return passes;
}

setHiddenFieldState({ dottedKey, hidden, omitValue }) {
const currentValue = this.store.hiddenFields[dottedKey];

// Prevent infinite loops
if (currentValue && currentValue.hidden === hidden && currentValue.omitValue === omitValue) {
return;
}

this.store.setHiddenField({
dottedKey,
hidden,
omitValue,
});
}

shouldForceHiddenField(dottedFieldPath) {
return data_get(this.store.hiddenFields[dottedFieldPath], 'hidden') === 'force';
}
}
69 changes: 3 additions & 66 deletions resources/js/components/field-conditions/ValidatorMixin.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,11 @@
import Validator from './Validator.js';
import { data_get } from '../../bootstrap/globals.js';
import ShowField from './ShowField.js';

export default {
inject: ['publishContainer'],
inject: ['store'],

methods: {
showField(field, dottedKey) {
let dottedFieldPath = dottedKey || field.handle;
let dottedPrefix = dottedKey ? dottedKey.replace(new RegExp('\.' + field.handle + '$'), '') : '';

// If we know the field is to permanently hidden, bypass validation.
if (field.visibility === 'hidden' || this.shouldForceHiddenField(dottedFieldPath)) {
this.setHiddenFieldState({
dottedKey: dottedFieldPath,
hidden: 'force',
omitValue: false,
});

return false;
}

// Use validation to determine whether field should be shown.
let validator = new Validator(
field,
{ ...this.values, ...this.extraValues },
dottedFieldPath,
this.publishContainer.store,
);
let passes = validator.passesConditions();

// If the field is configured to always save, never omit value.
if (field.always_save === true) {
this.setHiddenFieldState({
dottedKey: dottedFieldPath,
hidden: !passes,
omitValue: false,
});

return passes;
}

// Ensure DOM is updated to ensure all revealers are properly loaded and tracked before committing to store.
this.$nextTick(() => {
this.setHiddenFieldState({
dottedKey: dottedFieldPath,
hidden: !passes,
omitValue: field.type === 'revealer' || !validator.passesNonRevealerConditions(dottedPrefix),
});
});

return passes;
},

setHiddenFieldState({ dottedKey, hidden, omitValue }) {
const currentValue = this.publishContainer.store.hiddenFields[dottedKey];

// Prevent infinite loops
if (currentValue && currentValue.hidden === hidden && currentValue.omitValue === omitValue) {
return;
}

this.publishContainer.store.setHiddenField({
dottedKey,
hidden,
omitValue,
});
},

shouldForceHiddenField(dottedFieldPath) {
return data_get(this.publishContainer.store.hiddenFields[dottedFieldPath], 'hidden') === 'force';
return new ShowField(this.store, this.values, this.extraValues).showField(field, dottedKey);
},
},
};
6 changes: 3 additions & 3 deletions resources/js/components/fieldtypes/Fieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export default {
},
namePrefix: String,
fieldPathPrefix: String,
metaPathPrefix: String,
id: String,
},

methods: {
Expand Down Expand Up @@ -95,9 +97,7 @@ export default {
},

fieldId() {
let prefix = this.fieldPathPrefix ? this.fieldPathPrefix + '.' : '';

return prefix + 'field_' + this.config.handle;
return this.id;
},

fieldActionPayload() {
Expand Down
44 changes: 13 additions & 31 deletions resources/js/components/fieldtypes/GroupFieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,14 @@
>
</publish-field-fullscreen-header>
<section :class="{ 'mt-14 p-4': fullScreenMode }">
<div :class="{ 'replicator-set rounded-sm border shadow-sm dark:border-dark-900': config.border }">
<div
class="publish-fields @container"
:class="{ 'replicator-set-body': config.border, '-mx-4': !config.border }"
<div :class="{ 'replicator-set dark:border-dark-900 rounded-sm border shadow-sm': config.border }">
<FieldsProvider
:fields="fields"
:field-path-prefix="fieldPathPrefix || handle"
:meta-path-prefix="metaPathPrefix || handle"
>
<set-field
v-for="field in fields"
:key="field.handle"
v-show="showField(field, fieldPath(field.handle))"
:field="field"
:meta="meta[field.handle]"
:value="value[field.handle]"
:parent-name="name"
:set-index="0"
:errors="errors(field.handle)"
:field-path="fieldPath(field.handle)"
:read-only="isReadOnly"
:show-field-previews="config.replicator_preview"
@updated="updated(field.handle, $event)"
@meta-updated="updateMeta(field.handle, $event)"
@focus="$emit('focus')"
@blur="$emit('blur')"
@replicator-preview-updated="previewUpdated(field.handle, $event)"
/>
</div>
<Fields class="p-4" />
</FieldsProvider>
</div>
</section>
</div>
Expand All @@ -56,19 +39,19 @@

<script>
import Fieldtype from './Fieldtype.vue';
import SetField from './replicator/Field.vue';
import { ValidatesFieldConditions } from '../field-conditions/FieldConditions.js';
import ManagesPreviewText from './replicator/ManagesPreviewText';
import Fields from '@statamic/components/ui/Publish/Fields.vue';
import FieldsProvider from '@statamic/components/ui/Publish/FieldsProvider.vue';

export default {
mixins: [Fieldtype, ValidatesFieldConditions, ManagesPreviewText],
components: { SetField },
components: { Fields, FieldsProvider },
data() {
return {
containerWidth: null,
focused: false,
fullScreenMode: false,
previews: {},
provide: {
group: this.makeGroupProvide(),
},
Expand All @@ -85,6 +68,9 @@ export default {
fields() {
return this.config.fields;
},
previews() {
return data_get(this.store.previews, this.fieldPathPrefix || this.handle) || {};
},
replicatorPreview() {
if (!this.showFieldPreviews || !this.config.replicator_preview) return;

Expand Down Expand Up @@ -152,10 +138,6 @@ export default {
this.$emit('meta-updated', { ...this.meta, [handle]: value });
},

previewUpdated(handle, value) {
this.previews = { ...this.previews, [handle]: value };
},

fieldPath(handle) {
return (this.fieldPathPrefix || this.handle) + '.' + handle;
},
Expand Down
1 change: 1 addition & 0 deletions resources/js/components/fieldtypes/SlugFieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
:id="fieldId"
:isReadOnly="isReadOnly"
:name="slug"
:disabled="isReadOnly"
@focus="$emit('focus')"
@blur="$emit('blur')"
>
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/fieldtypes/TextFieldtype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
:autocomplete="config.autocomplete"
:autoselect="config.autoselect"
:type="config.input_type"
:isReadOnly="isReadOnly"
:disabled="isReadOnly"
:prepend="__(config.prepend)"
:append="__(config.append)"
:limit="config.character_limit"
:placeholder="__(config.placeholder)"
:name="name"
:id="fieldId"
:id="id"
:direction="config.direction"
@update:model-value="inputUpdated"
@focus="$emit('focus')"
Expand Down
Loading
Loading