rimelight-components 2.1.88 → 2.1.90
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.
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -1
- package/dist/runtime/components/blocks/BlockEditor.d.vue.ts +3 -0
- package/dist/runtime/components/blocks/BlockEditor.vue +2 -2
- package/dist/runtime/components/blocks/BlockEditor.vue.d.ts +3 -0
- package/dist/runtime/components/page/PageEditor.d.vue.ts +8 -0
- package/dist/runtime/components/page/PageEditor.vue +39 -8
- package/dist/runtime/components/page/PageEditor.vue.d.ts +8 -0
- package/dist/runtime/components/page/PageVersionSelector.d.vue.ts +4 -4
- package/dist/runtime/components/page/PageVersionSelector.vue.d.ts +4 -4
- package/dist/runtime/components/page/modals/CreatePageModal.vue +3 -3
- package/dist/runtime/components/page/modals/DeletePageModal.d.vue.ts +9 -3
- package/dist/runtime/components/page/modals/DeletePageModal.vue +10 -7
- package/dist/runtime/components/page/modals/DeletePageModal.vue.d.ts +9 -3
- package/dist/runtime/components/page/modals/PageTreeModal.vue +31 -13
- package/dist/runtime/composables/pages/usePageEditor.d.ts +1 -0
- package/dist/runtime/composables/pages/usePageEditor.js +30 -9
- package/dist/runtime/composables/pages/usePageEditor.mjs +30 -9
- package/dist/runtime/locale/en.js +4 -0
- package/dist/runtime/locale/en.mjs +4 -0
- package/dist/runtime/types/pages.d.ts +1 -0
- package/dist/runtime/utils/page.d.ts +5 -1
- package/dist/runtime/utils/page.js +10 -0
- package/dist/runtime/utils/page.mjs +10 -0
- package/package.json +1 -1
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { readdirSync } from 'node:fs';
|
|
|
4
4
|
import { basename } from 'node:path';
|
|
5
5
|
|
|
6
6
|
const name = "rimelight-components";
|
|
7
|
-
const version = "2.1.
|
|
7
|
+
const version = "2.1.90";
|
|
8
8
|
const homepage = "https://rimelight.com/tools/rimelight-components";
|
|
9
9
|
|
|
10
10
|
const defaultOptions = {
|
|
@@ -6,6 +6,7 @@ export interface BlockEditorProps {
|
|
|
6
6
|
type __VLS_Props = BlockEditorProps;
|
|
7
7
|
export interface BlockEditorEmits {
|
|
8
8
|
save: [];
|
|
9
|
+
mutation: [];
|
|
9
10
|
}
|
|
10
11
|
export interface BlockEditorSlots {
|
|
11
12
|
}
|
|
@@ -21,9 +22,11 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
21
22
|
canRedo: import("vue").ComputedRef<boolean>;
|
|
22
23
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
23
24
|
save: () => any;
|
|
25
|
+
mutation: () => any;
|
|
24
26
|
"update:modelValue": (value: Block[]) => any;
|
|
25
27
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
26
28
|
onSave?: (() => any) | undefined;
|
|
29
|
+
onMutation?: (() => any) | undefined;
|
|
27
30
|
"onUpdate:modelValue"?: ((value: Block[]) => any) | undefined;
|
|
28
31
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
29
32
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -8,7 +8,7 @@ const { historyLimit, rc: rcProp } = defineProps({
|
|
|
8
8
|
rc: { type: Object, required: false }
|
|
9
9
|
});
|
|
10
10
|
const blocks = defineModel({ type: Array, ...{ required: true } });
|
|
11
|
-
const emit = defineEmits(["save"]);
|
|
11
|
+
const emit = defineEmits(["save", "mutation"]);
|
|
12
12
|
const slots = defineSlots();
|
|
13
13
|
const blockTypes = [
|
|
14
14
|
{ label: "Paragraph", value: "ParagraphBlock", icon: "i-lucide-pilcrow" },
|
|
@@ -31,7 +31,7 @@ const {
|
|
|
31
31
|
redo,
|
|
32
32
|
canUndo,
|
|
33
33
|
canRedo
|
|
34
|
-
} = useBlockEditor(blocks, { maxHistorySize: historyLimit });
|
|
34
|
+
} = useBlockEditor(blocks, { maxHistorySize: historyLimit, onMutation: () => emit("mutation") });
|
|
35
35
|
const dropdownItems = computed(() => [
|
|
36
36
|
blockTypes.map((type) => ({
|
|
37
37
|
label: type.label,
|
|
@@ -6,6 +6,7 @@ export interface BlockEditorProps {
|
|
|
6
6
|
type __VLS_Props = BlockEditorProps;
|
|
7
7
|
export interface BlockEditorEmits {
|
|
8
8
|
save: [];
|
|
9
|
+
mutation: [];
|
|
9
10
|
}
|
|
10
11
|
export interface BlockEditorSlots {
|
|
11
12
|
}
|
|
@@ -21,9 +22,11 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
21
22
|
canRedo: import("vue").ComputedRef<boolean>;
|
|
22
23
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
23
24
|
save: () => any;
|
|
25
|
+
mutation: () => any;
|
|
24
26
|
"update:modelValue": (value: Block[]) => any;
|
|
25
27
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
26
28
|
onSave?: (() => any) | undefined;
|
|
29
|
+
onMutation?: (() => any) | undefined;
|
|
27
30
|
"onUpdate:modelValue"?: ((value: Block[]) => any) | undefined;
|
|
28
31
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
29
32
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -10,6 +10,7 @@ export interface PageEditorProps {
|
|
|
10
10
|
onDeletePage?: (id: string) => Promise<void>;
|
|
11
11
|
onFetchPages?: () => Promise<Pick<Page, 'title' | 'slug'>[]>;
|
|
12
12
|
onNavigateToPage?: (slug: string) => void;
|
|
13
|
+
onViewPage?: (slug: string) => void;
|
|
13
14
|
currentVersionId?: string | null;
|
|
14
15
|
isViewingVersion?: boolean;
|
|
15
16
|
isAdmin?: boolean;
|
|
@@ -37,6 +38,8 @@ type __VLS_Props = PageEditorProps;
|
|
|
37
38
|
export interface PageEditorEmits {
|
|
38
39
|
save: [value: Page];
|
|
39
40
|
'version-navigate': [version: PageVersion];
|
|
41
|
+
'version-approved': [version: PageVersion];
|
|
42
|
+
'version-reverted': [version: PageVersion];
|
|
40
43
|
}
|
|
41
44
|
export interface PageEditorSlots {
|
|
42
45
|
'header-actions'?: (props: {}) => any;
|
|
@@ -52,6 +55,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
52
55
|
redo: () => void;
|
|
53
56
|
canUndo: import("vue").ComputedRef<boolean>;
|
|
54
57
|
canRedo: import("vue").ComputedRef<boolean>;
|
|
58
|
+
resetHistory: () => void;
|
|
55
59
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
56
60
|
save: (value: {
|
|
57
61
|
type: "Default";
|
|
@@ -62,6 +66,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
62
66
|
properties: import("../../types/index.js").BasePageProperties;
|
|
63
67
|
} & import("../../types/index.js").BasePage) => any;
|
|
64
68
|
"version-navigate": (version: PageVersion) => any;
|
|
69
|
+
"version-approved": (version: PageVersion) => any;
|
|
70
|
+
"version-reverted": (version: PageVersion) => any;
|
|
65
71
|
"update:currentVersionId": (value: string | null) => any;
|
|
66
72
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
67
73
|
onSave?: ((value: {
|
|
@@ -73,6 +79,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
73
79
|
properties: import("../../types/index.js").BasePageProperties;
|
|
74
80
|
} & import("../../types/index.js").BasePage) => any) | undefined;
|
|
75
81
|
"onVersion-navigate"?: ((version: PageVersion) => any) | undefined;
|
|
82
|
+
"onVersion-approved"?: ((version: PageVersion) => any) | undefined;
|
|
83
|
+
"onVersion-reverted"?: ((version: PageVersion) => any) | undefined;
|
|
76
84
|
"onUpdate:currentVersionId"?: ((value: string | null) => any) | undefined;
|
|
77
85
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
78
86
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { ref, computed, useTemplateRef, provide } from "vue";
|
|
3
|
+
import { navigateTo } from "#imports";
|
|
3
4
|
import {} from "../../types";
|
|
4
|
-
import { usePageEditor, usePageRegistry, useRC, useHeaderStack } from "../../composables";
|
|
5
|
+
import { usePageEditor, usePageRegistry, useRC, useHeaderStack, useConfirm } from "../../composables";
|
|
5
6
|
import { getLocalizedContent } from "../../utils";
|
|
6
7
|
import { useI18n } from "vue-i18n";
|
|
7
8
|
import { tv } from "../../internal/tv";
|
|
@@ -15,6 +16,7 @@ const {
|
|
|
15
16
|
onDeletePage,
|
|
16
17
|
onFetchPages,
|
|
17
18
|
onNavigateToPage,
|
|
19
|
+
onViewPage,
|
|
18
20
|
currentVersionId = null,
|
|
19
21
|
isViewingVersion = false,
|
|
20
22
|
isAdmin = false,
|
|
@@ -30,6 +32,7 @@ const {
|
|
|
30
32
|
onDeletePage: { type: Function, required: false },
|
|
31
33
|
onFetchPages: { type: Function, required: false },
|
|
32
34
|
onNavigateToPage: { type: Function, required: false },
|
|
35
|
+
onViewPage: { type: Function, required: false },
|
|
33
36
|
currentVersionId: { type: [String, null], required: false },
|
|
34
37
|
isViewingVersion: { type: Boolean, required: false },
|
|
35
38
|
isAdmin: { type: Boolean, required: false },
|
|
@@ -37,7 +40,7 @@ const {
|
|
|
37
40
|
});
|
|
38
41
|
const page = defineModel({ type: null, ...{ required: true } });
|
|
39
42
|
const versionId = defineModel("currentVersionId", { type: [String, null], ...{ default: null } });
|
|
40
|
-
const emit = defineEmits(["save", "version-navigate"]);
|
|
43
|
+
const emit = defineEmits(["save", "version-navigate", "version-approved", "version-reverted"]);
|
|
41
44
|
const slots = defineSlots();
|
|
42
45
|
const { rc } = useRC("PageEditor", rcProp);
|
|
43
46
|
const pageEditorStyles = tv({
|
|
@@ -82,7 +85,25 @@ const {
|
|
|
82
85
|
} = pageEditorStyles();
|
|
83
86
|
const { getTypeLabelKey } = usePageRegistry();
|
|
84
87
|
const { t, locale } = useI18n();
|
|
85
|
-
const { undo, redo, canUndo, canRedo, captureSnapshot } = usePageEditor(page);
|
|
88
|
+
const { undo, redo, canUndo, canRedo, captureSnapshot, resetHistory } = usePageEditor(page);
|
|
89
|
+
const { confirm } = useConfirm();
|
|
90
|
+
const handleViewPage = async () => {
|
|
91
|
+
if (canUndo.value) {
|
|
92
|
+
const confirmed = await confirm({
|
|
93
|
+
title: t("page_editor.unsaved_changes_title"),
|
|
94
|
+
description: t("page_editor.unsaved_changes_description"),
|
|
95
|
+
confirmLabel: t("page_editor.leave_anyway"),
|
|
96
|
+
cancelLabel: t("common.cancel"),
|
|
97
|
+
danger: true
|
|
98
|
+
});
|
|
99
|
+
if (!confirmed) return;
|
|
100
|
+
}
|
|
101
|
+
if (onViewPage) {
|
|
102
|
+
onViewPage(page.value.slug);
|
|
103
|
+
} else {
|
|
104
|
+
navigateTo(`/${page.value.slug}`);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
86
107
|
const handleSave = () => {
|
|
87
108
|
const dataToPersist = JSON.parse(JSON.stringify(page.value));
|
|
88
109
|
emit("save", dataToPersist);
|
|
@@ -91,7 +112,8 @@ defineExpose({
|
|
|
91
112
|
undo,
|
|
92
113
|
redo,
|
|
93
114
|
canUndo,
|
|
94
|
-
canRedo
|
|
115
|
+
canRedo,
|
|
116
|
+
resetHistory
|
|
95
117
|
});
|
|
96
118
|
const editorRef = useTemplateRef("editor");
|
|
97
119
|
const showPreview = ref(false);
|
|
@@ -232,6 +254,14 @@ const handleTreeNavigate = (slug) => {
|
|
|
232
254
|
size="xs"
|
|
233
255
|
@click="showPreview = !showPreview"
|
|
234
256
|
/>
|
|
257
|
+
<UButton
|
|
258
|
+
icon="lucide:external-link"
|
|
259
|
+
:label="t('page_editor.view_page')"
|
|
260
|
+
variant="outline"
|
|
261
|
+
color="neutral"
|
|
262
|
+
size="xs"
|
|
263
|
+
@click="handleViewPage"
|
|
264
|
+
/>
|
|
235
265
|
<UButton
|
|
236
266
|
icon="lucide:save"
|
|
237
267
|
:label="t('page_editor.save')"
|
|
@@ -261,22 +291,22 @@ const handleTreeNavigate = (slug) => {
|
|
|
261
291
|
:page-id="page.id"
|
|
262
292
|
:is-admin="isAdmin"
|
|
263
293
|
@version-selected="(v) => emit('version-navigate', v)"
|
|
294
|
+
@version-approved="(v) => emit('version-approved', v)"
|
|
295
|
+
@version-reverted="(v) => emit('version-reverted', v)"
|
|
264
296
|
/>
|
|
265
297
|
<slot name="header-actions" />
|
|
266
298
|
<RCCreatePageModal
|
|
267
|
-
:
|
|
299
|
+
v-model:open="isCreateModalOpen"
|
|
268
300
|
:definitions="pageDefinitions"
|
|
269
301
|
:loading="isCreating"
|
|
270
|
-
@close="isCreateModalOpen = false"
|
|
271
302
|
@confirm="handleCreateConfirm"
|
|
272
303
|
>
|
|
273
304
|
<UButton icon="lucide:file-plus" :label="t('page_editor.create_page')" color="primary" size="xs" />
|
|
274
305
|
</RCCreatePageModal>
|
|
275
306
|
<RCDeletePageModal
|
|
276
|
-
:
|
|
307
|
+
v-model:open="isDeleteModalOpen"
|
|
277
308
|
:loading="isDeleting"
|
|
278
309
|
:page-title="getLocalizedContent(page.title, locale)"
|
|
279
|
-
@close="isDeleteModalOpen = false"
|
|
280
310
|
@confirm="handleDeleteConfirm"
|
|
281
311
|
>
|
|
282
312
|
<UButton icon="lucide:file-plus" :label="t('page_editor.delete_page')" color="error" size="xs" />
|
|
@@ -420,4 +450,5 @@ const handleTreeNavigate = (slug) => {
|
|
|
420
450
|
/>
|
|
421
451
|
</div>
|
|
422
452
|
</div>
|
|
453
|
+
<RCConfirmModal />
|
|
423
454
|
</template>
|
|
@@ -10,6 +10,7 @@ export interface PageEditorProps {
|
|
|
10
10
|
onDeletePage?: (id: string) => Promise<void>;
|
|
11
11
|
onFetchPages?: () => Promise<Pick<Page, 'title' | 'slug'>[]>;
|
|
12
12
|
onNavigateToPage?: (slug: string) => void;
|
|
13
|
+
onViewPage?: (slug: string) => void;
|
|
13
14
|
currentVersionId?: string | null;
|
|
14
15
|
isViewingVersion?: boolean;
|
|
15
16
|
isAdmin?: boolean;
|
|
@@ -37,6 +38,8 @@ type __VLS_Props = PageEditorProps;
|
|
|
37
38
|
export interface PageEditorEmits {
|
|
38
39
|
save: [value: Page];
|
|
39
40
|
'version-navigate': [version: PageVersion];
|
|
41
|
+
'version-approved': [version: PageVersion];
|
|
42
|
+
'version-reverted': [version: PageVersion];
|
|
40
43
|
}
|
|
41
44
|
export interface PageEditorSlots {
|
|
42
45
|
'header-actions'?: (props: {}) => any;
|
|
@@ -52,6 +55,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
52
55
|
redo: () => void;
|
|
53
56
|
canUndo: import("vue").ComputedRef<boolean>;
|
|
54
57
|
canRedo: import("vue").ComputedRef<boolean>;
|
|
58
|
+
resetHistory: () => void;
|
|
55
59
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
56
60
|
save: (value: {
|
|
57
61
|
type: "Default";
|
|
@@ -62,6 +66,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
62
66
|
properties: import("../../types/index.js").BasePageProperties;
|
|
63
67
|
} & import("../../types/index.js").BasePage) => any;
|
|
64
68
|
"version-navigate": (version: PageVersion) => any;
|
|
69
|
+
"version-approved": (version: PageVersion) => any;
|
|
70
|
+
"version-reverted": (version: PageVersion) => any;
|
|
65
71
|
"update:currentVersionId": (value: string | null) => any;
|
|
66
72
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
67
73
|
onSave?: ((value: {
|
|
@@ -73,6 +79,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
73
79
|
properties: import("../../types/index.js").BasePageProperties;
|
|
74
80
|
} & import("../../types/index.js").BasePage) => any) | undefined;
|
|
75
81
|
"onVersion-navigate"?: ((version: PageVersion) => any) | undefined;
|
|
82
|
+
"onVersion-approved"?: ((version: PageVersion) => any) | undefined;
|
|
83
|
+
"onVersion-reverted"?: ((version: PageVersion) => any) | undefined;
|
|
76
84
|
"onUpdate:currentVersionId"?: ((value: string | null) => any) | undefined;
|
|
77
85
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
78
86
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -11,15 +11,15 @@ export interface PageVersionSelectorProps {
|
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
declare const __VLS_export: import("vue").DefineComponent<PageVersionSelectorProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
-
"update:currentVersionId": (value: string | null) => any;
|
|
15
|
-
"version-selected": (version: PageVersion) => any;
|
|
16
14
|
"version-approved": (version: PageVersion) => any;
|
|
17
15
|
"version-reverted": (version: PageVersion) => any;
|
|
16
|
+
"update:currentVersionId": (value: string | null) => any;
|
|
17
|
+
"version-selected": (version: PageVersion) => any;
|
|
18
18
|
}, string, import("vue").PublicProps, Readonly<PageVersionSelectorProps> & Readonly<{
|
|
19
|
-
"onUpdate:currentVersionId"?: ((value: string | null) => any) | undefined;
|
|
20
|
-
"onVersion-selected"?: ((version: PageVersion) => any) | undefined;
|
|
21
19
|
"onVersion-approved"?: ((version: PageVersion) => any) | undefined;
|
|
22
20
|
"onVersion-reverted"?: ((version: PageVersion) => any) | undefined;
|
|
21
|
+
"onUpdate:currentVersionId"?: ((value: string | null) => any) | undefined;
|
|
22
|
+
"onVersion-selected"?: ((version: PageVersion) => any) | undefined;
|
|
23
23
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
24
24
|
declare const _default: typeof __VLS_export;
|
|
25
25
|
export default _default;
|
|
@@ -11,15 +11,15 @@ export interface PageVersionSelectorProps {
|
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
declare const __VLS_export: import("vue").DefineComponent<PageVersionSelectorProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
14
|
-
"update:currentVersionId": (value: string | null) => any;
|
|
15
|
-
"version-selected": (version: PageVersion) => any;
|
|
16
14
|
"version-approved": (version: PageVersion) => any;
|
|
17
15
|
"version-reverted": (version: PageVersion) => any;
|
|
16
|
+
"update:currentVersionId": (value: string | null) => any;
|
|
17
|
+
"version-selected": (version: PageVersion) => any;
|
|
18
18
|
}, string, import("vue").PublicProps, Readonly<PageVersionSelectorProps> & Readonly<{
|
|
19
|
-
"onUpdate:currentVersionId"?: ((value: string | null) => any) | undefined;
|
|
20
|
-
"onVersion-selected"?: ((version: PageVersion) => any) | undefined;
|
|
21
19
|
"onVersion-approved"?: ((version: PageVersion) => any) | undefined;
|
|
22
20
|
"onVersion-reverted"?: ((version: PageVersion) => any) | undefined;
|
|
21
|
+
"onUpdate:currentVersionId"?: ((value: string | null) => any) | undefined;
|
|
22
|
+
"onVersion-selected"?: ((version: PageVersion) => any) | undefined;
|
|
23
23
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
24
24
|
declare const _default: typeof __VLS_export;
|
|
25
25
|
export default _default;
|
|
@@ -85,9 +85,9 @@ watch(open, (isOpen) => {
|
|
|
85
85
|
<UButton
|
|
86
86
|
color="neutral"
|
|
87
87
|
variant="ghost"
|
|
88
|
-
icon="
|
|
88
|
+
icon="lucide:x"
|
|
89
89
|
:class="closeButton({ class: rc.closeButton })"
|
|
90
|
-
@click="
|
|
90
|
+
@click="open = false"
|
|
91
91
|
/>
|
|
92
92
|
</div>
|
|
93
93
|
</template>
|
|
@@ -113,7 +113,7 @@ watch(open, (isOpen) => {
|
|
|
113
113
|
|
|
114
114
|
<template #footer>
|
|
115
115
|
<div :class="footer({ class: rc.footer })">
|
|
116
|
-
<UButton color="neutral" variant="ghost" :label="t('common.cancel')" @click="
|
|
116
|
+
<UButton color="neutral" variant="ghost" :label="t('common.cancel')" @click="open = false" />
|
|
117
117
|
<UButton
|
|
118
118
|
color="primary"
|
|
119
119
|
:label="t('page_properties.create_and_edit')"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export interface DeletePageModalProps {
|
|
2
|
-
isOpen: boolean;
|
|
3
2
|
loading?: boolean;
|
|
4
3
|
pageTitle: string;
|
|
5
4
|
rc?: {
|
|
@@ -10,6 +9,7 @@ export interface DeletePageModalProps {
|
|
|
10
9
|
footer?: string;
|
|
11
10
|
};
|
|
12
11
|
}
|
|
12
|
+
type __VLS_Props = DeletePageModalProps;
|
|
13
13
|
export interface DeletePageModalEmits {
|
|
14
14
|
close: [];
|
|
15
15
|
confirm: [];
|
|
@@ -18,11 +18,17 @@ export interface DeletePageModalSlots {
|
|
|
18
18
|
default: (props: {}) => any;
|
|
19
19
|
}
|
|
20
20
|
type __VLS_Slots = DeletePageModalSlots;
|
|
21
|
-
|
|
21
|
+
type __VLS_ModelProps = {
|
|
22
|
+
"open"?: boolean;
|
|
23
|
+
};
|
|
24
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
25
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
22
26
|
close: () => any;
|
|
27
|
+
"update:open": (value: boolean) => any;
|
|
23
28
|
confirm: () => any;
|
|
24
|
-
}, string, import("vue").PublicProps, Readonly<
|
|
29
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
25
30
|
onClose?: (() => any) | undefined;
|
|
31
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
26
32
|
onConfirm?: (() => any) | undefined;
|
|
27
33
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
34
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -3,8 +3,8 @@ import { ref, watch } from "vue";
|
|
|
3
3
|
import { useI18n } from "vue-i18n";
|
|
4
4
|
import { tv } from "../../../internal/tv";
|
|
5
5
|
import { useRC } from "../../../composables";
|
|
6
|
-
const
|
|
7
|
-
|
|
6
|
+
const open = defineModel("open", { type: Boolean, ...{ default: false } });
|
|
7
|
+
const { loading, pageTitle, rc: rcProp } = defineProps({
|
|
8
8
|
loading: { type: Boolean, required: false },
|
|
9
9
|
pageTitle: { type: String, required: true },
|
|
10
10
|
rc: { type: Object, required: false }
|
|
@@ -31,8 +31,11 @@ const {
|
|
|
31
31
|
const { t } = useI18n();
|
|
32
32
|
const confirmationInput = ref("");
|
|
33
33
|
const CONFIRMATION_TEXT = "DELETE";
|
|
34
|
-
watch(
|
|
35
|
-
if (!val)
|
|
34
|
+
watch(open, (val) => {
|
|
35
|
+
if (!val) {
|
|
36
|
+
confirmationInput.value = "";
|
|
37
|
+
emits("close");
|
|
38
|
+
}
|
|
36
39
|
});
|
|
37
40
|
const handleConfirm = () => {
|
|
38
41
|
if (confirmationInput.value === CONFIRMATION_TEXT) {
|
|
@@ -42,7 +45,7 @@ const handleConfirm = () => {
|
|
|
42
45
|
</script>
|
|
43
46
|
|
|
44
47
|
<template>
|
|
45
|
-
<UModal
|
|
48
|
+
<UModal v-model:open="open">
|
|
46
49
|
<slot />
|
|
47
50
|
<template #content>
|
|
48
51
|
<UCard :ui="{ body: 'space-y-4' }">
|
|
@@ -56,7 +59,7 @@ const handleConfirm = () => {
|
|
|
56
59
|
variant="ghost"
|
|
57
60
|
icon="lucide:x"
|
|
58
61
|
:class="closeButton({ class: rc.closeButton })"
|
|
59
|
-
@click="
|
|
62
|
+
@click="open = false"
|
|
60
63
|
/>
|
|
61
64
|
</div>
|
|
62
65
|
</template>
|
|
@@ -87,7 +90,7 @@ const handleConfirm = () => {
|
|
|
87
90
|
color="neutral"
|
|
88
91
|
variant="ghost"
|
|
89
92
|
:label="t('common.cancel', 'Cancel')"
|
|
90
|
-
@click="
|
|
93
|
+
@click="open = false"
|
|
91
94
|
/>
|
|
92
95
|
<UButton
|
|
93
96
|
color="error"
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export interface DeletePageModalProps {
|
|
2
|
-
isOpen: boolean;
|
|
3
2
|
loading?: boolean;
|
|
4
3
|
pageTitle: string;
|
|
5
4
|
rc?: {
|
|
@@ -10,6 +9,7 @@ export interface DeletePageModalProps {
|
|
|
10
9
|
footer?: string;
|
|
11
10
|
};
|
|
12
11
|
}
|
|
12
|
+
type __VLS_Props = DeletePageModalProps;
|
|
13
13
|
export interface DeletePageModalEmits {
|
|
14
14
|
close: [];
|
|
15
15
|
confirm: [];
|
|
@@ -18,11 +18,17 @@ export interface DeletePageModalSlots {
|
|
|
18
18
|
default: (props: {}) => any;
|
|
19
19
|
}
|
|
20
20
|
type __VLS_Slots = DeletePageModalSlots;
|
|
21
|
-
|
|
21
|
+
type __VLS_ModelProps = {
|
|
22
|
+
"open"?: boolean;
|
|
23
|
+
};
|
|
24
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
25
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
22
26
|
close: () => any;
|
|
27
|
+
"update:open": (value: boolean) => any;
|
|
23
28
|
confirm: () => any;
|
|
24
|
-
}, string, import("vue").PublicProps, Readonly<
|
|
29
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
25
30
|
onClose?: (() => any) | undefined;
|
|
31
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
26
32
|
onConfirm?: (() => any) | undefined;
|
|
27
33
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
34
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -32,6 +32,7 @@ const treeItems = computed(() => {
|
|
|
32
32
|
const label = pageObj ? getLocalizedContent(pageObj.title, locale.value) || partLabel : partLabel.charAt(0).toUpperCase() + partLabel.slice(1);
|
|
33
33
|
const newNode = {
|
|
34
34
|
label,
|
|
35
|
+
path,
|
|
35
36
|
slug: pageObj ? pageObj.slug : void 0,
|
|
36
37
|
icon: pageObj ? "i-lucide-file" : "i-lucide-folder",
|
|
37
38
|
children: []
|
|
@@ -67,15 +68,28 @@ const treeItems = computed(() => {
|
|
|
67
68
|
parent = node;
|
|
68
69
|
});
|
|
69
70
|
});
|
|
70
|
-
const
|
|
71
|
+
const processNodes = (nodes) => {
|
|
71
72
|
nodes.sort((a, b) => a.label.localeCompare(b.label));
|
|
72
|
-
nodes
|
|
73
|
-
if (
|
|
74
|
-
|
|
73
|
+
for (const node of nodes) {
|
|
74
|
+
if (node.slug && node.children && node.children.length > 0) {
|
|
75
|
+
const indexNode = {
|
|
76
|
+
label: node.label,
|
|
77
|
+
// Or t('common.overview') / same name
|
|
78
|
+
slug: node.slug,
|
|
79
|
+
path: `${node.path}:index`,
|
|
80
|
+
icon: "i-lucide-file-text",
|
|
81
|
+
children: []
|
|
82
|
+
};
|
|
83
|
+
node.children.unshift(indexNode);
|
|
84
|
+
node.slug = void 0;
|
|
85
|
+
node.icon = "i-lucide-folder";
|
|
75
86
|
}
|
|
76
|
-
|
|
87
|
+
if (node.children && node.children.length > 0) {
|
|
88
|
+
processNodes(node.children);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
77
91
|
};
|
|
78
|
-
|
|
92
|
+
processNodes(rootNodes);
|
|
79
93
|
return rootNodes;
|
|
80
94
|
});
|
|
81
95
|
const handleSelect = (node) => {
|
|
@@ -84,7 +98,7 @@ const handleSelect = (node) => {
|
|
|
84
98
|
open.value = false;
|
|
85
99
|
}
|
|
86
100
|
};
|
|
87
|
-
const getKey = (item) => item.
|
|
101
|
+
const getKey = (item) => item.path;
|
|
88
102
|
</script>
|
|
89
103
|
|
|
90
104
|
<template>
|
|
@@ -97,7 +111,7 @@ const getKey = (item) => item.slug || item.label;
|
|
|
97
111
|
<UButton
|
|
98
112
|
color="neutral"
|
|
99
113
|
variant="ghost"
|
|
100
|
-
icon="
|
|
114
|
+
icon="lucide:x"
|
|
101
115
|
:class="closeButton({ class: rc.closeButton })"
|
|
102
116
|
@click="open = false"
|
|
103
117
|
/>
|
|
@@ -114,12 +128,16 @@ const getKey = (item) => item.slug || item.label;
|
|
|
114
128
|
<UTree
|
|
115
129
|
v-else
|
|
116
130
|
:items="treeItems"
|
|
117
|
-
:
|
|
131
|
+
:get-key="getKey"
|
|
132
|
+
:ui="{
|
|
133
|
+
item: 'cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800',
|
|
134
|
+
linkLabel: 'w-full'
|
|
135
|
+
}"
|
|
136
|
+
@select="(e, item2) => handleSelect(item2)"
|
|
118
137
|
>
|
|
119
|
-
<template #item="{ item }">
|
|
120
|
-
<div class="flex items-center gap-2 py-1 w-full"
|
|
121
|
-
<
|
|
122
|
-
<span :class="{ 'text-gray-900 dark:text-gray-100': item.slug, 'text-gray-500 font-medium': !item.slug }">
|
|
138
|
+
<template #item-label="{ item }">
|
|
139
|
+
<div class="flex items-center gap-2 py-1 w-full">
|
|
140
|
+
<span :class="{ 'text-gray-900 dark:text-gray-100 font-medium': item.slug, 'text-gray-400': !item.slug }">
|
|
123
141
|
{{ item.label }}
|
|
124
142
|
</span>
|
|
125
143
|
<UIcon v-if="item.slug" name="i-heroicons-arrow-right-20-solid" class="w-3 h-3 ml-auto text-gray-300 opacity-0 group-hover:opacity-100" />
|
|
@@ -2,23 +2,38 @@ import { computed, shallowRef, watch } from "vue";
|
|
|
2
2
|
export function usePageEditor(page, maxHistorySize = 100) {
|
|
3
3
|
const history = shallowRef([]);
|
|
4
4
|
const future = shallowRef([]);
|
|
5
|
+
let lastCapturedState = JSON.stringify(page.value);
|
|
5
6
|
const captureSnapshot = () => {
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
7
|
+
const currentSnapshot = JSON.stringify(page.value);
|
|
8
|
+
if (currentSnapshot === lastCapturedState) return;
|
|
8
9
|
future.value = [];
|
|
9
|
-
const newHistory = [...history.value,
|
|
10
|
+
const newHistory = [...history.value, lastCapturedState];
|
|
10
11
|
if (newHistory.length > maxHistorySize) newHistory.shift();
|
|
11
12
|
history.value = newHistory;
|
|
13
|
+
lastCapturedState = currentSnapshot;
|
|
12
14
|
};
|
|
13
15
|
const undo = () => {
|
|
14
16
|
if (history.value.length === 0) return;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
const currentState = JSON.stringify(page.value);
|
|
18
|
+
future.value = [currentState, ...future.value];
|
|
19
|
+
const previousStateString = history.value[history.value.length - 1];
|
|
20
|
+
lastCapturedState = previousStateString;
|
|
21
|
+
page.value = JSON.parse(previousStateString);
|
|
22
|
+
const newHistory = [...history.value];
|
|
23
|
+
newHistory.pop();
|
|
24
|
+
history.value = newHistory;
|
|
17
25
|
};
|
|
18
26
|
const redo = () => {
|
|
19
27
|
if (future.value.length === 0) return;
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
const currentState = JSON.stringify(page.value);
|
|
29
|
+
history.value = [...history.value, currentState];
|
|
30
|
+
lastCapturedState = currentState;
|
|
31
|
+
const nextStateString = future.value[0];
|
|
32
|
+
page.value = JSON.parse(nextStateString);
|
|
33
|
+
lastCapturedState = nextStateString;
|
|
34
|
+
const newFuture = [...future.value];
|
|
35
|
+
newFuture.shift();
|
|
36
|
+
future.value = newFuture;
|
|
22
37
|
};
|
|
23
38
|
const canUndo = computed(() => history.value.length > 0);
|
|
24
39
|
const canRedo = computed(() => future.value.length > 0);
|
|
@@ -26,18 +41,24 @@ export function usePageEditor(page, maxHistorySize = 100) {
|
|
|
26
41
|
return JSON.parse(JSON.stringify(page.value));
|
|
27
42
|
};
|
|
28
43
|
watch(
|
|
29
|
-
() => page.value.properties,
|
|
44
|
+
[() => page.value.properties, () => page.value.title, () => page.value.blocks],
|
|
30
45
|
() => {
|
|
31
46
|
captureSnapshot();
|
|
32
47
|
},
|
|
33
48
|
{ deep: true }
|
|
34
49
|
);
|
|
50
|
+
const resetHistory = () => {
|
|
51
|
+
history.value = [];
|
|
52
|
+
future.value = [];
|
|
53
|
+
lastCapturedState = JSON.stringify(page.value);
|
|
54
|
+
};
|
|
35
55
|
return {
|
|
36
56
|
undo,
|
|
37
57
|
redo,
|
|
38
58
|
canUndo,
|
|
39
59
|
canRedo,
|
|
40
60
|
save,
|
|
41
|
-
captureSnapshot
|
|
61
|
+
captureSnapshot,
|
|
62
|
+
resetHistory
|
|
42
63
|
};
|
|
43
64
|
}
|
|
@@ -2,23 +2,38 @@ import { computed, shallowRef, watch } from "vue";
|
|
|
2
2
|
export function usePageEditor(page, maxHistorySize = 100) {
|
|
3
3
|
const history = shallowRef([]);
|
|
4
4
|
const future = shallowRef([]);
|
|
5
|
+
let lastCapturedState = JSON.stringify(page.value);
|
|
5
6
|
const captureSnapshot = () => {
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
7
|
+
const currentSnapshot = JSON.stringify(page.value);
|
|
8
|
+
if (currentSnapshot === lastCapturedState) return;
|
|
8
9
|
future.value = [];
|
|
9
|
-
const newHistory = [...history.value,
|
|
10
|
+
const newHistory = [...history.value, lastCapturedState];
|
|
10
11
|
if (newHistory.length > maxHistorySize) newHistory.shift();
|
|
11
12
|
history.value = newHistory;
|
|
13
|
+
lastCapturedState = currentSnapshot;
|
|
12
14
|
};
|
|
13
15
|
const undo = () => {
|
|
14
16
|
if (history.value.length === 0) return;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
const currentState = JSON.stringify(page.value);
|
|
18
|
+
future.value = [currentState, ...future.value];
|
|
19
|
+
const previousStateString = history.value[history.value.length - 1];
|
|
20
|
+
lastCapturedState = previousStateString;
|
|
21
|
+
page.value = JSON.parse(previousStateString);
|
|
22
|
+
const newHistory = [...history.value];
|
|
23
|
+
newHistory.pop();
|
|
24
|
+
history.value = newHistory;
|
|
17
25
|
};
|
|
18
26
|
const redo = () => {
|
|
19
27
|
if (future.value.length === 0) return;
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
const currentState = JSON.stringify(page.value);
|
|
29
|
+
history.value = [...history.value, currentState];
|
|
30
|
+
lastCapturedState = currentState;
|
|
31
|
+
const nextStateString = future.value[0];
|
|
32
|
+
page.value = JSON.parse(nextStateString);
|
|
33
|
+
lastCapturedState = nextStateString;
|
|
34
|
+
const newFuture = [...future.value];
|
|
35
|
+
newFuture.shift();
|
|
36
|
+
future.value = newFuture;
|
|
22
37
|
};
|
|
23
38
|
const canUndo = computed(() => history.value.length > 0);
|
|
24
39
|
const canRedo = computed(() => future.value.length > 0);
|
|
@@ -26,18 +41,24 @@ export function usePageEditor(page, maxHistorySize = 100) {
|
|
|
26
41
|
return JSON.parse(JSON.stringify(page.value));
|
|
27
42
|
};
|
|
28
43
|
watch(
|
|
29
|
-
() => page.value.properties,
|
|
44
|
+
[() => page.value.properties, () => page.value.title, () => page.value.blocks],
|
|
30
45
|
() => {
|
|
31
46
|
captureSnapshot();
|
|
32
47
|
},
|
|
33
48
|
{ deep: true }
|
|
34
49
|
);
|
|
50
|
+
const resetHistory = () => {
|
|
51
|
+
history.value = [];
|
|
52
|
+
future.value = [];
|
|
53
|
+
lastCapturedState = JSON.stringify(page.value);
|
|
54
|
+
};
|
|
35
55
|
return {
|
|
36
56
|
undo,
|
|
37
57
|
redo,
|
|
38
58
|
canUndo,
|
|
39
59
|
canRedo,
|
|
40
60
|
save,
|
|
41
|
-
captureSnapshot
|
|
61
|
+
captureSnapshot,
|
|
62
|
+
resetHistory
|
|
42
63
|
};
|
|
43
64
|
}
|
|
@@ -47,10 +47,14 @@ export default defineLocale({
|
|
|
47
47
|
},
|
|
48
48
|
page_editor: {
|
|
49
49
|
preview: "Preview",
|
|
50
|
+
view_page: "View Page",
|
|
50
51
|
save: "Save",
|
|
51
52
|
create_page: "Create Page",
|
|
52
53
|
delete_page: "Delete Page",
|
|
53
54
|
viewing_version_notice: "Viewing a previous version. Changes made here will create a new version.",
|
|
55
|
+
unsaved_changes_title: "Unsaved Changes",
|
|
56
|
+
unsaved_changes_description: "You have unsaved changes. Are you sure you want to leave?",
|
|
57
|
+
leave_anyway: "Leave Anyway",
|
|
54
58
|
metadata: "Metadata",
|
|
55
59
|
page_id: "Page ID",
|
|
56
60
|
created_at: "Created At",
|
|
@@ -47,10 +47,14 @@ export default defineLocale({
|
|
|
47
47
|
},
|
|
48
48
|
page_editor: {
|
|
49
49
|
preview: "Preview",
|
|
50
|
+
view_page: "View Page",
|
|
50
51
|
save: "Save",
|
|
51
52
|
create_page: "Create Page",
|
|
52
53
|
delete_page: "Delete Page",
|
|
53
54
|
viewing_version_notice: "Viewing a previous version. Changes made here will create a new version.",
|
|
55
|
+
unsaved_changes_title: "Unsaved Changes",
|
|
56
|
+
unsaved_changes_description: "You have unsaved changes. Are you sure you want to leave?",
|
|
57
|
+
leave_anyway: "Leave Anyway",
|
|
54
58
|
metadata: "Metadata",
|
|
55
59
|
page_id: "Page ID",
|
|
56
60
|
created_at: "Created At",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type MaybeRefOrGetter } from "vue";
|
|
2
|
-
import { type Localized, type Page, type PageDefinition, type Property } from "../types/index.js";
|
|
2
|
+
import { type Localized, type Page, type PageDefinition, type PageVersion, type Property } from "../types/index.js";
|
|
3
3
|
export declare const getLocalizedContent: <T = string>(field: Localized<T> | undefined, currentLocale: MaybeRefOrGetter<string>) => T | string;
|
|
4
4
|
type WidenProperty<T> = T extends string ? string : T extends number ? number : T extends never[] ? Localized[] : T extends object ? {
|
|
5
5
|
[K in keyof T]: WidenProperty<T[K]>;
|
|
@@ -27,4 +27,8 @@ export declare function definePageDefinition<T extends PageDefinition>(def: T):
|
|
|
27
27
|
* - Removes templated blocks no longer in the definition.
|
|
28
28
|
*/
|
|
29
29
|
export declare function syncPageWithDefinition(page: Page, definition?: PageDefinition): Page;
|
|
30
|
+
/**
|
|
31
|
+
* Converts a PageVersion to a Page structure for display in the editor.
|
|
32
|
+
*/
|
|
33
|
+
export declare function convertVersionToPage(version: PageVersion): Page;
|
|
30
34
|
export {};
|
|
@@ -81,3 +81,13 @@ export function syncPageWithDefinition(page, definition) {
|
|
|
81
81
|
}
|
|
82
82
|
return page;
|
|
83
83
|
}
|
|
84
|
+
export function convertVersionToPage(version) {
|
|
85
|
+
return {
|
|
86
|
+
...version,
|
|
87
|
+
id: version.pageId,
|
|
88
|
+
type: version.type,
|
|
89
|
+
blocks: version.content?.blocks || version.blocks,
|
|
90
|
+
properties: version.content?.properties,
|
|
91
|
+
authorsIds: version.authorsIds
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -81,3 +81,13 @@ export function syncPageWithDefinition(page, definition) {
|
|
|
81
81
|
}
|
|
82
82
|
return page;
|
|
83
83
|
}
|
|
84
|
+
export function convertVersionToPage(version) {
|
|
85
|
+
return {
|
|
86
|
+
...version,
|
|
87
|
+
id: version.pageId,
|
|
88
|
+
type: version.type,
|
|
89
|
+
blocks: version.content?.blocks || version.blocks,
|
|
90
|
+
properties: version.content?.properties,
|
|
91
|
+
authorsIds: version.authorsIds
|
|
92
|
+
};
|
|
93
|
+
}
|