Skip to content

Commit 97ee228

Browse files
Save button options (#2404)
* Add save and continue dropdown component. * Add save and continue dropdown to entry publish form. * Wire up save button option to user preferences. * Rename option key. * Clean up preference handling on publish form. * Pass `listingUrl` and `createAnotherUrl` to entry publish forms. * Wire up redirect after save logic. * Guard when revisions are enabled. * 📝 Save button text now shows what happens next * 📝 Continue * 📝 I only missed half of the states. NBD. * 💄 Using buttons instead of text to convey next action * Use same `breadcrumbs` prop on terms publish form as we do on entries publish form. * Add save and continue, etc. logic to terms publish form. * Fix setting of `initialPublished` after saving. * Fix button text. Co-authored-by: Jack McDade <jack@jackmcdade.com>
1 parent 7b75898 commit 97ee228

File tree

12 files changed

+305
-66
lines changed

12 files changed

+305
-66
lines changed

resources/js/components/entries/BaseCreateForm.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
:revisions-enabled="revisions"
1818
:breadcrumbs="breadcrumbs"
1919
:initial-site="site"
20+
:create-another-url="createAnotherUrl"
21+
:listing-url="listingUrl"
2022
@saved="saved"
2123
></entry-publish-form>
2224

@@ -35,6 +37,8 @@ export default {
3537
'revisions',
3638
'breadcrumbs',
3739
'site',
40+
'createAnotherUrl',
41+
'listingUrl',
3842
],
3943
4044
methods: {

resources/js/components/entries/PublishForm.vue

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,27 @@
2020
</div>
2121

2222
<div class="hidden md:flex items-center">
23-
<button
23+
24+
<save-button-options
2425
v-if="!readOnly"
25-
:class="{
26-
'btn': revisionsEnabled,
27-
'btn-primary': isCreating || !revisionsEnabled,
28-
}"
29-
:disabled="!canSave"
30-
@click.prevent="save"
31-
v-text="saveText" />
26+
:show-options="!revisionsEnabled"
27+
:button-class="saveButtonClass"
28+
:preferences-prefix="preferencesPrefix"
29+
>
30+
<button
31+
:class="saveButtonClass"
32+
:disabled="!canSave"
33+
@click.prevent="save"
34+
v-text="saveText"
35+
/>
36+
</save-button-options>
3237

3338
<button
3439
v-if="revisionsEnabled && !isCreating"
3540
class="ml-2 btn-primary flex items-center"
3641
:disabled="!canPublish"
3742
@click="confirmingPublish = true">
38-
<span v-text="__('Publish')" />
39-
<svg-icon name="chevron-down-xs" class="ml-1 w-2" />
43+
<span>{{ __('Publish') }}…</span>
4044
</button>
4145
</div>
4246

@@ -177,15 +181,16 @@
177181
</div>
178182
<template v-slot:buttons>
179183
<button
180-
v-if="!readOnly"
181-
class="ml-2"
182-
:class="{
183-
'btn': revisionsEnabled,
184-
'btn-primary': isCreating || !revisionsEnabled,
185-
}"
186-
:disabled="!canSave"
187-
@click.prevent="save"
188-
v-text="saveText" />
184+
v-if="!readOnly"
185+
class="ml-2"
186+
:class="{
187+
'btn': revisionsEnabled,
188+
'btn-primary': isCreating || !revisionsEnabled,
189+
}"
190+
:disabled="!canSave"
191+
@click.prevent="save"
192+
v-text="saveText">
193+
</button>
189194

190195
<button
191196
v-if="revisionsEnabled && !isCreating"
@@ -248,13 +253,20 @@
248253

249254

250255
<script>
251-
import PublishActions from './PublishActions.vue';
252-
import RevisionHistory from '../revision-history/History.vue';
256+
import PublishActions from './PublishActions';
257+
import SaveButtonOptions from '../publish/SaveButtonOptions';
258+
import RevisionHistory from '../revision-history/History';
259+
import HasPreferences from '../data-list/HasPreferences';
253260
254261
export default {
255262
263+
mixins: [
264+
HasPreferences,
265+
],
266+
256267
components: {
257268
PublishActions,
269+
SaveButtonOptions,
258270
RevisionHistory,
259271
},
260272
@@ -283,7 +295,9 @@ export default {
283295
initialPermalink: String,
284296
revisionsEnabled: Boolean,
285297
preloadedAssets: Array,
286-
canEditBlueprint: Boolean
298+
canEditBlueprint: Boolean,
299+
createAnotherUrl: String,
300+
listingUrl: String,
287301
},
288302
289303
data() {
@@ -309,6 +323,7 @@ export default {
309323
state: 'new',
310324
revisionMessage: null,
311325
showRevisionHistory: false,
326+
preferencesPrefix: `collections.${this.collectionHandle}`,
312327
313328
// Whether it was published the last time it was saved.
314329
// Successful publish actions (if using revisions) or just saving (if not) will update this.
@@ -367,14 +382,36 @@ export default {
367382
},
368383
369384
saveText() {
370-
if (this.revisionsEnabled) return __('Save Changes');
385+
switch(true) {
386+
case this.revisionsEnabled:
387+
return __('Save Changes');
388+
case this.isUnpublishing:
389+
return __('Save & Unpublish');
390+
case this.isDraft:
391+
return __('Save Draft');
392+
default:
393+
return __('Save & Publish');
394+
}
395+
},
371396
372-
if (this.published) return __('Save & Publish');
397+
isUnpublishing() {
398+
return this.initialPublished && ! this.published && ! this.isCreating;
399+
},
373400
374-
if (!this.published && this.initialPublished) return __('Save & Unpublish');
401+
isDraft() {
402+
return ! this.published;
403+
},
375404
376-
return __('Save');
377-
}
405+
saveButtonClass() {
406+
return {
407+
'btn': this.revisionsEnabled,
408+
'btn-primary': this.isCreating || ! this.revisionsEnabled,
409+
};
410+
},
411+
412+
afterSaveOption() {
413+
return this.getPreference('after_save');
414+
},
378415
379416
},
380417
@@ -448,11 +485,29 @@ export default {
448485
response
449486
})
450487
.then(() => {
451-
if (! this.revisionsEnabled) this.initialPublished = response.data.published;
452-
453-
// Finally, we'll emit an event. We need to wait until after the hooks are resolved because
454-
// if this form is being shown in a stack, we only want to close it once everything's done.
455-
this.$nextTick(() => this.$emit('saved', response));
488+
// If revisions are enabled, just emit event.
489+
if (this.revisionsEnabled) {
490+
this.$nextTick(() => this.$emit('saved', response));
491+
return;
492+
}
493+
494+
// If the user has opted to create another entry, redirect them to create page.
495+
if (this.afterSaveOption === 'create_another') {
496+
window.location = this.createAnotherUrl;
497+
}
498+
499+
// If the user has opted to go to listing (default/null option), redirect them there.
500+
else if (this.afterSaveOption === null) {
501+
window.location = this.listingUrl;
502+
}
503+
504+
// Otherwise, leave them on the edit form and emit an event. We need to wait until after
505+
// the hooks are resolved because if this form is being shown in a stack, we only
506+
// want to close it once everything's done.
507+
else {
508+
this.initialPublished = response.data.data.published;
509+
this.$nextTick(() => this.$emit('saved', response));
510+
}
456511
}).catch(e => {});
457512
},
458513
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<template>
2+
3+
<div :class="{ 'btn-group': showOptions }">
4+
5+
<!-- Save button -->
6+
<slot></slot>
7+
8+
<!-- Save and continue options dropdown -->
9+
<dropdown-list v-if="showOptions" class="text-left">
10+
<template v-slot:trigger>
11+
<button :class="buttonClass" class="rounded-l-none">
12+
<svg-icon v-if="buttonIcon" :name="buttonIcon.name" :class="buttonIcon.class" />
13+
</button>
14+
</template>
15+
<h6 v-text="__('After Saving')" class="p-1" />
16+
<div class="publish-fields px-1">
17+
<div class="publish-field save-and-continue-options">
18+
<radio-fieldtype
19+
handle="save_and_continue_options"
20+
:config="options"
21+
v-model="currentOption"
22+
/>
23+
</div>
24+
</div>
25+
</dropdown-list>
26+
27+
</div>
28+
29+
</template>
30+
31+
<script>
32+
export default {
33+
34+
props: {
35+
showOptions: {
36+
type: Boolean,
37+
default: true
38+
},
39+
buttonClass: {
40+
default: 'btn-primary',
41+
},
42+
preferencesPrefix: {
43+
type: String,
44+
required: true,
45+
},
46+
},
47+
48+
data() {
49+
return {
50+
currentOption: null,
51+
};
52+
},
53+
54+
computed: {
55+
options() {
56+
return {
57+
options: {
58+
listing: __('Go To Listing'),
59+
continue_editing: __('Continue Editing'),
60+
create_another: __('Create Another'),
61+
},
62+
};
63+
},
64+
65+
buttonIcon() {
66+
switch(true) {
67+
case this.currentOption === 'listing':
68+
return {name: 'micro-arrow-go-back', class: 'w-3'};
69+
case this.currentOption === 'continue_editing':
70+
return {name: 'chevron-down-xs', class: 'w-2'};
71+
case this.currentOption === 'create_another':
72+
return {name: 'micro-add-circle', class: 'w-3'};
73+
}
74+
},
75+
76+
preferencesKey() {
77+
return `${this.preferencesPrefix}.after_save`;
78+
},
79+
},
80+
81+
watch: {
82+
currentOption: 'setPreference',
83+
},
84+
85+
mounted() {
86+
this.setInitialValue();
87+
},
88+
89+
methods: {
90+
setInitialValue() {
91+
this.currentOption = this.$preferences.get(this.preferencesKey) || 'listing';
92+
},
93+
94+
setPreference(value) {
95+
if (value === this.$preferences.get(this.preferencesKey)) return;
96+
97+
value === 'listing'
98+
? this.$preferences.remove(this.preferencesKey)
99+
: this.$preferences.set(this.preferencesKey, value);
100+
},
101+
},
102+
103+
}
104+
</script>
105+
106+
<style>
107+
.save-and-continue-options input {
108+
margin-bottom: 9px;
109+
}
110+
.save-and-continue-options input {
111+
margin-right: 5px;
112+
}
113+
</style>

resources/js/components/terms/BaseCreateForm.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
:initial-actions="actions"
77
method="post"
88
:initial-title="__('Create')"
9-
:taxonomy-title="taxonomyTitle"
10-
:taxonomy-url="taxonomyUrl"
9+
:taxonomy-handle="taxonomyHandle"
10+
:breadcrumbs="breadcrumbs"
1111
:initial-fieldset="fieldset"
1212
:initial-values="values"
1313
:initial-meta="meta"
@@ -16,6 +16,8 @@
1616
:initial-has-origin="false"
1717
:initial-is-root="true"
1818
:initial-origin-values="{}"
19+
:create-another-url="createAnotherUrl"
20+
:listing-url="listingUrl"
1921
@saved="saved"
2022
></term-publish-form>
2123

@@ -26,13 +28,15 @@ export default {
2628
2729
props: [
2830
'actions',
29-
'taxonomyTitle',
30-
'taxonomyUrl',
31+
'taxonomyHandle',
32+
'breadcrumbs',
3133
'fieldset',
3234
'values',
3335
'meta',
3436
'published',
3537
'localizations',
38+
'createAnotherUrl',
39+
'listingUrl',
3640
],
3741
3842
methods: {

0 commit comments

Comments
 (0)