@eifi1/ui-kit 0.29.0 → 0.31.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/README.md +65 -6
- package/dist/account/account-parts.d.ts +21 -0
- package/dist/account/account-parts.js +40 -0
- package/dist/account/account-parts.js.map +1 -0
- package/dist/account/data-export-setting.d.ts +73 -0
- package/dist/account/data-export-setting.js +114 -0
- package/dist/account/data-export-setting.js.map +1 -0
- package/dist/account/delete-account-setting.d.ts +95 -0
- package/dist/account/delete-account-setting.js +200 -0
- package/dist/account/delete-account-setting.js.map +1 -0
- package/dist/account/email-change-setting.d.ts +136 -0
- package/dist/account/email-change-setting.js +278 -0
- package/dist/account/email-change-setting.js.map +1 -0
- package/dist/account/sessions-setting.d.ts +110 -0
- package/dist/account/sessions-setting.js +147 -0
- package/dist/account/sessions-setting.js.map +1 -0
- package/dist/admin/admin-action-confirm.d.ts +95 -0
- package/dist/admin/admin-action-confirm.js +276 -0
- package/dist/admin/admin-action-confirm.js.map +1 -0
- package/dist/admin/admin-action-log.d.ts +105 -0
- package/dist/admin/admin-action-log.js +153 -0
- package/dist/admin/admin-action-log.js.map +1 -0
- package/dist/admin/admin-parts.d.ts +40 -0
- package/dist/admin/admin-parts.js +45 -0
- package/dist/admin/admin-parts.js.map +1 -0
- package/dist/admin/invitations-panel.d.ts +95 -0
- package/dist/admin/invitations-panel.js +290 -0
- package/dist/admin/invitations-panel.js.map +1 -0
- package/dist/admin/reviewer-scope-editor.d.ts +95 -0
- package/dist/admin/reviewer-scope-editor.js +134 -0
- package/dist/admin/reviewer-scope-editor.js.map +1 -0
- package/dist/admin/role-select.d.ts +95 -0
- package/dist/admin/role-select.js +128 -0
- package/dist/admin/role-select.js.map +1 -0
- package/dist/admin/transfer-ownership-dialog.d.ts +95 -0
- package/dist/admin/transfer-ownership-dialog.js +83 -0
- package/dist/admin/transfer-ownership-dialog.js.map +1 -0
- package/dist/admin/user-roster.d.ts +95 -0
- package/dist/admin/user-roster.js +285 -0
- package/dist/admin/user-roster.js.map +1 -0
- package/dist/auth/auth-errors.d.ts +103 -6
- package/dist/auth/auth-errors.js +68 -2
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/forgot-password-form.d.ts +10 -3
- package/dist/auth/forgot-password-form.js +6 -3
- package/dist/auth/forgot-password-form.js.map +1 -1
- package/dist/auth/register-form.d.ts +21 -12
- package/dist/auth/register-form.js +6 -4
- package/dist/auth/register-form.js.map +1 -1
- package/dist/auth/reset-password-form.d.ts +10 -3
- package/dist/auth/reset-password-form.js +6 -3
- package/dist/auth/reset-password-form.js.map +1 -1
- package/dist/auth/sign-in-form.d.ts +75 -9
- package/dist/auth/sign-in-form.js +105 -15
- package/dist/auth/sign-in-form.js.map +1 -1
- package/dist/auth/verify-email.d.ts +7 -2
- package/dist/auth/verify-email.js +44 -8
- package/dist/auth/verify-email.js.map +1 -1
- package/dist/chart.d.ts +20 -11
- package/dist/components/account-chips.d.ts +47 -7
- package/dist/components/account-chips.js +19 -3
- package/dist/components/account-chips.js.map +1 -1
- package/dist/components/account-settings-labels.d.ts +24 -1
- package/dist/components/account-settings-labels.js +6 -2
- package/dist/components/account-settings-labels.js.map +1 -1
- package/dist/components/account-settings.d.ts +69 -8
- package/dist/components/account-settings.js +133 -25
- package/dist/components/account-settings.js.map +1 -1
- package/dist/components/amount-input.d.ts +21 -12
- package/dist/components/button-group.d.ts +21 -12
- package/dist/components/calculator.d.ts +21 -12
- package/dist/components/confirm-dialog.d.ts +21 -12
- package/dist/components/copy-button.d.ts +18 -9
- package/dist/components/danger-confirm.d.ts +21 -12
- package/dist/components/data-table.js +8 -1
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.js +9 -4
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/facing-pair.d.ts +21 -12
- package/dist/components/file-button.d.ts +21 -12
- package/dist/components/file-dropzone.d.ts +21 -12
- package/dist/components/form-actions.d.ts +21 -12
- package/dist/components/iban-input.d.ts +21 -12
- package/dist/components/language-select.d.ts +21 -12
- package/dist/components/legal-page.d.ts +21 -12
- package/dist/components/legal.d.ts +21 -12
- package/dist/components/money-field.d.ts +21 -12
- package/dist/components/number-field.d.ts +21 -12
- package/dist/components/number-input.d.ts +21 -12
- package/dist/components/numpad-sheet.d.ts +21 -12
- package/dist/components/passkeys-setting.js +2 -1
- package/dist/components/passkeys-setting.js.map +1 -1
- package/dist/components/phone-input.d.ts +21 -12
- package/dist/components/series-chart.d.ts +21 -12
- package/dist/components/settings-fields.d.ts +55 -13
- package/dist/components/settings-fields.js +20 -1
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/share-card.d.ts +20 -11
- package/dist/components/text-link.d.ts +21 -12
- package/dist/components/time-input.d.ts +21 -12
- package/dist/components/ui.d.ts +17 -8
- package/dist/{register-form-V1OeNlMr.d.ts → delete-account-setting-DCFS5Vof.d.ts} +6612 -5612
- package/dist/demo/demo-banner.d.ts +51 -0
- package/dist/demo/demo-banner.js +97 -0
- package/dist/demo/demo-banner.js.map +1 -0
- package/dist/demo/demo-countdown.d.ts +58 -0
- package/dist/demo/demo-countdown.js +79 -0
- package/dist/demo/demo-countdown.js.map +1 -0
- package/dist/demo/demo-ended.d.ts +45 -0
- package/dist/demo/demo-ended.js +42 -0
- package/dist/demo/demo-ended.js.map +1 -0
- package/dist/demo/demo-labels.d.ts +53 -0
- package/dist/demo/demo-labels.js +29 -0
- package/dist/demo/demo-labels.js.map +1 -0
- package/dist/demo/demo-session.d.ts +30 -0
- package/dist/demo/demo-session.js +8 -0
- package/dist/demo/demo-session.js.map +1 -0
- package/dist/demo/demo-start.d.ts +54 -0
- package/dist/demo/demo-start.js +68 -0
- package/dist/demo/demo-start.js.map +1 -0
- package/dist/feedback/feedback-attachment.d.ts +21 -12
- package/dist/feedback/feedback-context.d.ts +21 -12
- package/dist/feedback/feedback-crash.d.ts +21 -12
- package/dist/feedback/feedback-dialog.d.ts +21 -12
- package/dist/feedback/feedback-inbox.d.ts +21 -12
- package/dist/feedback/feedback-inbox.js +12 -2
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-labels.d.ts +21 -12
- package/dist/feedback/feedback-labels.js +1 -0
- package/dist/feedback/feedback-labels.js.map +1 -1
- package/dist/feedback/feedback-menu.d.ts +21 -12
- package/dist/feedback/feedback-record.d.ts +21 -12
- package/dist/feedback/feedback-record.js +2 -0
- package/dist/feedback/feedback-record.js.map +1 -1
- package/dist/feedback/feedback-row-detail.d.ts +21 -12
- package/dist/feedback/feedback-row-detail.js +7 -0
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-status-undo.d.ts +21 -12
- package/dist/feedback/feedback-submit.d.ts +21 -12
- package/dist/feedback/feedback-swipe.d.ts +22 -13
- package/dist/feedback/feedback-swipe.js.map +1 -1
- package/dist/feedback/feedback-table.d.ts +18 -9
- package/dist/feedback/feedback-thread.d.ts +21 -12
- package/dist/feedback.d.ts +21 -12
- package/dist/hooks/use-anchored-panel.d.ts +6 -2
- package/dist/hooks/use-anchored-panel.js +2 -1
- package/dist/hooks/use-anchored-panel.js.map +1 -1
- package/dist/hooks/use-file-drop.d.ts +21 -12
- package/dist/i18n/defaults.d.ts +21 -12
- package/dist/i18n/defaults.js +28 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +21 -12
- package/dist/i18n/german.js +298 -12
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +14 -5
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +15 -6
- package/dist/i18n/locales/de-CH.d.ts +21 -12
- package/dist/i18n/locales/en.d.ts +21 -12
- package/dist/i18n/locales/es.d.ts +21 -12
- package/dist/i18n/locales/es.js +287 -10
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +21 -12
- package/dist/i18n/locales/fr.js +290 -7
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +21 -12
- package/dist/i18n/locales/hu.js +288 -12
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +21 -12
- package/dist/i18n/locales/it.js +289 -7
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +21 -12
- package/dist/i18n/locales/zh.js +279 -7
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +21 -12
- package/dist/i18n/review.js +50 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +31 -4
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -1
- package/dist/landing/access.d.ts +48 -0
- package/dist/landing/access.js +38 -0
- package/dist/landing/access.js.map +1 -0
- package/dist/landing/landing-actions.d.ts +138 -0
- package/dist/landing/landing-actions.js +39 -0
- package/dist/landing/landing-actions.js.map +1 -0
- package/dist/landing/landing-labels.d.ts +43 -0
- package/dist/landing/landing-labels.js +23 -0
- package/dist/landing/landing-labels.js.map +1 -0
- package/dist/landing/landing-sections.d.ts +218 -0
- package/dist/landing/landing-sections.js +167 -0
- package/dist/landing/landing-sections.js.map +1 -0
- package/dist/landing/page-seo.d.ts +99 -0
- package/dist/landing/page-seo.js +121 -0
- package/dist/landing/page-seo.js.map +1 -0
- package/dist/landing/public-header.d.ts +148 -0
- package/dist/landing/public-header.js +49 -0
- package/dist/landing/public-header.js.map +1 -0
- package/dist/landing/routing.d.ts +218 -0
- package/dist/landing/routing.js +81 -0
- package/dist/landing/routing.js.map +1 -0
- package/dist/rhf/fields.d.ts +21 -12
- package/dist/rhf/form.d.ts +21 -12
- package/dist/rhf.d.ts +21 -12
- package/dist/settings/settings-catalogue.d.ts +84 -0
- package/dist/settings/settings-catalogue.js +47 -0
- package/dist/settings/settings-catalogue.js.map +1 -0
- package/dist/settings/settings-context.d.ts +31 -0
- package/dist/settings/settings-context.js +11 -0
- package/dist/settings/settings-context.js.map +1 -0
- package/dist/settings/settings-heading.d.ts +50 -0
- package/dist/settings/settings-heading.js +27 -0
- package/dist/settings/settings-heading.js.map +1 -0
- package/dist/settings/settings-labels.d.ts +41 -0
- package/dist/settings/settings-labels.js +38 -0
- package/dist/settings/settings-labels.js.map +1 -0
- package/dist/settings/settings-layout.d.ts +77 -0
- package/dist/settings/settings-layout.js +242 -0
- package/dist/settings/settings-layout.js.map +1 -0
- package/dist/settings/settings-section.d.ts +133 -0
- package/dist/settings/settings-section.js +63 -0
- package/dist/settings/settings-section.js.map +1 -0
- package/dist/settings/use-account-language.d.ts +83 -0
- package/dist/settings/use-account-language.js +62 -0
- package/dist/settings/use-account-language.js.map +1 -0
- package/dist/settings/use-settings-focus.d.ts +34 -0
- package/dist/settings/use-settings-focus.js +77 -0
- package/dist/settings/use-settings-focus.js.map +1 -0
- package/dist/settings/use-settings-route.d.ts +118 -0
- package/dist/settings/use-settings-route.js +120 -0
- package/dist/settings/use-settings-route.js.map +1 -0
- package/dist/shell/app-shell.d.ts +27 -12
- package/dist/shell/app-shell.js +3 -2
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/top-bar-brand.d.ts +21 -12
- package/dist/shell.d.ts +25 -6
- package/dist/shell.js +56 -0
- package/dist/shell.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +21 -12
- package/dist/wizard.d.ts +21 -12
- package/package.json +2 -1
- package/src/account/account-parts.ts +67 -0
- package/src/account/data-export-setting.tsx +219 -0
- package/src/account/delete-account-setting.tsx +363 -0
- package/src/account/email-change-setting.tsx +454 -0
- package/src/account/sessions-setting.tsx +284 -0
- package/src/admin/admin-action-confirm.tsx +495 -0
- package/src/admin/admin-action-log.tsx +297 -0
- package/src/admin/admin-parts.ts +82 -0
- package/src/admin/invitations-panel.tsx +523 -0
- package/src/admin/reviewer-scope-editor.tsx +234 -0
- package/src/admin/role-select.tsx +286 -0
- package/src/admin/transfer-ownership-dialog.tsx +172 -0
- package/src/admin/user-roster.tsx +573 -0
- package/src/auth/auth-errors.ts +196 -8
- package/src/auth/forgot-password-form.tsx +21 -5
- package/src/auth/register-form.tsx +24 -6
- package/src/auth/reset-password-form.tsx +19 -5
- package/src/auth/sign-in-form.tsx +241 -38
- package/src/auth/verify-email.tsx +59 -8
- package/src/components/account-chips.tsx +64 -7
- package/src/components/account-settings-labels.ts +28 -1
- package/src/components/account-settings.tsx +231 -34
- package/src/components/data-table.tsx +8 -0
- package/src/components/date-picker.tsx +9 -4
- package/src/components/passkeys-setting.tsx +2 -1
- package/src/components/settings-fields.tsx +50 -1
- package/src/demo/demo-banner.tsx +159 -0
- package/src/demo/demo-countdown.ts +141 -0
- package/src/demo/demo-ended.tsx +89 -0
- package/src/demo/demo-labels.ts +78 -0
- package/src/demo/demo-session.ts +32 -0
- package/src/demo/demo-start.tsx +150 -0
- package/src/feedback/feedback-inbox.tsx +21 -8
- package/src/feedback/feedback-labels.ts +2 -1
- package/src/feedback/feedback-record.ts +10 -7
- package/src/feedback/feedback-row-detail.tsx +28 -4
- package/src/feedback/feedback-swipe.tsx +1 -1
- package/src/hooks/use-anchored-panel.ts +14 -3
- package/src/i18n/defaults.ts +28 -0
- package/src/i18n/german.ts +327 -5
- package/src/i18n/kit-labels.tsx +42 -0
- package/src/i18n/locales/es.ts +313 -3
- package/src/i18n/locales/fr.ts +316 -0
- package/src/i18n/locales/hu.ts +308 -5
- package/src/i18n/locales/it.ts +313 -0
- package/src/i18n/locales/zh.ts +286 -0
- package/src/i18n/review.ts +49 -0
- package/src/index.ts +184 -0
- package/src/landing/access.ts +97 -0
- package/src/landing/landing-actions.tsx +92 -0
- package/src/landing/landing-labels.ts +59 -0
- package/src/landing/landing-sections.tsx +337 -0
- package/src/landing/page-seo.ts +251 -0
- package/src/landing/public-header.tsx +120 -0
- package/src/landing/routing.tsx +209 -0
- package/src/settings/settings-catalogue.ts +132 -0
- package/src/settings/settings-context.ts +33 -0
- package/src/settings/settings-heading.tsx +65 -0
- package/src/settings/settings-labels.ts +75 -0
- package/src/settings/settings-layout.tsx +379 -0
- package/src/settings/settings-section.tsx +108 -0
- package/src/settings/use-account-language.ts +146 -0
- package/src/settings/use-settings-focus.ts +120 -0
- package/src/settings/use-settings-route.ts +258 -0
- package/src/shell/app-shell.tsx +10 -2
- package/src/shell.ts +45 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import type { ComponentPropsWithoutRef } from "react";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../lib/cn";
|
|
5
|
+
import { AlertBanner } from "../components/alert-banner";
|
|
6
|
+
import { Button, Spinner } from "../components/ui";
|
|
7
|
+
import { useNoIndex } from "../hooks/use-noindex";
|
|
8
|
+
import { authErrorCode, isRateLimited, retryAfterSeconds } from "../auth/auth-errors";
|
|
9
|
+
import { useOncePerKey } from "../auth/status-parts";
|
|
10
|
+
import { useAccessAction } from "../landing/access";
|
|
11
|
+
import type { AccessChoice } from "../landing/access";
|
|
12
|
+
import type { LandingLabels } from "../landing/landing-labels";
|
|
13
|
+
import { useDemoLabels } from "./demo-labels";
|
|
14
|
+
import type { DemoLabels } from "./demo-labels";
|
|
15
|
+
|
|
16
|
+
/** Why a start was refused, in the page's terms (§5.2). */
|
|
17
|
+
type Refusal =
|
|
18
|
+
| { reason: "rateLimited"; minutes?: number }
|
|
19
|
+
| { reason: "capacity" }
|
|
20
|
+
| { reason: "unavailable" }
|
|
21
|
+
| { reason: "failed" };
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The server's answer to `POST /auth/demo-session`, read as a refusal (§5.1, §6.2):
|
|
25
|
+
* `demo_rate_limited` (429, with `Retry-After`), `demo_capacity` (429, without),
|
|
26
|
+
* `demo_disabled` (404) and `demo_not_ready` (503) by their codes; a bare 429 as the
|
|
27
|
+
* per-IP window too; anything else is a plain failure.
|
|
28
|
+
*/
|
|
29
|
+
function refusalOf(error: unknown): Refusal {
|
|
30
|
+
const code = authErrorCode(error);
|
|
31
|
+
if (code === "demo_capacity") return { reason: "capacity" };
|
|
32
|
+
if (code === "demo_disabled" || code === "demo_not_ready") return { reason: "unavailable" };
|
|
33
|
+
if (code === "demo_rate_limited" || (code === undefined && isRateLimited(error))) {
|
|
34
|
+
const seconds = retryAfterSeconds(error);
|
|
35
|
+
return { reason: "rateLimited", minutes: seconds ? Math.ceil(seconds / 60) : undefined };
|
|
36
|
+
}
|
|
37
|
+
return { reason: "failed" };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function messageOf(refusal: Refusal, labels: DemoLabels): string {
|
|
41
|
+
switch (refusal.reason) {
|
|
42
|
+
case "rateLimited":
|
|
43
|
+
return labels.rateLimited(refusal.minutes);
|
|
44
|
+
case "capacity":
|
|
45
|
+
return labels.capacity;
|
|
46
|
+
case "unavailable":
|
|
47
|
+
return labels.unavailable;
|
|
48
|
+
case "failed":
|
|
49
|
+
return labels.failed;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** The one start a mount makes. */
|
|
54
|
+
const ONCE = "demo";
|
|
55
|
+
|
|
56
|
+
export interface DemoStartProps<T> extends Omit<ComponentPropsWithoutRef<"div">, "children"> {
|
|
57
|
+
/**
|
|
58
|
+
* Create the demo: the app's `POST /auth/demo-session {locale}`. Resolve with what it
|
|
59
|
+
* answered (the `TokenResponse`, `refresh_token: null`, `expires_at`); reject with the
|
|
60
|
+
* client's error — the codes are read out of it. Called once per mount.
|
|
61
|
+
*/
|
|
62
|
+
start: () => Promise<T>;
|
|
63
|
+
/** The demo exists: store the session (and, for kastlan, `kastlan.demoSession`) and
|
|
64
|
+
* replace to the app's home. The page keeps saying "Starting the demo…" meanwhile. */
|
|
65
|
+
onStarted: (session: T) => void;
|
|
66
|
+
/** "Request access" beside a refusal. */
|
|
67
|
+
access: AccessChoice;
|
|
68
|
+
/** "Back to the start page". Default `/`. */
|
|
69
|
+
backHref?: string;
|
|
70
|
+
/** `false` adds no `noindex` — for a preview. Default `true`: `/demo` is never indexed
|
|
71
|
+
* (§4.3). */
|
|
72
|
+
noIndex?: boolean;
|
|
73
|
+
labels?: Partial<DemoLabels>;
|
|
74
|
+
/** The access words (`landing` namespace) for this instance. */
|
|
75
|
+
landingLabels?: Partial<LandingLabels>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The `/demo` page's content (docs/landing-demo-harmonization.md §5.2): it starts the
|
|
80
|
+
* demo ONCE — StrictMode's double mount included, keksdose's ref guard — and says
|
|
81
|
+
* "Starting the demo…" until the app has the session and has moved on.
|
|
82
|
+
*
|
|
83
|
+
* A refusal says why, in the visitor's words, and offers "Request access" and "Back to
|
|
84
|
+
* the start page":
|
|
85
|
+
*
|
|
86
|
+
* | code | says |
|
|
87
|
+
* |---|---|
|
|
88
|
+
* | `demo_rate_limited` (429) | "Too many demos from this network. Try again in N min." — N from `Retry-After` |
|
|
89
|
+
* | `demo_capacity` (429) | "The demo is full right now. Try again later." |
|
|
90
|
+
* | `demo_disabled` (404), `demo_not_ready` (503) | "The demo isn't available right now." |
|
|
91
|
+
* | anything else | "The demo could not be started. Please try again." |
|
|
92
|
+
*
|
|
93
|
+
* keksdose fell back to `/register` with a toast; registration is invitation-only now,
|
|
94
|
+
* so the way on is the access mail.
|
|
95
|
+
*
|
|
96
|
+
* Put it in the app's `AuthLayout`. A live demo session never reaches it: the `/demo`
|
|
97
|
+
* route sits in `RedirectIfAuthed` WITHOUT `allowDemo`, which continues the live demo at
|
|
98
|
+
* its resume target instead of starting a second one. A cold start is the kit's
|
|
99
|
+
* `ServerWakeNotice`'s, once the app's watcher counts this POST
|
|
100
|
+
* (`watchReadsAnd(/\/auth\/demo-session\b/)`).
|
|
101
|
+
*/
|
|
102
|
+
export function DemoStart<T>({
|
|
103
|
+
start,
|
|
104
|
+
onStarted,
|
|
105
|
+
access,
|
|
106
|
+
backHref = "/",
|
|
107
|
+
noIndex = true,
|
|
108
|
+
labels: labelsProp,
|
|
109
|
+
landingLabels,
|
|
110
|
+
className,
|
|
111
|
+
...rest
|
|
112
|
+
}: DemoStartProps<T>) {
|
|
113
|
+
const labels = useDemoLabels(labelsProp);
|
|
114
|
+
const accessLink = useAccessAction(access, landingLabels);
|
|
115
|
+
const [refusal, setRefusal] = useState<Refusal | null>(null);
|
|
116
|
+
useNoIndex(noIndex);
|
|
117
|
+
useOncePerKey<T>(ONCE, () => start(), (_key, result) => {
|
|
118
|
+
if (result.ok) onStarted(result.value);
|
|
119
|
+
else setRefusal(refusalOf(result.error));
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<div {...rest} className={cn("flex flex-col items-center gap-4 py-4 text-center", className)}>
|
|
124
|
+
{/* One live region, there from the start, so the refusal that replaces the
|
|
125
|
+
progress line is announced (a region inserted with its text often is not). */}
|
|
126
|
+
<div role="status" aria-live="polite" className="w-full">
|
|
127
|
+
{refusal === null ? (
|
|
128
|
+
<p className="flex items-center justify-center gap-2 text-sm text-[var(--text-secondary)]">
|
|
129
|
+
<Spinner label={null} className="size-5" />
|
|
130
|
+
{labels.starting}
|
|
131
|
+
</p>
|
|
132
|
+
) : (
|
|
133
|
+
<AlertBanner tone={refusal.reason === "failed" ? "danger" : "warning"} className="text-start">
|
|
134
|
+
{messageOf(refusal, labels)}
|
|
135
|
+
</AlertBanner>
|
|
136
|
+
)}
|
|
137
|
+
</div>
|
|
138
|
+
{refusal !== null && (
|
|
139
|
+
<div className="flex flex-wrap justify-center gap-3">
|
|
140
|
+
<Button href={accessLink.href} variant="brand">
|
|
141
|
+
{accessLink.label}
|
|
142
|
+
</Button>
|
|
143
|
+
<Button href={backHref} variant="secondary">
|
|
144
|
+
{labels.backToStart}
|
|
145
|
+
</Button>
|
|
146
|
+
</div>
|
|
147
|
+
)}
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
Ban,
|
|
5
5
|
Bug,
|
|
6
6
|
CheckCircle2,
|
|
7
|
+
ClipboardCheck,
|
|
7
8
|
CloudUpload,
|
|
8
9
|
Eye,
|
|
9
10
|
HelpCircle,
|
|
@@ -55,13 +56,16 @@ import { useFeedbackCategoryLabels, useFeedbackStatusLabels } from "./feedback-l
|
|
|
55
56
|
* a `label` the caller passes still wins.
|
|
56
57
|
*/
|
|
57
58
|
|
|
58
|
-
/** The
|
|
59
|
+
/** The eight states a report can be in.
|
|
59
60
|
*
|
|
60
|
-
* Shared value for value across
|
|
61
|
-
* and one agent prompt, work on
|
|
62
|
-
* it — see {@link visibleFeedbackStatuses} for what that buys.
|
|
61
|
+
* Shared value for value across the apps on purpose: it is what lets one habit,
|
|
62
|
+
* and one agent prompt, work on any repo. Five are a chain and three sit off
|
|
63
|
+
* it — see {@link visibleFeedbackStatuses} for what that buys. `READY` joined in 0.31
|
|
64
|
+
* (feedback contract §8.2): OPEN is "filed, not yet triaged", READY "released for
|
|
65
|
+
* implementation", and nobody works an OPEN row. */
|
|
63
66
|
export type FeedbackStatus =
|
|
64
67
|
| "OPEN"
|
|
68
|
+
| "READY"
|
|
65
69
|
| "IN_PROGRESS"
|
|
66
70
|
| "IN_EVALUATION"
|
|
67
71
|
| "NEEDS_LIVE_TEST"
|
|
@@ -81,7 +85,7 @@ export type FeedbackCategory = "CRASH" | "BUG" | "IDEA" | "QUESTION" | "OTHER";
|
|
|
81
85
|
* its own shape as well. Declaration order is chain order, and
|
|
82
86
|
* {@link FEEDBACK_STATUS_ORDER} is derived from it rather than restated, because
|
|
83
87
|
* a restated list cannot be checked for exhaustiveness: an eighth status would
|
|
84
|
-
* break the build here and leave a literal
|
|
88
|
+
* break the build here and leave a literal eight long (as READY did in 0.31).
|
|
85
89
|
*/
|
|
86
90
|
export const FEEDBACK_STATUS_META: Record<
|
|
87
91
|
FeedbackStatus,
|
|
@@ -92,6 +96,15 @@ export const FEEDBACK_STATUS_META: Record<
|
|
|
92
96
|
activeBg: "bg-[var(--bg-active)]",
|
|
93
97
|
activeText: "text-[var(--text-primary)]",
|
|
94
98
|
},
|
|
99
|
+
// Triaged and released for implementation (feedback contract §8.2, keksdose live
|
|
100
|
+
// #396): OPEN is "filed, nobody has looked yet", READY is "go". The brand tint at full
|
|
101
|
+
// strength, so it reads as the go-ahead beside OPEN's neutral fill and
|
|
102
|
+
// NEEDS_LIVE_TEST's muted brand.
|
|
103
|
+
READY: {
|
|
104
|
+
icon: ClipboardCheck,
|
|
105
|
+
activeBg: "bg-[var(--brand-bg)]",
|
|
106
|
+
activeText: "text-[var(--brand)]",
|
|
107
|
+
},
|
|
95
108
|
IN_PROGRESS: {
|
|
96
109
|
icon: Wrench,
|
|
97
110
|
activeBg: "bg-[var(--warning-bg)]",
|
|
@@ -155,7 +168,7 @@ export const FEEDBACK_STATUS_ORDER = Object.keys(FEEDBACK_STATUS_META) as Feedba
|
|
|
155
168
|
* through them to reach `DONE`. */
|
|
156
169
|
const OFF_CHAIN: FeedbackStatus[] = ["NEEDS_LIVE_TEST", "POSTPONED", "WONT_DO"];
|
|
157
170
|
|
|
158
|
-
const FORWARD_CHAIN: FeedbackStatus[] = ["OPEN", "IN_PROGRESS", "IN_EVALUATION", "DONE"];
|
|
171
|
+
const FORWARD_CHAIN: FeedbackStatus[] = ["OPEN", "READY", "IN_PROGRESS", "IN_EVALUATION", "DONE"];
|
|
159
172
|
|
|
160
173
|
/** The next status along the chain, or null at the end (or off it, as `WONT_DO`
|
|
161
174
|
* is). What a swipe-to-advance gesture commits. */
|
|
@@ -168,7 +181,7 @@ export function nextFeedbackStatus(current: FeedbackStatus): FeedbackStatus | nu
|
|
|
168
181
|
* The steps that make sense from where a row currently stands.
|
|
169
182
|
*
|
|
170
183
|
* For the compact control in a table cell: it is a glanceable triage affordance,
|
|
171
|
-
* and a row of
|
|
184
|
+
* and a row of eight icons in a cell is noise. One step forward, one step back
|
|
172
185
|
* (so an item can be sent back for rework), and any of the three off-chain
|
|
173
186
|
* verdicts — which is what makes those usable as verdicts at all.
|
|
174
187
|
*
|
|
@@ -452,7 +465,7 @@ export function FeedbackStatusTransitions({
|
|
|
452
465
|
),
|
|
453
466
|
// Both stay unclickable, but only the read-only case is DIMMED: the
|
|
454
467
|
// current status is the one thing in the row that has to be legible
|
|
455
|
-
// at a glance, and among
|
|
468
|
+
// at a glance, and among eight pills a faded active one reads as
|
|
456
469
|
// "unavailable" rather than as "this is where the row stands".
|
|
457
470
|
(!canEdit || active) && "cursor-default",
|
|
458
471
|
!canEdit && "opacity-60",
|
|
@@ -24,7 +24,7 @@ import type { FeedbackCategory, FeedbackStatus } from "./feedback-inbox";
|
|
|
24
24
|
* `feedbackStatus` — one word per status, keyed by the enum value so
|
|
25
25
|
* `labels[row.status]` is the whole lookup.
|
|
26
26
|
*
|
|
27
|
-
* de-CH canon: OPEN "Offen" · IN_PROGRESS "In Bearbeitung" · IN_EVALUATION "Zur Prüfung"
|
|
27
|
+
* de-CH canon: OPEN "Offen" · READY "Bereit zur Umsetzung" · IN_PROGRESS "In Bearbeitung" · IN_EVALUATION "Zur Prüfung"
|
|
28
28
|
* · NEEDS_LIVE_TEST "Live testen" · POSTPONED "Zurückgestellt" · DONE "Erledigt" ·
|
|
29
29
|
* WONT_DO "Wird nicht umgesetzt".
|
|
30
30
|
*/
|
|
@@ -32,6 +32,7 @@ export type FeedbackStatusLabels = Record<FeedbackStatus, string>;
|
|
|
32
32
|
|
|
33
33
|
export const DEFAULT_FEEDBACK_STATUS_LABELS: FeedbackStatusLabels = {
|
|
34
34
|
OPEN: "Open",
|
|
35
|
+
READY: "Ready to implement",
|
|
35
36
|
IN_PROGRESS: "In progress",
|
|
36
37
|
IN_EVALUATION: "In evaluation",
|
|
37
38
|
NEEDS_LIVE_TEST: "Test when live",
|
|
@@ -158,22 +158,25 @@ export const FEEDBACK_REWORKABLE_STATUSES: readonly FeedbackStatus[] = Object.fr
|
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
160
|
* The statuses in which the AUTHOR may still edit title, body and category (§3.4,
|
|
161
|
-
* keksdose `canAuthorEdit`, `feedback-page.tsx:398`): `OPEN` and `IN_PROGRESS`.
|
|
162
|
-
* team has answered, the description is what they answered and stays as it
|
|
163
|
-
* correction goes in as a rework.
|
|
161
|
+
* keksdose `canAuthorEdit`, `feedback-page.tsx:398`): `OPEN`, `READY` and `IN_PROGRESS`.
|
|
162
|
+
* Once the team has answered, the description is what they answered and stays as it
|
|
163
|
+
* was; a correction goes in as a rework.
|
|
164
164
|
*/
|
|
165
165
|
export const FEEDBACK_AUTHOR_EDITABLE_STATUSES: readonly FeedbackStatus[] = Object.freeze([
|
|
166
166
|
"OPEN",
|
|
167
|
+
"READY",
|
|
167
168
|
"IN_PROGRESS",
|
|
168
169
|
] as const);
|
|
169
170
|
|
|
170
171
|
/**
|
|
171
|
-
* The
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
172
|
+
* The statuses that wait on the person triaging: filed and not yet triaged (`OPEN`,
|
|
173
|
+
* since READY took over "released for implementation" in 0.31, feedback contract §8.2),
|
|
174
|
+
* answered and handed back for a verdict, or answered and only checkable on a deployed
|
|
175
|
+
* build (keksdose `AWAITING_VERDICT`, live #330). The phone's "Only what is waiting for
|
|
176
|
+
* you" toggle narrows the inbox to exactly these (§4.3).
|
|
175
177
|
*/
|
|
176
178
|
export const FEEDBACK_AWAITING_STATUSES: readonly FeedbackStatus[] = Object.freeze([
|
|
179
|
+
"OPEN",
|
|
177
180
|
"IN_EVALUATION",
|
|
178
181
|
"NEEDS_LIVE_TEST",
|
|
179
182
|
] as const);
|
|
@@ -12,6 +12,7 @@ import { formatDate } from "../lib/format";
|
|
|
12
12
|
import { DEFAULT_MAX_ATTACHMENT_BYTES } from "./feedback-attachment";
|
|
13
13
|
import { DEFAULT_FEEDBACK_DIALOG_LABELS } from "./feedback-dialog";
|
|
14
14
|
import {
|
|
15
|
+
FeedbackCategoryBadge,
|
|
15
16
|
FeedbackDetail,
|
|
16
17
|
FeedbackDetailSection,
|
|
17
18
|
FeedbackNoteEditor,
|
|
@@ -63,8 +64,9 @@ import type { FeedbackStatusChange } from "./feedback-status-undo";
|
|
|
63
64
|
* path (`/accounts?p=2`): keksdose's `new URL(…)` throws on one and the section
|
|
64
65
|
* vanished. kastlan already fell back to `context.route` (`feedbackRaw`, `:97`).
|
|
65
66
|
*
|
|
66
|
-
* The sections, in the contract's order: **
|
|
67
|
-
*
|
|
67
|
+
* The sections, in the contract's order: **Subject** (the category and the title, §8.1;
|
|
68
|
+
* `showSubject={false}` leaves it out), **Description** (the body; the author's
|
|
69
|
+
* Edit while OPEN / READY / IN_PROGRESS), **URL**, **Attachment**, **Outcome** (the admin's
|
|
68
70
|
* outcome editor, Rework, Open page), **Send for rework** (only while reworking) and
|
|
69
71
|
* **Status**. No comment thread (§2.2: kastlan's comments fold into the body, §7.7).
|
|
70
72
|
*
|
|
@@ -81,7 +83,11 @@ import type { FeedbackStatusChange } from "./feedback-status-undo";
|
|
|
81
83
|
* canon (keksdose `de-CH.json`, ss never ß, "Nacharbeit" throughout — §7.14) on each key.
|
|
82
84
|
*/
|
|
83
85
|
export interface FeedbackDetailLabels {
|
|
84
|
-
/**
|
|
86
|
+
/** The first section's heading: what the report is called (feedback contract §8.1,
|
|
87
|
+
* keksdose live #395 — with the row expanded and the table scrolled, nothing said
|
|
88
|
+
* which entry was being answered). de-CH: "Betreff" */
|
|
89
|
+
subject: string;
|
|
90
|
+
/** The description section's heading — keksdose's `feedback.body` (§7.3). The dialog's field asks
|
|
85
91
|
* "What happened? (optional)"; the description, once filed, is headed as what it is
|
|
86
92
|
* — and as the author's "Edit description" calls it. de-CH: "Beschreibung" */
|
|
87
93
|
body: string;
|
|
@@ -140,6 +146,7 @@ export interface FeedbackDetailLabels {
|
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
export const DEFAULT_FEEDBACK_DETAIL_LABELS: FeedbackDetailLabels = {
|
|
149
|
+
subject: "Subject",
|
|
143
150
|
body: "Description",
|
|
144
151
|
edit: "Edit",
|
|
145
152
|
editDescription: "Edit description",
|
|
@@ -316,7 +323,7 @@ function AttachmentDownload({
|
|
|
316
323
|
export interface FeedbackRowAccess {
|
|
317
324
|
/** The viewer filed it (`viewerId === row.user_id`; never for an erased author). */
|
|
318
325
|
isAuthor: boolean;
|
|
319
|
-
/** "Edit description": the author, while the row is OPEN or IN_PROGRESS — on either
|
|
326
|
+
/** "Edit description": the author, while the row is OPEN, READY or IN_PROGRESS — on either
|
|
320
327
|
* page (keksdose `canAuthorEdit`, `feedback-page.tsx:398`, is not gated on `mine`). */
|
|
321
328
|
canEditDescription: boolean;
|
|
322
329
|
/** The outcome editor: the admin on the inbox (`canEdit`). */
|
|
@@ -563,6 +570,12 @@ export interface FeedbackRowDetailProps {
|
|
|
563
570
|
* BUDGET, and a person viewing one still owns their own reports.
|
|
564
571
|
*/
|
|
565
572
|
commit?: boolean;
|
|
573
|
+
/**
|
|
574
|
+
* Open with the subject: the category badge and the title (feedback contract §8.1,
|
|
575
|
+
* keksdose live #395). On by default; `false` for a page that already shows the title
|
|
576
|
+
* beside the detail.
|
|
577
|
+
*/
|
|
578
|
+
showSubject?: boolean;
|
|
566
579
|
labels?: Partial<FeedbackDetailLabels>;
|
|
567
580
|
className?: string;
|
|
568
581
|
}
|
|
@@ -603,6 +616,7 @@ export function FeedbackRowDetail({
|
|
|
603
616
|
reworkAttachment,
|
|
604
617
|
renderDate,
|
|
605
618
|
commit,
|
|
619
|
+
showSubject = true,
|
|
606
620
|
labels: labelsProp,
|
|
607
621
|
className,
|
|
608
622
|
}: FeedbackRowDetailProps) {
|
|
@@ -653,6 +667,16 @@ export function FeedbackRowDetail({
|
|
|
653
667
|
|
|
654
668
|
return (
|
|
655
669
|
<FeedbackDetail className={className}>
|
|
670
|
+
{showSubject && (
|
|
671
|
+
<FeedbackDetailSection title={labels.subject}>
|
|
672
|
+
<p className="flex flex-wrap items-center gap-x-2 gap-y-1 text-sm" data-feedback-subject="">
|
|
673
|
+
<FeedbackCategoryBadge category={row.category} />
|
|
674
|
+
<span className="min-w-0 font-medium text-[var(--text-primary)] [overflow-wrap:anywhere]">
|
|
675
|
+
{row.title}
|
|
676
|
+
</span>
|
|
677
|
+
</p>
|
|
678
|
+
</FeedbackDetailSection>
|
|
679
|
+
)}
|
|
656
680
|
<FeedbackDetailSection
|
|
657
681
|
title={labels.body}
|
|
658
682
|
action={
|
|
@@ -10,7 +10,7 @@ import type { FeedbackStatusChange, FeedbackStatusRow } from "./feedback-status-
|
|
|
10
10
|
* (`feedback-page.tsx:990`, feedback #144 rework item 4: *"it is a queue, and triaging it
|
|
11
11
|
* one tap-into-the-row at a time is the slow way"*), for every app.
|
|
12
12
|
*
|
|
13
|
-
* - `advance` — one step along the chain (`nextFeedbackStatus`: OPEN → IN_PROGRESS →
|
|
13
|
+
* - `advance` — one step along the chain (`nextFeedbackStatus`: OPEN → READY → IN_PROGRESS →
|
|
14
14
|
* IN_EVALUATION → DONE), labelled with the status it goes to;
|
|
15
15
|
* - `done` — straight to DONE, for a row that plainly needs no stop on the way;
|
|
16
16
|
* - `wont_do` — dismiss as WONT_DO.
|
|
@@ -55,13 +55,21 @@ export interface AnchoredPanel {
|
|
|
55
55
|
/** Absolute floor: below this a list is useless, so overflow the margin instead. */
|
|
56
56
|
const FLOOR = 96;
|
|
57
57
|
|
|
58
|
+
/** How much more room above must offer, when neither side fits the preferred height,
|
|
59
|
+
* before the panel changes sides — so it never jumps for a few pixels' gain. */
|
|
60
|
+
const FLIP_GAIN = 48;
|
|
61
|
+
|
|
58
62
|
/**
|
|
59
63
|
* The pure half of {@link useAnchoredPanel}: where a panel goes, given the trigger's
|
|
60
64
|
* rect and the region actually on screen.
|
|
61
65
|
*
|
|
62
66
|
* Prefers below the trigger — the conventional direction, and the one that keeps the
|
|
63
|
-
* trigger's own value visible
|
|
64
|
-
*
|
|
67
|
+
* trigger's own value visible — whenever the panel's preferred height fits there. When it
|
|
68
|
+
* does not, the panel opens above if the full height fits there, or if above is clearly
|
|
69
|
+
* roomier (by {@link FLIP_GAIN}); below an unusable `minHeight` it flips to any roomier
|
|
70
|
+
* side, as before. It used to flip only below `minHeight`, so a select with 160–319 px
|
|
71
|
+
* under it opened downward as a cramped list with 600 px free above (keksdose live #384,
|
|
72
|
+
* the currency select of the new-budget form near the bottom of the screen). The
|
|
65
73
|
* returned `maxHeight` is what makes the flip sufficient rather than merely different:
|
|
66
74
|
* without it a tall panel placed above just runs off the top instead of the bottom.
|
|
67
75
|
*
|
|
@@ -77,7 +85,10 @@ export function anchoredPanelPlacement(
|
|
|
77
85
|
const viewBottom = viewport.top + viewport.height - margin;
|
|
78
86
|
const spaceBelow = viewBottom - (rect.bottom + gap);
|
|
79
87
|
const spaceAbove = rect.top - gap - viewTop;
|
|
80
|
-
const above =
|
|
88
|
+
const above =
|
|
89
|
+
spaceAbove > spaceBelow &&
|
|
90
|
+
(spaceBelow < minHeight ||
|
|
91
|
+
(spaceBelow < preferredHeight && (spaceAbove >= preferredHeight || spaceAbove - spaceBelow >= FLIP_GAIN)));
|
|
81
92
|
const space = Math.max(FLOOR, above ? spaceAbove : spaceBelow);
|
|
82
93
|
const maxHeight = Math.min(preferredHeight, space);
|
|
83
94
|
return {
|
package/src/i18n/defaults.ts
CHANGED
|
@@ -70,6 +70,20 @@ import { DEFAULT_VERIFY_EMAIL_LABELS } from "../auth/verify-email";
|
|
|
70
70
|
import { DEFAULT_NOT_FOUND_LABELS } from "../auth/not-found-page";
|
|
71
71
|
import { DEFAULT_ACCEPT_INVITATION_LABELS } from "../auth/accept-invitation";
|
|
72
72
|
import { DEFAULT_COMPANY_SWITCHER_LABELS } from "../shell/company-switcher";
|
|
73
|
+
import { DEFAULT_EMAIL_CHANGE_LABELS } from "../account/email-change-setting";
|
|
74
|
+
import { DEFAULT_SESSIONS_LABELS } from "../account/sessions-setting";
|
|
75
|
+
import { DEFAULT_DELETE_ACCOUNT_LABELS } from "../account/delete-account-setting";
|
|
76
|
+
import { DEFAULT_DATA_EXPORT_LABELS } from "../account/data-export-setting";
|
|
77
|
+
import { DEFAULT_USER_ROSTER_LABELS } from "../admin/user-roster";
|
|
78
|
+
import { DEFAULT_ROLE_SELECT_LABELS } from "../admin/role-select";
|
|
79
|
+
import { DEFAULT_REVIEWER_SCOPE_LABELS } from "../admin/reviewer-scope-editor";
|
|
80
|
+
import { DEFAULT_ADMIN_ACTION_LABELS } from "../admin/admin-action-confirm";
|
|
81
|
+
import { DEFAULT_ADMIN_ACTION_LOG_LABELS } from "../admin/admin-action-log";
|
|
82
|
+
import { DEFAULT_TRANSFER_OWNERSHIP_LABELS } from "../admin/transfer-ownership-dialog";
|
|
83
|
+
import { DEFAULT_INVITATIONS_LABELS } from "../admin/invitations-panel";
|
|
84
|
+
import { DEFAULT_SETTINGS_LABELS } from "../settings/settings-labels";
|
|
85
|
+
import { DEFAULT_LANDING_LABELS } from "../landing/landing-labels";
|
|
86
|
+
import { DEFAULT_DEMO_LABELS } from "../demo/demo-labels";
|
|
73
87
|
import { DEFAULT_ACCOUNT_STATE_LABELS } from "../components/account-chips";
|
|
74
88
|
import { DEFAULT_SHARE_CARD_LABELS } from "../components/share-card";
|
|
75
89
|
import { DEFAULT_REAUTH_DIALOG_LABELS } from "../components/reauth-dialog";
|
|
@@ -186,6 +200,20 @@ export const DEFAULT_UI_KIT_LABELS: UiKitLabels = {
|
|
|
186
200
|
notFound: DEFAULT_NOT_FOUND_LABELS,
|
|
187
201
|
acceptInvitation: DEFAULT_ACCEPT_INVITATION_LABELS,
|
|
188
202
|
companySwitcher: DEFAULT_COMPANY_SWITCHER_LABELS,
|
|
203
|
+
emailChange: DEFAULT_EMAIL_CHANGE_LABELS,
|
|
204
|
+
sessions: DEFAULT_SESSIONS_LABELS,
|
|
205
|
+
deleteAccount: DEFAULT_DELETE_ACCOUNT_LABELS,
|
|
206
|
+
dataExport: DEFAULT_DATA_EXPORT_LABELS,
|
|
207
|
+
userRoster: DEFAULT_USER_ROSTER_LABELS,
|
|
208
|
+
roleSelect: DEFAULT_ROLE_SELECT_LABELS,
|
|
209
|
+
reviewerScope: DEFAULT_REVIEWER_SCOPE_LABELS,
|
|
210
|
+
adminAction: DEFAULT_ADMIN_ACTION_LABELS,
|
|
211
|
+
adminActionLog: DEFAULT_ADMIN_ACTION_LOG_LABELS,
|
|
212
|
+
transferOwnership: DEFAULT_TRANSFER_OWNERSHIP_LABELS,
|
|
213
|
+
invitations: DEFAULT_INVITATIONS_LABELS,
|
|
214
|
+
settings: DEFAULT_SETTINGS_LABELS,
|
|
215
|
+
landing: DEFAULT_LANDING_LABELS,
|
|
216
|
+
demo: DEFAULT_DEMO_LABELS,
|
|
189
217
|
characterCount: DEFAULT_CHARACTER_COUNT_LABELS,
|
|
190
218
|
countrySelect: DEFAULT_COUNTRY_SELECT_LABELS,
|
|
191
219
|
inlineEdit: DEFAULT_INLINE_EDIT_LABELS,
|