@antelopejs/dms 0.7.20 → 0.8.0
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/CHANGELOG.md +62 -0
- package/dist/implementations/dms-auth/account-emails.d.ts +4 -0
- package/dist/implementations/dms-auth/account-emails.js +62 -0
- package/dist/implementations/dms-auth/account-emails.js.map +1 -0
- package/dist/implementations/dms-auth/index.d.ts +1 -3
- package/dist/implementations/dms-auth/index.js +15 -61
- package/dist/implementations/dms-auth/index.js.map +1 -1
- package/dist/pages/settings/users/email-change.js +3 -4
- package/dist/pages/settings/users/email-change.js.map +1 -1
- package/dist/pages/settings/users/invites.js +1 -1
- package/dist/pages/settings/users/invites.js.map +1 -1
- package/dist/pages/settings/users/members.js +1 -1
- package/dist/pages/settings/users/members.js.map +1 -1
- package/dist/pages/settings/users/notifications.js +1 -0
- package/dist/pages/settings/users/notifications.js.map +1 -1
- package/dist/test/unit/implementations/dms-html-render/built-in-emails.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms-html-render/built-in-emails.test.js +34 -0
- package/dist/test/unit/implementations/dms-html-render/built-in-emails.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/hook-handler-results.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/hook-handler-results.test.js +49 -0
- package/dist/test/unit/interfaces/dms/hook-handler-results.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/page-topics.test.js +17 -0
- package/dist/test/unit/interfaces/dms/page-topics.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/confirm-dialog-secondary-action.test.js +2 -2
- package/dist/test/unit/interfaces/dms-base/confirm-dialog-secondary-action.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/query-response-delta.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms-base/query-response-delta.test.js +29 -0
- package/dist/test/unit/interfaces/dms-base/query-response-delta.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/resource-form.test.js +5 -0
- package/dist/test/unit/interfaces/dms-base/resource-form.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-form-redirect.test.js +12 -2
- package/dist/test/unit/interfaces/dms-base/table-view-form-redirect.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js +29 -4
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-row-menu-label.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-row-menu-label.test.js +27 -0
- package/dist/test/unit/interfaces/dms-base/table-view-row-menu-label.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js +18 -4
- package/dist/test/unit/interfaces/dms-base/table-view-source-reorder.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-views.test.js +8 -5
- package/dist/test/unit/interfaces/dms-base/table-view-views.test.js.map +1 -1
- package/dist/test/unit/utils/email-subjects.test.d.ts +1 -0
- package/dist/test/unit/utils/email-subjects.test.js +27 -0
- package/dist/test/unit/utils/email-subjects.test.js.map +1 -0
- package/dist/utils/admin-invite-email.js +2 -4
- package/dist/utils/admin-invite-email.js.map +1 -1
- package/dist/utils/email-change-mail.d.ts +1 -1
- package/dist/utils/email-change-mail.js +11 -6
- package/dist/utils/email-change-mail.js.map +1 -1
- package/dist/utils/email-subjects.d.ts +3 -0
- package/dist/utils/email-subjects.js +32 -0
- package/dist/utils/email-subjects.js.map +1 -0
- package/dist/utils/export-jobs.js +15 -10
- package/dist/utils/export-jobs.js.map +1 -1
- package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +29 -11
- package/frontend-vue/layers/dms-core/shared/types/app-config.ts +17 -0
- package/frontend-vue/layers/dms-layout/app/app.config.ts +5 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +18 -2
- package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +16 -1
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useHeaderActionControls.ts +14 -0
- package/frontend-vue/layers/dms-layout/app/components/layout/HStack.vue +16 -0
- package/frontend-vue/layers/dms-layout/app/components/layout/VStack.vue +2 -0
- package/frontend-vue/layers/dms-layout/app/composables/useFooterLinks.ts +11 -1
- package/frontend-vue/layers/dms-layout/app/custom-pages/settings/roles.vue +1 -1
- package/frontend-vue/layers/dms-layout/app/emails/EmailAdminInvite.vue +1 -1
- package/frontend-vue/layers/dms-layout/app/emails/EmailChangeNotice.vue +13 -7
- package/frontend-vue/layers/dms-layout/app/emails/EmailChangeVerification.vue +18 -7
- package/frontend-vue/layers/dms-layout/app/emails/EmailExportReady.vue +23 -12
- package/frontend-vue/layers/dms-layout/app/emails/EmailResetPassword.vue +18 -7
- package/frontend-vue/layers/dms-layout/app/emails/EmailTwoFactor.vue +23 -4
- package/frontend-vue/layers/dms-layout/app/emails/EmailUserValidation.vue +18 -6
- package/frontend-vue/layers/dms-layout/app/emails/components/EmailOTP.vue +8 -2
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +40 -0
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +40 -0
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +11 -3
- package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +13 -3
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +1 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +14 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +90 -43
- package/frontend-vue/layers/dms-ui/app/build/composables/chart/apexTheme.ts +59 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +27 -4
- package/frontend-vue/layers/dms-ui/app/build/composables/confirm/useActionConfirm.ts +10 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +0 -5
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryOrder.ts +23 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formFooter.ts +19 -15
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +26 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/page/pageUrlValues.ts +41 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/registerDefaultFunctions.ts +2 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +3 -5
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableUrlTab.ts +42 -12
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewConfig.ts +7 -11
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +3 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +10 -11
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +29 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/link.ts +7 -3
- package/frontend-vue/layers/dms-ui/app/build/utils/urlVariables.ts +32 -9
- package/frontend-vue/layers/dms-ui/app/components/activity-feed/ActivityFeed.vue +8 -1
- package/frontend-vue/layers/dms-ui/app/components/banner/Banner.vue +9 -4
- package/frontend-vue/layers/dms-ui/app/components/blocks/BannerBlock.vue +5 -11
- package/frontend-vue/layers/dms-ui/app/components/blocks/NavCardGridBlock.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +32 -1
- package/frontend-vue/layers/dms-ui/app/components/check-list/CheckList.vue +1 -1
- package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +12 -2
- package/frontend-vue/layers/dms-ui/app/components/form/components/Cascader.vue +7 -3
- package/frontend-vue/layers/dms-ui/app/components/form/components/File.vue +7 -0
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +4 -1
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +4 -2
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +3 -2
- package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +4 -1
- package/frontend-vue/layers/dms-ui/app/components/grid/columns.ts +15 -3
- package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/components/list-row/ListRow.vue +9 -2
- package/frontend-vue/layers/dms-ui/app/components/save-bar/InstantSaveBadge.vue +13 -5
- package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +1 -1
- package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +3 -2
- package/frontend-vue/layers/dms-ui/app/components/table-view/CascaderPath.vue +53 -31
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +14 -6
- package/frontend-vue/layers/dms-ui/app/composables/chart/apexPlotOptions.ts +15 -4
- package/frontend-vue/layers/dms-ui/app/composables/chart/apexYRange.ts +123 -0
- package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +49 -49
- package/frontend-vue/layers/dms-ui/app/composables/chart/useChartTheme.ts +20 -1
- package/frontend-vue/layers/dms-ui/app/composables/confirm/types.ts +1 -1
- package/frontend-vue/layers/dms-ui/app/composables/form/types/props.ts +2 -0
- package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +8 -6
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +1 -1
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +3 -3
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +6 -0
- package/frontend-vue/layers/dms-ui/app/utils/bannerToneIcons.ts +13 -0
- package/frontend-vue/layers/dms-ui/app/utils/cascader.ts +26 -0
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +4 -0
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +4 -0
- package/frontend-vue/tests/activity-feed-fill-height.test.ts +7 -0
- package/frontend-vue/tests/banner-tone-icon.test.ts +55 -0
- package/frontend-vue/tests/builtin-emails.test.ts +141 -0
- package/frontend-vue/tests/cascader.test.ts +27 -0
- package/frontend-vue/tests/chart-auto-y-range.test.ts +25 -9
- package/frontend-vue/tests/chart-colors.test.ts +8 -0
- package/frontend-vue/tests/chart-resize-after-animation.test.ts +100 -0
- package/frontend-vue/tests/chart-type-defaults.test.ts +128 -0
- package/frontend-vue/tests/check-list-marker.test.ts +58 -0
- package/frontend-vue/tests/confirm-from.test.ts +1 -1
- package/frontend-vue/tests/confirm-secondary-action.test.ts +2 -2
- package/frontend-vue/tests/context-links.test.ts +2 -2
- package/frontend-vue/tests/custom-action-confirm-from.test.ts +2 -2
- package/frontend-vue/tests/download-action-target.test.ts +2 -2
- package/frontend-vue/tests/file-drop-prompt.test.ts +72 -0
- package/frontend-vue/tests/footer-config.test.ts +135 -0
- package/frontend-vue/tests/form-actions.test.ts +7 -0
- package/frontend-vue/tests/form-entry-order.test.ts +45 -0
- package/frontend-vue/tests/form-footer-kind.test.ts +11 -6
- package/frontend-vue/tests/form-load-error.test.ts +38 -1
- package/frontend-vue/tests/grid-responsive-columns.test.ts +9 -0
- package/frontend-vue/tests/header-actions.test.ts +55 -9
- package/frontend-vue/tests/instant-save-badge.test.ts +11 -4
- package/frontend-vue/tests/list-row-truncate.test.ts +46 -0
- package/frontend-vue/tests/roles-name-errors.test.ts +2 -3
- package/frontend-vue/tests/row-side-panel.test.ts +93 -2
- package/frontend-vue/tests/save-bar.test.ts +15 -3
- package/frontend-vue/tests/save-status-error.test.ts +2 -2
- package/frontend-vue/tests/table-row-action-errors.test.ts +5 -5
- package/frontend-vue/tests/table-row-hover.test.ts +2 -2
- package/frontend-vue/tests/table-view-bulk-drawer.test.ts +114 -0
- package/frontend-vue/tests/table-view-cards-reread.test.ts +77 -0
- package/frontend-vue/tests/table-view-sources.test.ts +1 -1
- package/frontend-vue/tests/table-view-url-tab.test.ts +84 -2
- package/frontend-vue/tests/template-tokens.test.ts +235 -0
- package/frontend-vue/tests/url-interpolation.test.ts +6 -6
- package/package.json +2 -2
- package/skills/dms/SKILL.md +2 -1
- package/skills/dms-pages/REFERENCE.md +2 -2
- package/skills/dms-project/SKILL.md +0 -1
|
@@ -7,7 +7,8 @@ export interface FooterLink {
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* The Antelope links every footer starts with. A layer replaces one by
|
|
10
|
-
* registering an entry under the same id
|
|
10
|
+
* registering an entry under the same id, or removes it with
|
|
11
|
+
* `unregisterFooterLink`.
|
|
11
12
|
*/
|
|
12
13
|
const DEFAULT_FOOTER_LINKS: FooterLink[] = [
|
|
13
14
|
{
|
|
@@ -43,6 +44,15 @@ export function registerFooterLink(link: FooterLink): void {
|
|
|
43
44
|
links.value = next;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Removes a link from the footer, one of the Antelope defaults
|
|
49
|
+
* (`dms:documentation`, `dms:website`) or another layer's. An id never
|
|
50
|
+
* registered is ignored.
|
|
51
|
+
*/
|
|
52
|
+
export function unregisterFooterLink(id: string): void {
|
|
53
|
+
links.value = links.value.filter((entry) => entry.id !== id);
|
|
54
|
+
}
|
|
55
|
+
|
|
46
56
|
export function useFooterLinks() {
|
|
47
57
|
const sortedLinks = computed<FooterLink[]>(() =>
|
|
48
58
|
[...links.value].sort(compareByOrder),
|
|
@@ -32,7 +32,7 @@ interface RoleEditorHandle {
|
|
|
32
32
|
|
|
33
33
|
const NAME_REQUIRED = "$page.settings.roles.error.name_required";
|
|
34
34
|
const NAME_TAKEN = "$page.settings.roles.error.name_taken";
|
|
35
|
-
const ROLE_DELETE_CONFIRM_URL = `${ROLES_API_PATH}/{id}/delete-confirm`;
|
|
35
|
+
const ROLE_DELETE_CONFIRM_URL = `${ROLES_API_PATH}/{{row.id}}/delete-confirm`;
|
|
36
36
|
|
|
37
37
|
const api = useRolesApi();
|
|
38
38
|
const { t } = useI18n();
|
|
@@ -51,7 +51,7 @@ const invitation = computed(() => {
|
|
|
51
51
|
</script>
|
|
52
52
|
|
|
53
53
|
<template>
|
|
54
|
-
<EmailLayout :title="title" :lang="locale">
|
|
54
|
+
<EmailLayout :title="title" :lang="locale" public-logo-only>
|
|
55
55
|
<EText :style="emailStyles.text">
|
|
56
56
|
{{ t("emails.admin_invite.greeting") }}
|
|
57
57
|
</EText>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "vue-i18n";
|
|
2
3
|
import EmailLayout from "./components/EmailLayout.vue";
|
|
3
4
|
import { emailStyles } from "./components/index";
|
|
4
5
|
|
|
@@ -6,22 +7,27 @@ defineProps<{
|
|
|
6
7
|
userName: string;
|
|
7
8
|
newEmail: string;
|
|
8
9
|
}>();
|
|
10
|
+
|
|
11
|
+
const { t, locale } = useI18n();
|
|
9
12
|
</script>
|
|
10
13
|
|
|
11
14
|
<template>
|
|
12
|
-
<EmailLayout
|
|
13
|
-
|
|
15
|
+
<EmailLayout
|
|
16
|
+
:title="t('emails.email_change_notice.title')"
|
|
17
|
+
:lang="locale"
|
|
18
|
+
public-logo-only
|
|
19
|
+
>
|
|
20
|
+
<EText :style="emailStyles.text">
|
|
21
|
+
{{ t("emails.common.greeting", { name: userName }) }}
|
|
22
|
+
</EText>
|
|
14
23
|
|
|
15
24
|
<EText :style="emailStyles.text">
|
|
16
|
-
|
|
17
|
-
{{ newEmail }}. The change takes effect once that address is confirmed.
|
|
25
|
+
{{ t("emails.email_change_notice.body", { email: newEmail }) }}
|
|
18
26
|
</EText>
|
|
19
27
|
|
|
20
28
|
<template #footer>
|
|
21
29
|
<EText :style="emailStyles.footer">
|
|
22
|
-
|
|
23
|
-
sessions in Security: your account keeps this address until the new
|
|
24
|
-
one is confirmed.
|
|
30
|
+
{{ t("emails.email_change_notice.footer") }}
|
|
25
31
|
</EText>
|
|
26
32
|
</template>
|
|
27
33
|
</EmailLayout>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "vue-i18n";
|
|
2
3
|
import EmailLayout from "./components/EmailLayout.vue";
|
|
3
4
|
import EmailOTP from "./components/EmailOTP.vue";
|
|
4
5
|
import { emailStyles } from "./components/index";
|
|
@@ -8,24 +9,34 @@ defineProps<{
|
|
|
8
9
|
newEmail: string;
|
|
9
10
|
code: string;
|
|
10
11
|
expiresIn: string;
|
|
12
|
+
expiresInHours: number;
|
|
11
13
|
}>();
|
|
14
|
+
|
|
15
|
+
const { t, locale } = useI18n();
|
|
12
16
|
</script>
|
|
13
17
|
|
|
14
18
|
<template>
|
|
15
|
-
<EmailLayout
|
|
16
|
-
|
|
19
|
+
<EmailLayout
|
|
20
|
+
:title="t('emails.email_change_verification.title')"
|
|
21
|
+
:lang="locale"
|
|
22
|
+
public-logo-only
|
|
23
|
+
>
|
|
24
|
+
<EText :style="emailStyles.text">
|
|
25
|
+
{{ t("emails.common.greeting", { name: userName }) }}
|
|
26
|
+
</EText>
|
|
17
27
|
|
|
18
28
|
<EText :style="emailStyles.text">
|
|
19
|
-
|
|
20
|
-
account:
|
|
29
|
+
{{ t("emails.email_change_verification.body", { email: newEmail }) }}
|
|
21
30
|
</EText>
|
|
22
31
|
|
|
23
|
-
<EmailOTP
|
|
32
|
+
<EmailOTP
|
|
33
|
+
:code="code"
|
|
34
|
+
:expires-in="t('emails.common.hours', expiresInHours)"
|
|
35
|
+
/>
|
|
24
36
|
|
|
25
37
|
<template #footer>
|
|
26
38
|
<EText :style="emailStyles.footer">
|
|
27
|
-
|
|
28
|
-
your account keeps its current address.
|
|
39
|
+
{{ t("emails.email_change_verification.footer") }}
|
|
29
40
|
</EText>
|
|
30
41
|
</template>
|
|
31
42
|
</EmailLayout>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { I18nT, useI18n } from "vue-i18n";
|
|
2
3
|
import EmailLayout from "./components/EmailLayout.vue";
|
|
3
4
|
import EmailButton from "./components/EmailButton.vue";
|
|
4
5
|
import { emailStyles } from "./components/index";
|
|
@@ -7,38 +8,48 @@ defineProps<{
|
|
|
7
8
|
userName: string;
|
|
8
9
|
downloadLink: string;
|
|
9
10
|
expiresIn: string;
|
|
11
|
+
expiresInHours: number;
|
|
10
12
|
partial: boolean;
|
|
11
13
|
failedSources: string[];
|
|
12
14
|
}>();
|
|
15
|
+
|
|
16
|
+
const { t, locale } = useI18n();
|
|
13
17
|
</script>
|
|
14
18
|
|
|
15
19
|
<template>
|
|
16
|
-
<EmailLayout
|
|
17
|
-
|
|
20
|
+
<EmailLayout
|
|
21
|
+
:title="t('emails.export_ready.title')"
|
|
22
|
+
:lang="locale"
|
|
23
|
+
public-logo-only
|
|
24
|
+
>
|
|
25
|
+
<EText :style="emailStyles.text">
|
|
26
|
+
{{ t("emails.common.greeting", { name: userName }) }}
|
|
27
|
+
</EText>
|
|
18
28
|
|
|
19
29
|
<EText :style="emailStyles.text">
|
|
20
|
-
|
|
21
|
-
archive:
|
|
30
|
+
{{ t("emails.export_ready.body") }}
|
|
22
31
|
</EText>
|
|
23
32
|
|
|
24
33
|
<EmailButton
|
|
25
34
|
:href="downloadLink"
|
|
26
|
-
:expires-in="
|
|
27
|
-
expires-label="
|
|
35
|
+
:expires-in="t('emails.common.hours', expiresInHours)"
|
|
36
|
+
:expires-label="t('emails.export_ready.expires_label')"
|
|
28
37
|
>
|
|
29
|
-
|
|
38
|
+
{{ t("emails.export_ready.button") }}
|
|
30
39
|
</EmailButton>
|
|
31
40
|
|
|
32
41
|
<EText v-if="partial" :style="emailStyles.text">
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
<I18nT keypath="emails.export_ready.partial" scope="global">
|
|
43
|
+
<template #incomplete>
|
|
44
|
+
<strong>{{ t("emails.export_ready.incomplete") }}</strong>
|
|
45
|
+
</template>
|
|
46
|
+
<template #sources>{{ failedSources.join(", ") }}</template>
|
|
47
|
+
</I18nT>
|
|
37
48
|
</EText>
|
|
38
49
|
|
|
39
50
|
<template #footer>
|
|
40
51
|
<EText :style="emailStyles.footer">
|
|
41
|
-
|
|
52
|
+
{{ t("emails.export_ready.footer") }}
|
|
42
53
|
</EText>
|
|
43
54
|
</template>
|
|
44
55
|
</EmailLayout>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "vue-i18n";
|
|
2
3
|
import EmailLayout from "./components/EmailLayout.vue";
|
|
3
4
|
import EmailOTP from "./components/EmailOTP.vue";
|
|
4
5
|
import { emailStyles } from "./components/index";
|
|
@@ -7,24 +8,34 @@ defineProps<{
|
|
|
7
8
|
userName: string;
|
|
8
9
|
resetCode: string;
|
|
9
10
|
expiresIn: string;
|
|
11
|
+
expiresInHours: number;
|
|
10
12
|
}>();
|
|
13
|
+
|
|
14
|
+
const { t, locale } = useI18n();
|
|
11
15
|
</script>
|
|
12
16
|
|
|
13
17
|
<template>
|
|
14
|
-
<EmailLayout
|
|
15
|
-
|
|
18
|
+
<EmailLayout
|
|
19
|
+
:title="t('emails.reset_password.title')"
|
|
20
|
+
:lang="locale"
|
|
21
|
+
public-logo-only
|
|
22
|
+
>
|
|
23
|
+
<EText :style="emailStyles.text">
|
|
24
|
+
{{ t("emails.common.greeting", { name: userName }) }}
|
|
25
|
+
</EText>
|
|
16
26
|
|
|
17
27
|
<EText :style="emailStyles.text">
|
|
18
|
-
|
|
19
|
-
below to reset your password:
|
|
28
|
+
{{ t("emails.reset_password.body") }}
|
|
20
29
|
</EText>
|
|
21
30
|
|
|
22
|
-
<EmailOTP
|
|
31
|
+
<EmailOTP
|
|
32
|
+
:code="resetCode"
|
|
33
|
+
:expires-in="t('emails.common.hours', expiresInHours)"
|
|
34
|
+
/>
|
|
23
35
|
|
|
24
36
|
<template #footer>
|
|
25
37
|
<EText :style="emailStyles.footer">
|
|
26
|
-
|
|
27
|
-
email. Your password will remain unchanged.
|
|
38
|
+
{{ t("emails.reset_password.footer") }}
|
|
28
39
|
</EText>
|
|
29
40
|
</template>
|
|
30
41
|
</EmailLayout>
|
|
@@ -1,18 +1,37 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "vue-i18n";
|
|
2
3
|
import EmailLayout from "./components/EmailLayout.vue";
|
|
3
4
|
import EmailOTP from "./components/EmailOTP.vue";
|
|
5
|
+
import { emailStyles } from "./components/index";
|
|
4
6
|
|
|
5
7
|
defineProps<{
|
|
6
8
|
userName: string;
|
|
7
9
|
verificationCode: string;
|
|
8
10
|
}>();
|
|
11
|
+
|
|
12
|
+
const { t, locale } = useI18n();
|
|
9
13
|
</script>
|
|
10
14
|
|
|
11
15
|
<template>
|
|
12
|
-
<EmailLayout
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
<EmailLayout
|
|
17
|
+
:title="t('emails.two_factor.title')"
|
|
18
|
+
:lang="locale"
|
|
19
|
+
public-logo-only
|
|
20
|
+
>
|
|
21
|
+
<EText :style="emailStyles.text">
|
|
22
|
+
{{ t("emails.common.greeting", { name: userName }) }}
|
|
23
|
+
</EText>
|
|
24
|
+
|
|
25
|
+
<EText :style="emailStyles.text">
|
|
26
|
+
{{ t("emails.two_factor.body") }}
|
|
27
|
+
</EText>
|
|
28
|
+
|
|
15
29
|
<EmailOTP :code="verificationCode" />
|
|
16
|
-
|
|
30
|
+
|
|
31
|
+
<template #footer>
|
|
32
|
+
<EText :style="emailStyles.footer">
|
|
33
|
+
{{ t("emails.two_factor.footer") }}
|
|
34
|
+
</EText>
|
|
35
|
+
</template>
|
|
17
36
|
</EmailLayout>
|
|
18
37
|
</template>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "vue-i18n";
|
|
2
3
|
import EmailLayout from "./components/EmailLayout.vue";
|
|
3
4
|
import EmailOTP from "./components/EmailOTP.vue";
|
|
4
5
|
import { emailStyles } from "./components/index";
|
|
@@ -7,23 +8,34 @@ defineProps<{
|
|
|
7
8
|
userName: string;
|
|
8
9
|
validationCode: string;
|
|
9
10
|
expiresIn: string;
|
|
11
|
+
expiresInHours: number;
|
|
10
12
|
}>();
|
|
13
|
+
|
|
14
|
+
const { t, locale } = useI18n();
|
|
11
15
|
</script>
|
|
12
16
|
|
|
13
17
|
<template>
|
|
14
|
-
<EmailLayout
|
|
15
|
-
|
|
18
|
+
<EmailLayout
|
|
19
|
+
:title="t('emails.user_validation.title')"
|
|
20
|
+
:lang="locale"
|
|
21
|
+
public-logo-only
|
|
22
|
+
>
|
|
23
|
+
<EText :style="emailStyles.text">
|
|
24
|
+
{{ t("emails.common.greeting", { name: userName }) }}
|
|
25
|
+
</EText>
|
|
16
26
|
|
|
17
27
|
<EText :style="emailStyles.text">
|
|
18
|
-
|
|
19
|
-
email address:
|
|
28
|
+
{{ t("emails.user_validation.body") }}
|
|
20
29
|
</EText>
|
|
21
30
|
|
|
22
|
-
<EmailOTP
|
|
31
|
+
<EmailOTP
|
|
32
|
+
:code="validationCode"
|
|
33
|
+
:expires-in="t('emails.common.hours', expiresInHours)"
|
|
34
|
+
/>
|
|
23
35
|
|
|
24
36
|
<template #footer>
|
|
25
37
|
<EText :style="emailStyles.footer">
|
|
26
|
-
|
|
38
|
+
{{ t("emails.user_validation.footer") }}
|
|
27
39
|
</EText>
|
|
28
40
|
</template>
|
|
29
41
|
</EmailLayout>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useI18n } from "vue-i18n";
|
|
2
3
|
import { emailStyles } from "./index";
|
|
3
4
|
|
|
4
5
|
defineProps<{
|
|
@@ -6,17 +7,22 @@ defineProps<{
|
|
|
6
7
|
expiresIn?: string;
|
|
7
8
|
expiresLabel?: string;
|
|
8
9
|
}>();
|
|
10
|
+
|
|
11
|
+
const { t } = useI18n();
|
|
9
12
|
</script>
|
|
10
13
|
|
|
11
14
|
<template>
|
|
12
15
|
<ESection :style="emailStyles.otp.box">
|
|
13
|
-
<EText :style="emailStyles.otp.label">
|
|
16
|
+
<EText :style="emailStyles.otp.label">
|
|
17
|
+
{{ t("emails.common.code_label") }}
|
|
18
|
+
</EText>
|
|
14
19
|
<EText :style="emailStyles.otp.code">
|
|
15
20
|
{{ code }}
|
|
16
21
|
</EText>
|
|
17
22
|
</ESection>
|
|
18
23
|
|
|
19
24
|
<EText v-if="expiresIn" :style="emailStyles.expires">
|
|
20
|
-
{{ expiresLabel ?? "
|
|
25
|
+
{{ expiresLabel ?? t("emails.common.code_expires_label") }}
|
|
26
|
+
{{ expiresIn }}.
|
|
21
27
|
</EText>
|
|
22
28
|
</template>
|
|
@@ -867,6 +867,46 @@
|
|
|
867
867
|
"expires_label": "This invitation expires in",
|
|
868
868
|
"expires_in": "{days} days",
|
|
869
869
|
"footer": "If you didn't expect this invitation, you can safely ignore this email."
|
|
870
|
+
},
|
|
871
|
+
"common": {
|
|
872
|
+
"greeting": "Hello {name},",
|
|
873
|
+
"code_label": "Your verification code is:",
|
|
874
|
+
"code_expires_label": "This code expires in",
|
|
875
|
+
"hours": "{count} hour | {count} hours"
|
|
876
|
+
},
|
|
877
|
+
"user_validation": {
|
|
878
|
+
"title": "Verify Your Email",
|
|
879
|
+
"body": "Thank you for signing up! Enter the verification code below to verify your email address:",
|
|
880
|
+
"footer": "If you didn't create an account, you can safely ignore this email."
|
|
881
|
+
},
|
|
882
|
+
"reset_password": {
|
|
883
|
+
"title": "Reset Your Password",
|
|
884
|
+
"body": "We received a request to reset your password. Enter the verification code below to reset your password:",
|
|
885
|
+
"footer": "If you didn't request a password reset, you can safely ignore this email. Your password will remain unchanged."
|
|
886
|
+
},
|
|
887
|
+
"two_factor": {
|
|
888
|
+
"title": "Your verification code",
|
|
889
|
+
"body": "Use this verification code to finish signing in:",
|
|
890
|
+
"footer": "If you did not attempt to sign in, you can safely ignore this email."
|
|
891
|
+
},
|
|
892
|
+
"email_change_verification": {
|
|
893
|
+
"title": "Confirm your new sign-in email",
|
|
894
|
+
"body": "Enter the code below to make {email} the sign-in email of your account:",
|
|
895
|
+
"footer": "If you didn't ask for this change, you can safely ignore this email: your account keeps its current address."
|
|
896
|
+
},
|
|
897
|
+
"email_change_notice": {
|
|
898
|
+
"title": "Your sign-in email is being changed",
|
|
899
|
+
"body": "Someone signed in to your account asked to change its sign-in email to {email}. The change takes effect once that address is confirmed.",
|
|
900
|
+
"footer": "If this wasn't you, change your password now and sign out the other sessions in Security: your account keeps this address until the new one is confirmed."
|
|
901
|
+
},
|
|
902
|
+
"export_ready": {
|
|
903
|
+
"title": "Your data export is ready",
|
|
904
|
+
"body": "Your data export has been prepared. Use the button below to download the archive:",
|
|
905
|
+
"button": "Download export",
|
|
906
|
+
"expires_label": "This download link expires in",
|
|
907
|
+
"partial": "This export is {incomplete}: the following parts could not be included — {sources}. Request a new export if you need them.",
|
|
908
|
+
"incomplete": "incomplete",
|
|
909
|
+
"footer": "If you didn't request this export, you can safely ignore this email."
|
|
870
910
|
}
|
|
871
911
|
},
|
|
872
912
|
"empty_layout": {
|
|
@@ -871,6 +871,46 @@
|
|
|
871
871
|
"expires_label": "Cette invitation expire dans",
|
|
872
872
|
"expires_in": "{days} jours",
|
|
873
873
|
"footer": "Si vous n'attendiez pas cette invitation, vous pouvez ignorer cet e-mail."
|
|
874
|
+
},
|
|
875
|
+
"common": {
|
|
876
|
+
"greeting": "Bonjour {name},",
|
|
877
|
+
"code_label": "Votre code de vérification :",
|
|
878
|
+
"code_expires_label": "Ce code expire dans",
|
|
879
|
+
"hours": "{count} heure | {count} heures"
|
|
880
|
+
},
|
|
881
|
+
"user_validation": {
|
|
882
|
+
"title": "Vérifiez votre adresse e-mail",
|
|
883
|
+
"body": "Merci pour votre inscription ! Saisissez le code ci-dessous pour vérifier votre adresse e-mail :",
|
|
884
|
+
"footer": "Si vous n'avez pas créé de compte, vous pouvez ignorer cet e-mail."
|
|
885
|
+
},
|
|
886
|
+
"reset_password": {
|
|
887
|
+
"title": "Réinitialisez votre mot de passe",
|
|
888
|
+
"body": "Nous avons reçu une demande de réinitialisation de votre mot de passe. Saisissez le code ci-dessous pour le réinitialiser :",
|
|
889
|
+
"footer": "Si vous n'êtes pas à l'origine de cette demande, vous pouvez ignorer cet e-mail. Votre mot de passe reste inchangé."
|
|
890
|
+
},
|
|
891
|
+
"two_factor": {
|
|
892
|
+
"title": "Votre code de vérification",
|
|
893
|
+
"body": "Saisissez ce code de vérification pour terminer votre connexion :",
|
|
894
|
+
"footer": "Si vous n'avez pas essayé de vous connecter, vous pouvez ignorer cet e-mail."
|
|
895
|
+
},
|
|
896
|
+
"email_change_verification": {
|
|
897
|
+
"title": "Confirmez votre nouvelle adresse de connexion",
|
|
898
|
+
"body": "Saisissez le code ci-dessous pour faire de {email} l'adresse de connexion de votre compte :",
|
|
899
|
+
"footer": "Si vous n'avez pas demandé ce changement, vous pouvez ignorer cet e-mail : votre compte garde son adresse actuelle."
|
|
900
|
+
},
|
|
901
|
+
"email_change_notice": {
|
|
902
|
+
"title": "Votre adresse de connexion va changer",
|
|
903
|
+
"body": "Une personne connectée à votre compte a demandé à remplacer son adresse de connexion par {email}. Le changement prendra effet une fois cette adresse confirmée.",
|
|
904
|
+
"footer": "Si ce n'est pas vous, changez votre mot de passe maintenant et déconnectez les autres sessions dans Sécurité : votre compte garde cette adresse tant que la nouvelle n'est pas confirmée."
|
|
905
|
+
},
|
|
906
|
+
"export_ready": {
|
|
907
|
+
"title": "Votre export de données est prêt",
|
|
908
|
+
"body": "Votre export de données a été préparé. Utilisez le bouton ci-dessous pour télécharger l'archive :",
|
|
909
|
+
"button": "Télécharger l'export",
|
|
910
|
+
"expires_label": "Ce lien de téléchargement expire dans",
|
|
911
|
+
"partial": "Cet export est {incomplete} : les parties suivantes n'ont pas pu être incluses — {sources}. Demandez un nouvel export si vous en avez besoin.",
|
|
912
|
+
"incomplete": "incomplet",
|
|
913
|
+
"footer": "Si vous n'avez pas demandé cet export, vous pouvez ignorer cet e-mail."
|
|
874
914
|
}
|
|
875
915
|
},
|
|
876
916
|
"empty_layout": {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { pageLink } from "../../composables/page/pageUrlValues";
|
|
2
3
|
import type {
|
|
3
4
|
FormField,
|
|
4
5
|
FormFieldReadonly,
|
|
@@ -79,7 +80,7 @@ const readonly = computed<FormFieldReadonly>(() =>
|
|
|
79
80
|
/>
|
|
80
81
|
<DmsAutoLink
|
|
81
82
|
v-if="readonly.link"
|
|
82
|
-
:to="readonly.link.to"
|
|
83
|
+
:to="pageLink(readonly.link.to)"
|
|
83
84
|
class="text-primary ms-auto text-[12.5px] font-medium"
|
|
84
85
|
>
|
|
85
86
|
{{ processI18n(readonly.link.label) }}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import DmsEmptyState
|
|
2
|
+
import DmsEmptyState, {
|
|
3
|
+
type EmptyStateVariant,
|
|
4
|
+
} from "../../../components/empty-state/EmptyState.vue";
|
|
3
5
|
import type { FormLoadFailure } from "../../composables/form/formRecordLoad";
|
|
4
6
|
|
|
5
7
|
// What a form shows instead of its fields when the record it edits did not
|
|
@@ -21,16 +23,22 @@ const props = withDefaults(defineProps<FormLoadErrorProps>(), {
|
|
|
21
23
|
const emit = defineEmits<FormLoadErrorEmits>();
|
|
22
24
|
|
|
23
25
|
const { t } = useI18n();
|
|
26
|
+
|
|
27
|
+
const VARIANTS: Record<FormLoadFailure, EmptyStateVariant> = {
|
|
28
|
+
forbidden: "no-access",
|
|
29
|
+
missing: "no-data",
|
|
30
|
+
error: "error",
|
|
31
|
+
};
|
|
24
32
|
</script>
|
|
25
33
|
|
|
26
34
|
<template>
|
|
27
35
|
<DmsEmptyState
|
|
28
36
|
size="md"
|
|
29
|
-
:variant="props.failure
|
|
37
|
+
:variant="VARIANTS[props.failure]"
|
|
30
38
|
:title="t(`dms.form.load_error.${props.failure}_title`)"
|
|
31
39
|
:description="t(`dms.form.load_error.${props.failure}_description`)"
|
|
32
40
|
>
|
|
33
|
-
<template #actions>
|
|
41
|
+
<template v-if="props.failure !== 'missing'" #actions>
|
|
34
42
|
<UButton
|
|
35
43
|
:label="t('dms.form.load_error.retry')"
|
|
36
44
|
icon="i-ph-arrows-clockwise"
|
|
@@ -256,6 +256,12 @@ export interface TableProps<T> {
|
|
|
256
256
|
data?: T[] | null;
|
|
257
257
|
columns?: TableColumn<T>[];
|
|
258
258
|
loading?: boolean;
|
|
259
|
+
/**
|
|
260
|
+
* No answer has arrived yet. Without it, a load with no row listed counts
|
|
261
|
+
* as the first one, which also draws the skeleton over a re-read of an
|
|
262
|
+
* empty list.
|
|
263
|
+
*/
|
|
264
|
+
firstPageLoading?: boolean;
|
|
259
265
|
/**
|
|
260
266
|
* Message (i18n key) of a failed data fetch; switches the empty-table panel
|
|
261
267
|
* to its error state so a refused query never reads as "no data".
|
|
@@ -713,7 +719,11 @@ const DEFAULT_CAPABILITIES = resolveDisplayCapabilities({
|
|
|
713
719
|
columnManagement: true,
|
|
714
720
|
});
|
|
715
721
|
|
|
716
|
-
|
|
722
|
+
// Undefined, not the `false` an absent boolean prop casts to: the table then
|
|
723
|
+
// judges the first load by itself.
|
|
724
|
+
const props = withDefaults(defineProps<TableProps<T>>(), {
|
|
725
|
+
firstPageLoading: undefined,
|
|
726
|
+
});
|
|
717
727
|
const emits = defineEmits<TableEmits<T>>();
|
|
718
728
|
|
|
719
729
|
const appConfig = useDmsAppConfig() as DmsAppConfig & {
|
|
@@ -827,7 +837,7 @@ const paginationState = defineModel<PaginationState>("pagination", {
|
|
|
827
837
|
// The first page is on its way: skeleton rows (and placeholders for the
|
|
828
838
|
// counts) hold the list's place instead of its empty state.
|
|
829
839
|
const isFirstPageLoading = computed(
|
|
830
|
-
() => !!props.loading && !props.data?.length,
|
|
840
|
+
() => props.firstPageLoading ?? (!!props.loading && !props.data?.length),
|
|
831
841
|
);
|
|
832
842
|
const skeletonRowCount = computed(() =>
|
|
833
843
|
Math.min(
|
|
@@ -1654,7 +1664,7 @@ defineShortcuts({
|
|
|
1654
1664
|
</template>
|
|
1655
1665
|
<!-- First load: skeleton rows keep the column rhythm instead of
|
|
1656
1666
|
flashing the empty state. -->
|
|
1657
|
-
<template v-else-if="
|
|
1667
|
+
<template v-else-if="isFirstPageLoading">
|
|
1658
1668
|
<tr
|
|
1659
1669
|
v-for="rowIndex in skeletonRowCount"
|
|
1660
1670
|
:key="`skeleton-${rowIndex}`"
|
|
@@ -113,7 +113,7 @@ const cardReorder = (index: number): TableViewCardReorder | undefined =>
|
|
|
113
113
|
<!-- v2 cards display: an auto-fill grid inside the table card, sharing
|
|
114
114
|
its selection and its pagination footer. -->
|
|
115
115
|
<CardGridSkeleton
|
|
116
|
-
v-if="props.context.
|
|
116
|
+
v-if="props.context.firstPageLoading"
|
|
117
117
|
:count="props.context.pagination.pageSize"
|
|
118
118
|
:fields="fieldColumns.length"
|
|
119
119
|
/>
|
|
@@ -18,8 +18,22 @@ export interface RowNavigation {
|
|
|
18
18
|
export interface RowNavigationSource {
|
|
19
19
|
rows: () => Data[];
|
|
20
20
|
rowIdKey: string;
|
|
21
|
+
/**
|
|
22
|
+
* Reads one row by id (the table's `get` route or `fetchRowUrl`): what a
|
|
23
|
+
* container's `showRow` falls back to for a row the table does not list.
|
|
24
|
+
*/
|
|
25
|
+
getRow?: (id: string) => Promise<Data | undefined>;
|
|
21
26
|
}
|
|
22
27
|
|
|
28
|
+
/**
|
|
29
|
+
* What a drawer, modal or side panel opened on a row receives to show
|
|
30
|
+
* another row of the same table in its place (`showRow` prop): the row
|
|
31
|
+
* itself, or its id, read from the rows shown or else from the table's route.
|
|
32
|
+
* The table then treats it as the open row: its highlight, its position, its
|
|
33
|
+
* `?record=`. It rejects when the row could not be read.
|
|
34
|
+
*/
|
|
35
|
+
export type ShowRow = (row: Data | string) => Promise<void>;
|
|
36
|
+
|
|
23
37
|
const rowIdOf = (row: Data, rowIdKey: string): string =>
|
|
24
38
|
String(get(row, rowIdKey));
|
|
25
39
|
|