@blokkli/editor 2.0.0-alpha.14 → 2.0.0-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +867 -2
  3. package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliEditState.graphql +4 -0
  4. package/dist/modules/drupal/graphql/features/publishNew.graphql +1 -4
  5. package/dist/modules/drupal/graphql/features/scheduler.graphql +31 -0
  6. package/dist/modules/drupal/index.mjs +17 -0
  7. package/dist/modules/drupal/runtime/adapter/index.js +31 -1
  8. package/dist/runtime/adapter/index.d.ts +36 -0
  9. package/dist/runtime/blokkliPlugins/MenuButton/index.vue.d.ts +2 -2
  10. package/dist/runtime/components/Edit/Features/EntityTitle/index.vue +33 -1
  11. package/dist/runtime/components/Edit/Features/Publish/Dialog/Item.vue +41 -14
  12. package/dist/runtime/components/Edit/Features/Publish/Dialog/Item.vue.d.ts +2 -0
  13. package/dist/runtime/components/Edit/Features/Publish/Dialog/PublishOption.vue +47 -0
  14. package/dist/runtime/components/Edit/Features/Publish/Dialog/PublishOption.vue.d.ts +19 -0
  15. package/dist/runtime/components/Edit/Features/Publish/Dialog/ScheduleDate.vue +183 -0
  16. package/dist/runtime/components/Edit/Features/Publish/Dialog/ScheduleDate.vue.d.ts +13 -0
  17. package/dist/runtime/components/Edit/Features/Publish/Dialog/Summary.vue +83 -0
  18. package/dist/runtime/components/Edit/Features/Publish/Dialog/Summary.vue.d.ts +9 -0
  19. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue +381 -129
  20. package/dist/runtime/components/Edit/Features/Publish/Dialog/index.vue.d.ts +3 -14
  21. package/dist/runtime/components/Edit/Features/Publish/index.vue +34 -20
  22. package/dist/runtime/components/Edit/Form/Datepicker/index.vue +198 -0
  23. package/dist/runtime/components/Edit/Form/Datepicker/index.vue.d.ts +15 -0
  24. package/dist/runtime/components/Edit/Konami/Game/index.vue +8 -1
  25. package/dist/runtime/components/Edit/index.d.ts +2 -1
  26. package/dist/runtime/components/Edit/index.js +2 -0
  27. package/dist/runtime/css/output.css +1 -1
  28. package/dist/runtime/helpers/stateProvider.d.ts +2 -1
  29. package/dist/runtime/helpers/stateProvider.js +31 -0
  30. package/dist/runtime/helpers/uiProvider.d.ts +2 -0
  31. package/dist/runtime/helpers/uiProvider.js +23 -0
  32. package/dist/runtime/icons/calendar-clock.svg +1 -0
  33. package/dist/runtime/icons/eye-off.svg +1 -0
  34. package/dist/runtime/types/index.d.ts +9 -1
  35. package/package.json +1 -1
@@ -0,0 +1,83 @@
1
+ <template>
2
+ <div class="bk-publish-summary">
3
+ <!-- Current State -->
4
+ <div class="bk-publish-summary-state">
5
+ <div class="bk-publish-summary-state-icon" :class="currentStateClass">
6
+ <Icon :name="currentStateIcon" />
7
+ </div>
8
+ <div class="bk-publish-summary-state-label">
9
+ {{ currentStateLabel }}
10
+ </div>
11
+ </div>
12
+
13
+ <!-- Arrow -->
14
+ <div class="bk-publish-summary-arrow">
15
+ <Icon name="arrow-right" />
16
+ </div>
17
+
18
+ <!-- Action -->
19
+ <div class="bk-publish-summary-action">
20
+ <div class="bk-publish-summary-action-icon" :class="actionClass">
21
+ <Icon :name="actionIcon" />
22
+ </div>
23
+ <div class="bk-publish-summary-action-label">
24
+ {{ actionLabel }}
25
+ </div>
26
+ </div>
27
+
28
+ <!-- Arrow -->
29
+ <div class="bk-publish-summary-arrow">
30
+ <Icon name="arrow-right" />
31
+ </div>
32
+
33
+ <!-- Result State -->
34
+ <div class="bk-publish-summary-state">
35
+ <div class="bk-publish-summary-state-icon" :class="resultStateClass">
36
+ <Icon :name="resultStateIcon" />
37
+ </div>
38
+ <div class="bk-publish-summary-state-label">
39
+ {{ resultStateLabel }}
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </template>
44
+
45
+ <script setup>
46
+ import { computed } from "#imports";
47
+ import { Icon } from "#blokkli/components";
48
+ const props = defineProps({
49
+ isPublished: { type: Boolean, required: true },
50
+ mode: { type: String, required: true },
51
+ currentStateLabel: { type: String, required: true },
52
+ actionLabel: { type: String, required: true },
53
+ resultStateLabel: { type: String, required: true }
54
+ });
55
+ const currentStateIcon = computed(
56
+ () => props.isPublished ? "eye" : "eye-off"
57
+ );
58
+ const currentStateClass = computed(
59
+ () => props.isPublished ? "bk-is-published" : "bk-is-unpublished"
60
+ );
61
+ const resultStateIcon = computed(() => {
62
+ if (props.mode === "save") {
63
+ return "eye-off";
64
+ }
65
+ return "eye";
66
+ });
67
+ const resultStateClass = computed(() => {
68
+ if (props.mode === "save") {
69
+ return "bk-is-unpublished";
70
+ }
71
+ return "bk-is-published";
72
+ });
73
+ const actionIcon = computed(() => {
74
+ if (props.mode === "save") return "save";
75
+ if (props.mode === "scheduled") return "calendar-clock";
76
+ return "publish";
77
+ });
78
+ const actionClass = computed(() => {
79
+ if (props.mode === "save") return "bk-is-save";
80
+ if (props.mode === "scheduled") return "bk-is-scheduled";
81
+ return "bk-is-publish";
82
+ });
83
+ </script>
@@ -0,0 +1,9 @@
1
+ type __VLS_Props = {
2
+ isPublished: boolean;
3
+ mode: 'immediate' | 'scheduled' | 'save';
4
+ currentStateLabel: string;
5
+ actionLabel: string;
6
+ resultStateLabel: string;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ export default _default;
@@ -1,117 +1,272 @@
1
1
  <template>
2
2
  <DialogModal
3
3
  :title="$t('publishDialogTitle', 'Publish changes')"
4
- :width="1200"
4
+ :width="900"
5
5
  :submit-label
6
6
  :is-loading="isLoading"
7
- :can-submit="!!selectedToPublishItems.length"
7
+ :can-submit="canSubmit"
8
8
  class="bk-is-publish-dialog"
9
9
  @submit="onSubmit"
10
10
  @cancel="$emit('close')"
11
11
  >
12
12
  <div class="bk bk-form bk-dialog-publish-form">
13
- <FormGroup title="Einstellungen" horizontal>
14
- <FormItem v-if="publishOptions?.hasRevisionLogMessage">
15
- <FormTextarea
16
- id="revision-message"
17
- v-model="revisionMessage"
18
- label="Protokollnachricht der Revision"
19
- description="Beschreiben Sie kurz die vorgenommenen Änderungen"
20
- :disabled="isLoading"
13
+ <FormItem>
14
+ <div class="bk-form-label">
15
+ {{ $t("publishMode", "Publish mode")
16
+ }}<span class="bk-required-indicator">*</span>
17
+ </div>
18
+ <div class="bk-publish-options">
19
+ <PublishOption
20
+ v-for="option in publishModeOptions"
21
+ :id="option.id"
22
+ :key="option.id"
23
+ v-model="publishMode"
24
+ :icon="option.icon"
25
+ :color="option.color"
26
+ :label="option.label"
27
+ :description="option.description"
28
+ :disabled="option.disabled"
21
29
  />
22
- </FormItem>
23
- <FormItem>
24
- <FormToggle
25
- v-model="shouldPublish"
26
- :label="toggleLabel"
27
- :disabled="isLoading"
28
- />
29
- </FormItem>
30
- </FormGroup>
30
+ </div>
31
+ </FormItem>
32
+
33
+ <FormItem v-if="publishMode === 'scheduled'">
34
+ <div>
35
+ <label class="bk-form-label">
36
+ {{ $t("publishScheduleDate", "Publication date") }}
37
+ </label>
38
+ <div class="bk-publish-schedule-date-wrapper">
39
+ <div v-if="isAlreadyScheduled" class="bk-publish-scheduled-display">
40
+ {{
41
+ ui.formatDate(scheduleDate, {
42
+ weekday: "long",
43
+ year: "numeric",
44
+ month: "2-digit",
45
+ day: "2-digit",
46
+ hour: "2-digit",
47
+ minute: "2-digit"
48
+ })
49
+ }}
50
+ </div>
51
+ <ScheduleDate
52
+ v-else
53
+ v-model="scheduleDate"
54
+ :disabled="isLoading"
55
+ :error="scheduleDateError"
56
+ />
57
+ <button
58
+ v-if="isAlreadyScheduled"
59
+ type="button"
60
+ class="bk-button bk-is-danger"
61
+ @click="removeScheduledDate"
62
+ >
63
+ {{ $t("publishRemoveSchedule", "Remove schedule") }}
64
+ </button>
65
+ </div>
66
+ <div v-if="isAlreadyScheduled" class="bk-form-description">
67
+ {{
68
+ $t(
69
+ "publishAlreadyScheduledDescription",
70
+ "This page is already scheduled for publishing"
71
+ )
72
+ }}
73
+ </div>
74
+ </div>
75
+ </FormItem>
76
+
77
+ <FormItem v-if="publishOptions?.hasRevisionLogMessage">
78
+ <FormTextarea
79
+ id="revision-message"
80
+ v-model="revisionMessage"
81
+ :label="$t('publishRevisionLogMessage', 'Revision log message')"
82
+ :description="
83
+ $t(
84
+ 'publishRevisionLogMessageDescription',
85
+ 'Briefly describe the changes made'
86
+ )
87
+ "
88
+ :disabled="isLoading || isAlreadyScheduled"
89
+ rows="2"
90
+ />
91
+ </FormItem>
31
92
 
32
- <FormGroup title="Inhalte" horizontal>
33
- <FormItem>
34
- <template v-if="successItems.length">
35
- <h2 class="bk-heading-2">Erfolgreich veröffentlicht</h2>
93
+ <FormItem v-if="successItems.length && showTable">
94
+ <h2 class="bk-heading-2">
95
+ {{ $t("publishSuccessfullyPublished", "Successfully published") }}
96
+ </h2>
36
97
 
37
- <table class="bk-table bk-publish-dialog-table">
38
- <thead>
39
- <tr>
40
- <th>Name</th>
41
- <th colspan="2">Status</th>
42
- </tr>
43
- </thead>
98
+ <table class="bk-table bk-publish-dialog-table">
99
+ <thead>
100
+ <tr>
101
+ <th>{{ $t("publishName", "Name") }}</th>
102
+ <th colspan="2">{{ $t("publishStatus", "Status") }}</th>
103
+ </tr>
104
+ </thead>
44
105
 
45
- <tbody>
46
- <Item
47
- v-for="item in successItems"
48
- :key="'success' + item.id"
49
- v-bind="item"
50
- v-model="states"
51
- :is-current="item.id === currentId"
52
- :should-publish
53
- :is-mutating
54
- :mutation-status="mutationStatusItems[item.id]"
55
- />
56
- </tbody>
57
- </table>
58
- </template>
106
+ <tbody>
107
+ <Item
108
+ v-for="item in successItems"
109
+ :key="'success' + item.id"
110
+ v-bind="item"
111
+ v-model="states"
112
+ :is-current="item.id === currentId"
113
+ :should-publish
114
+ :is-mutating
115
+ :mutation-status="mutationStatusItems[item.id]"
116
+ :is-scheduled="enableScheduling"
117
+ :schedule-date
118
+ />
119
+ </tbody>
120
+ </table>
59
121
 
60
- <table class="bk-table bk-publish-dialog-table">
61
- <thead>
62
- <tr>
63
- <th>Name</th>
64
- <th colspan="2">Status</th>
65
- </tr>
66
- </thead>
122
+ <table class="bk-table bk-publish-dialog-table">
123
+ <thead>
124
+ <tr>
125
+ <th>{{ $t("publishName", "Name") }}</th>
126
+ <th colspan="2">{{ $t("publishStatus", "Status") }}</th>
127
+ </tr>
128
+ </thead>
67
129
 
68
- <tbody>
69
- <Item
70
- v-for="item in toPublishItems"
71
- :key="'to_publish_' + item.id"
72
- v-bind="item"
73
- v-model="states"
74
- :is-current="item.id === currentId"
75
- :should-publish
76
- :is-mutating
77
- :mutation-status="mutationStatusItems[item.id]"
78
- />
79
- </tbody>
80
- </table>
81
- </FormItem>
82
- </FormGroup>
130
+ <tbody>
131
+ <Item
132
+ v-for="item in toPublishItems"
133
+ :key="'to_publish_' + item.id"
134
+ v-bind="item"
135
+ v-model="states"
136
+ :is-current="item.id === currentId"
137
+ :should-publish
138
+ :is-mutating
139
+ :mutation-status="mutationStatusItems[item.id]"
140
+ :is-scheduled="enableScheduling"
141
+ :schedule-date
142
+ />
143
+ </tbody>
144
+ </table>
145
+ </FormItem>
146
+ <FormItem class="bk-is-summary">
147
+ <h3 class="bk-form-label">
148
+ {{ $t("publishSummary", "Summary") }}
149
+ </h3>
150
+ <Summary
151
+ :is-published="isCurrentlyPublished"
152
+ :mode="publishMode"
153
+ :current-state-label="currentStateLabel"
154
+ :action-label="actionLabel"
155
+ :result-state-label="resultStateLabel"
156
+ />
157
+ </FormItem>
83
158
  </div>
84
159
  </DialogModal>
85
160
  </template>
86
161
 
87
162
  <script setup>
88
- import { ref, computed, useBlokkli, useAsyncData } from "#imports";
89
163
  import {
90
- DialogModal,
91
- FormToggle,
92
- FormTextarea,
93
- FormItem,
94
- FormGroup
95
- } from "#blokkli/components";
96
- import { falsy } from "#blokkli/helpers";
164
+ ref,
165
+ computed,
166
+ watch,
167
+ useBlokkli,
168
+ useAsyncData,
169
+ onMounted,
170
+ onUnmounted
171
+ } from "#imports";
172
+ import { DialogModal, FormTextarea, FormItem } from "#blokkli/components";
173
+ import { emitMessage } from "#blokkli/helpers/eventBus";
97
174
  import Item from "./Item.vue";
98
- const { adapter, $t, state, context } = useBlokkli();
175
+ import PublishOption, {} from "./PublishOption.vue";
176
+ import Summary from "./Summary.vue";
177
+ import ScheduleDate from "./ScheduleDate.vue";
178
+ const showTable = false;
179
+ const { adapter, $t, state, context, ui } = useBlokkli();
99
180
  const isMutating = ref(false);
100
181
  const mutationStatusItems = ref({});
101
182
  const publishedIds = ref([]);
102
- const shouldPublish = defineModel("shouldPublish", { type: Boolean, ...{
103
- default: () => false
104
- } });
105
- const states = defineModel("states", { type: Array, ...{
106
- default: () => []
107
- } });
108
- const revisionMessage = defineModel("revisionMessage", { type: String, ...{
109
- default: () => false
110
- } });
183
+ const states = ref([]);
184
+ const revisionMessage = ref("");
185
+ const currentTimestamp = ref(Date.now());
186
+ let timestampInterval = null;
187
+ onMounted(() => {
188
+ timestampInterval = setInterval(() => {
189
+ currentTimestamp.value = Date.now();
190
+ }, 3e4);
191
+ });
192
+ onUnmounted(() => {
193
+ if (timestampInterval) {
194
+ clearInterval(timestampInterval);
195
+ }
196
+ });
197
+ const publishMode = ref("immediate");
111
198
  const emit = defineEmits(["close", "submit"]);
112
- const { data: publishOptions, status } = await useAsyncData(() => {
199
+ const {
200
+ data: publishOptions,
201
+ status,
202
+ refresh
203
+ } = await useAsyncData(() => {
113
204
  return adapter.getPublishOptions();
114
205
  });
206
+ const canSchedule = computed(() => !!publishOptions.value?.canSchedule);
207
+ const publishOn = computed(
208
+ () => publishOptions.value?.publishOn ?? null
209
+ );
210
+ const isAlreadyScheduled = computed(() => !!publishOn.value);
211
+ const isCurrentlyPublished = computed(() => !!state.entity.value?.status);
212
+ const publishModeOptions = computed(() => {
213
+ const options = [
214
+ {
215
+ id: "save",
216
+ icon: "save",
217
+ color: "red",
218
+ label: $t("publishModeSaveTitle", "Save"),
219
+ description: $t(
220
+ "publishModeSaveDescription",
221
+ "Save changes without publishing"
222
+ ),
223
+ disabled: isCurrentlyPublished.value || isAlreadyScheduled.value
224
+ },
225
+ {
226
+ id: "immediate",
227
+ icon: "publish",
228
+ color: "lime",
229
+ label: $t("publishModeImmediateTitle", "Publish"),
230
+ description: $t(
231
+ "publishModeImmediateDescription",
232
+ "Publish changes immediately"
233
+ ),
234
+ disabled: isAlreadyScheduled.value
235
+ }
236
+ ];
237
+ if (canSchedule.value) {
238
+ options.push({
239
+ id: "scheduled",
240
+ icon: "calendar-clock",
241
+ color: "yellow",
242
+ label: $t("publishModeScheduledTitle", "Schedule"),
243
+ description: $t(
244
+ "publishModeScheduledDescription",
245
+ "Schedule changes for publishing"
246
+ ),
247
+ disabled: false
248
+ });
249
+ }
250
+ return options;
251
+ });
252
+ const scheduleDate = ref(publishOn.value || "");
253
+ console.log("SET REIVISON LOG MESSAGE");
254
+ if (publishOptions.value?.revisionLogMessage) {
255
+ revisionMessage.value = publishOptions.value.revisionLogMessage;
256
+ }
257
+ if (publishOn.value) {
258
+ publishMode.value = "scheduled";
259
+ }
260
+ watch(publishMode, (newMode) => {
261
+ if (newMode === "scheduled" && !scheduleDate.value) {
262
+ const tomorrow = /* @__PURE__ */ new Date();
263
+ tomorrow.setDate(tomorrow.getDate() + 1);
264
+ tomorrow.setHours(12, 0, 0, 0);
265
+ scheduleDate.value = tomorrow.toISOString();
266
+ }
267
+ });
268
+ const enableScheduling = computed(() => publishMode.value === "scheduled");
269
+ const shouldPublish = computed(() => publishMode.value !== "save");
115
270
  const { data: editStates } = await useAsyncData(
116
271
  () => {
117
272
  if (adapter.getEditStates) {
@@ -167,39 +322,127 @@ const selectedToPublishItems = computed(
167
322
  )
168
323
  );
169
324
  const isLoading = computed(() => status.value === "pending" || isMutating.value);
170
- const submitLabelPublish = computed(() => {
171
- if (shouldPublish.value) {
172
- const count = 1 + states.value.length;
173
- return "@count Inhalte publizieren".replace("@count", count.toString());
325
+ const scheduleDateError = computed(() => {
326
+ if (publishMode.value !== "scheduled" || !scheduleDate.value) {
327
+ return "";
328
+ }
329
+ const selectedDateTime = new Date(scheduleDate.value);
330
+ const minDateTime = new Date(currentTimestamp.value + 2 * 60 * 1e3);
331
+ if (selectedDateTime < minDateTime) {
332
+ return $t(
333
+ "publishScheduleDateTooSoon",
334
+ "The scheduled date must be at least 2 minutes in the future"
335
+ );
336
+ }
337
+ return "";
338
+ });
339
+ const canSubmit = computed(() => {
340
+ if (!selectedToPublishItems.value.length) {
341
+ return false;
342
+ }
343
+ if (publishMode.value === "scheduled" && !scheduleDate.value) {
344
+ return false;
174
345
  }
175
- return null;
346
+ if (publishMode.value === "scheduled" && isAlreadyScheduled.value) {
347
+ return false;
348
+ }
349
+ if (scheduleDateError.value) {
350
+ return false;
351
+ }
352
+ return true;
176
353
  });
177
- const submitLabelSave = computed(() => {
354
+ const submitLabel = computed(() => {
178
355
  const count = selectedToPublishItems.value.length;
179
- if (!count) {
180
- if (shouldPublish.value) {
181
- return "Inhalte publizieren";
356
+ if (publishMode.value === "scheduled") {
357
+ if (count === 0) {
358
+ return $t("publishSchedulePublication", "Schedule publication");
182
359
  }
183
- return "Inhalte speichern";
360
+ return count === 1 ? $t("publishSchedulePublication", "Schedule publication") : $t(
361
+ "publishSchedulePublications",
362
+ "Schedule @count publications"
363
+ ).replace("@count", count.toString());
184
364
  }
185
- if (!shouldPublish.value) {
186
- return "@count Inhalte speichern".replace("@count", count.toString());
365
+ if (publishMode.value === "save") {
366
+ if (count === 0) {
367
+ return $t("publishSaveContent", "Save content");
368
+ }
369
+ return count === 1 ? $t("publishSaveContent", "Save content") : $t("publishSaveContents", "Save @count contents").replace(
370
+ "@count",
371
+ count.toString()
372
+ );
373
+ }
374
+ if (count === 0) {
375
+ return $t("publishPublishContent", "Publish content");
187
376
  }
188
- return null;
377
+ return count === 1 ? $t("publishPublishContent", "Publish content") : $t("publishPublishContents", "Publish @count contents").replace(
378
+ "@count",
379
+ count.toString()
380
+ );
189
381
  });
190
- const submitLabel = computed(() => {
191
- return [submitLabelPublish.value, submitLabelSave.value].filter(falsy).join(", ");
382
+ const currentStateLabel = computed(
383
+ () => isCurrentlyPublished.value ? $t("publishCurrentlyPublished", "Page is published") : $t("publishCurrentlyUnpublished", "Page is unpublished")
384
+ );
385
+ const actionLabel = computed(() => {
386
+ if (publishMode.value === "save") {
387
+ return $t("publishModeSaveTitle", "Save");
388
+ }
389
+ if (publishMode.value === "scheduled") {
390
+ return $t("publishModeScheduledTitle", "Schedule");
391
+ }
392
+ return $t("publishModeImmediateTitle", "Publish");
192
393
  });
193
- const toggleLabel = computed(() => {
194
- if (states.value.length) {
195
- return "Inhalte publizieren";
394
+ const resultStateLabel = computed(() => {
395
+ if (publishMode.value === "save") {
396
+ return $t(
397
+ "publishResultSaveChanges",
398
+ "Changes are saved, page remains unpublished"
399
+ );
196
400
  }
197
- return "Inhalt publizieren";
401
+ if (publishMode.value === "scheduled" && scheduleDate.value) {
402
+ const formattedDate = ui.formatDate(scheduleDate.value);
403
+ return $t(
404
+ "publishResultScheduledChanges",
405
+ "Changes will be published on @date"
406
+ ).replace("@date", formattedDate);
407
+ }
408
+ if (isCurrentlyPublished.value) {
409
+ return $t(
410
+ "publishResultPublishChangesRemainPublished",
411
+ "Changes are published, page remains published"
412
+ );
413
+ }
414
+ return $t(
415
+ "publishResultPublishChangesNowPublished",
416
+ "Changes are published, page is now published"
417
+ );
198
418
  });
419
+ async function removeScheduledDate() {
420
+ if (!adapter.unscheduleEditState) {
421
+ return;
422
+ }
423
+ isMutating.value = true;
424
+ const previousScheduleDate = scheduleDate.value;
425
+ const success = await state.mutateWithLoadingState(
426
+ () => adapter.unscheduleEditState({
427
+ hostEntityType: context.value.entityType,
428
+ hostEntityUuid: context.value.entityUuid
429
+ })
430
+ );
431
+ if (success) {
432
+ await refresh();
433
+ scheduleDate.value = previousScheduleDate;
434
+ }
435
+ isMutating.value = false;
436
+ }
199
437
  async function onSubmit() {
438
+ currentTimestamp.value = Date.now();
439
+ if (scheduleDateError.value) {
440
+ return;
441
+ }
200
442
  isMutating.value = true;
201
443
  const items = stateItems.value;
202
- let hasAnyError = false;
444
+ const hasAnyError = false;
445
+ let mutationResult = false;
203
446
  for (const item of items) {
204
447
  const isSelected = states.value.includes(item.id) || item.hostEntityType === context.value.entityType && item.hostEntityUuid === context.value.entityUuid;
205
448
  if (!isSelected) {
@@ -209,30 +452,29 @@ async function onSubmit() {
209
452
  continue;
210
453
  }
211
454
  try {
212
- const result = await adapter.publish({
213
- hostEntityType: item.hostEntityType,
214
- hostEntityUuid: item.hostEntityUuid,
215
- closeAfterPublish: true,
216
- revisionLogMessage: revisionMessage.value,
217
- publishIfUnpublished: shouldPublish.value
218
- });
219
- let violations = [];
220
- if (!result.success && result.state) {
221
- const mapped = adapter.mapState(result.state);
222
- if (mapped.mutatedState?.violations) {
223
- violations = mapped.mutatedState.violations;
455
+ if (publishMode.value === "scheduled") {
456
+ if (!adapter.scheduleEditState) {
457
+ throw new Error("scheduleEditState method not available");
224
458
  }
459
+ mutationResult = await state.mutateWithLoadingState(
460
+ () => adapter.scheduleEditState({
461
+ hostEntityType: item.hostEntityType,
462
+ hostEntityUuid: item.hostEntityUuid,
463
+ revisionLogMessage: revisionMessage.value,
464
+ date: scheduleDate.value
465
+ })
466
+ );
467
+ } else {
468
+ mutationResult = await state.mutateWithLoadingState(
469
+ () => adapter.publish({
470
+ hostEntityType: item.hostEntityType,
471
+ hostEntityUuid: item.hostEntityUuid,
472
+ closeAfterPublish: true,
473
+ revisionLogMessage: revisionMessage.value,
474
+ publishIfUnpublished: shouldPublish.value
475
+ })
476
+ );
225
477
  }
226
- mutationStatusItems.value[item.id] = {
227
- id: item.id,
228
- success: result.success,
229
- errors: result.errors,
230
- violations
231
- };
232
- if (result.success) {
233
- publishedIds.value.push(item.id);
234
- }
235
- hasAnyError ||= !result.success;
236
478
  } catch {
237
479
  mutationStatusItems.value[item.id] = {
238
480
  id: item.id,
@@ -244,9 +486,19 @@ async function onSubmit() {
244
486
  }
245
487
  }
246
488
  isMutating.value = false;
247
- if (hasAnyError) {
489
+ if (hasAnyError || !mutationResult) {
248
490
  return;
249
491
  }
250
- emit("submit");
492
+ if (publishMode.value === "scheduled") {
493
+ const formattedDate = ui.formatDate(scheduleDate.value);
494
+ const message = $t(
495
+ "publishScheduleSuccess",
496
+ "Publication scheduled for @date"
497
+ ).replace("@date", formattedDate);
498
+ emitMessage(message, "success");
499
+ emit("close");
500
+ } else {
501
+ emit("submit");
502
+ }
251
503
  }
252
504
  </script>