@purposeinplay/payload-ai-translate 0.1.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/LICENSE +21 -0
- package/README.md +714 -0
- package/dist/alerts-collection.d.ts +21 -0
- package/dist/alerts-collection.js +159 -0
- package/dist/api.d.ts +4 -0
- package/dist/api.js +918 -0
- package/dist/bulk-translate-batches-collection.d.ts +29 -0
- package/dist/bulk-translate-batches-collection.js +404 -0
- package/dist/bulk-translate-units-collection.d.ts +35 -0
- package/dist/bulk-translate-units-collection.js +310 -0
- package/dist/client/estimated-cost-cell.d.ts +6 -0
- package/dist/client/estimated-cost-cell.js +12 -0
- package/dist/client/excluded-fields-field.d.ts +45 -0
- package/dist/client/excluded-fields-field.js +553 -0
- package/dist/client/field-translate-button.d.ts +6 -0
- package/dist/client/field-translate-button.js +199 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +6 -0
- package/dist/client/lib/use-global-kill-switches.d.ts +20 -0
- package/dist/client/lib/use-global-kill-switches.js +58 -0
- package/dist/client/translate-button.d.ts +2 -0
- package/dist/client/translate-button.js +228 -0
- package/dist/client/translate-modal.d.ts +16 -0
- package/dist/client/translate-modal.js +549 -0
- package/dist/client/translation-progress.d.ts +10 -0
- package/dist/client/translation-progress.js +297 -0
- package/dist/components/TranslationNavGroup.d.ts +45 -0
- package/dist/components/TranslationNavGroup.js +104 -0
- package/dist/defaults.d.ts +11 -0
- package/dist/defaults.js +16 -0
- package/dist/endpoints/client-config.d.ts +44 -0
- package/dist/endpoints/client-config.js +145 -0
- package/dist/endpoints/estimate.d.ts +5 -0
- package/dist/endpoints/estimate.js +237 -0
- package/dist/endpoints/progress.d.ts +2 -0
- package/dist/endpoints/progress.js +314 -0
- package/dist/endpoints/translate.d.ts +11 -0
- package/dist/endpoints/translate.js +376 -0
- package/dist/endpoints/translation-hub/_helpers.d.ts +140 -0
- package/dist/endpoints/translation-hub/_helpers.js +297 -0
- package/dist/endpoints/translation-hub/active.d.ts +21 -0
- package/dist/endpoints/translation-hub/active.js +220 -0
- package/dist/endpoints/translation-hub/cancel.d.ts +22 -0
- package/dist/endpoints/translation-hub/cancel.js +233 -0
- package/dist/endpoints/translation-hub/enqueue.d.ts +70 -0
- package/dist/endpoints/translation-hub/enqueue.js +529 -0
- package/dist/endpoints/translation-hub/failures.d.ts +12 -0
- package/dist/endpoints/translation-hub/failures.js +67 -0
- package/dist/endpoints/translation-hub/force-reset.d.ts +20 -0
- package/dist/endpoints/translation-hub/force-reset.js +144 -0
- package/dist/endpoints/translation-hub/index.d.ts +21 -0
- package/dist/endpoints/translation-hub/index.js +20 -0
- package/dist/endpoints/translation-hub/list.d.ts +40 -0
- package/dist/endpoints/translation-hub/list.js +182 -0
- package/dist/endpoints/translation-hub/preflight.d.ts +19 -0
- package/dist/endpoints/translation-hub/preflight.js +141 -0
- package/dist/endpoints/translation-hub/retry-failed.d.ts +38 -0
- package/dist/endpoints/translation-hub/retry-failed.js +235 -0
- package/dist/endpoints/translation-hub/revert.d.ts +88 -0
- package/dist/endpoints/translation-hub/revert.js +405 -0
- package/dist/endpoints/translation-hub/status.d.ts +45 -0
- package/dist/endpoints/translation-hub/status.js +391 -0
- package/dist/endpoints/translation-hub/usage-summary.d.ts +114 -0
- package/dist/endpoints/translation-hub/usage-summary.js +481 -0
- package/dist/exports/client.d.ts +6 -0
- package/dist/exports/client.js +6 -0
- package/dist/exports/components.d.ts +6 -0
- package/dist/exports/components.js +5 -0
- package/dist/exports/index.d.ts +8 -0
- package/dist/exports/index.js +7 -0
- package/dist/exports/providers.d.ts +9 -0
- package/dist/exports/providers.js +5 -0
- package/dist/exports/views-client.d.ts +23 -0
- package/dist/exports/views-client.js +22 -0
- package/dist/exports/views.d.ts +30 -0
- package/dist/exports/views.js +29 -0
- package/dist/hooks/after-change-global.d.ts +4 -0
- package/dist/hooks/after-change-global.js +109 -0
- package/dist/hooks/after-change.d.ts +16 -0
- package/dist/hooks/after-change.js +205 -0
- package/dist/hooks/after-delete.d.ts +30 -0
- package/dist/hooks/after-delete.js +95 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/jobs-collection.d.ts +17 -0
- package/dist/jobs-collection.js +139 -0
- package/dist/lexical/classifier.d.ts +3 -0
- package/dist/lexical/classifier.js +108 -0
- package/dist/lexical/deserializer.d.ts +4 -0
- package/dist/lexical/deserializer.js +263 -0
- package/dist/lexical/placeholder-integrity.d.ts +6 -0
- package/dist/lexical/placeholder-integrity.js +21 -0
- package/dist/lexical/placeholders.d.ts +21 -0
- package/dist/lexical/placeholders.js +117 -0
- package/dist/lexical/serializer.d.ts +21 -0
- package/dist/lexical/serializer.js +233 -0
- package/dist/lexical/types.d.ts +32 -0
- package/dist/lexical/types.js +1 -0
- package/dist/lib/auth-diagnostics.d.ts +14 -0
- package/dist/lib/auth-diagnostics.js +19 -0
- package/dist/lib/batch-counts.d.ts +58 -0
- package/dist/lib/batch-counts.js +105 -0
- package/dist/lib/bulk-translate-migrations.d.ts +92 -0
- package/dist/lib/bulk-translate-migrations.js +153 -0
- package/dist/lib/coalescing-queue.d.ts +38 -0
- package/dist/lib/coalescing-queue.js +69 -0
- package/dist/lib/content-extractor.d.ts +16 -0
- package/dist/lib/content-extractor.js +410 -0
- package/dist/lib/content-hash.d.ts +1 -0
- package/dist/lib/content-hash.js +19 -0
- package/dist/lib/content-patcher.d.ts +15 -0
- package/dist/lib/content-patcher.js +293 -0
- package/dist/lib/cost-guards.d.ts +2 -0
- package/dist/lib/cost-guards.js +18 -0
- package/dist/lib/daily-spend-cap.d.ts +58 -0
- package/dist/lib/daily-spend-cap.js +233 -0
- package/dist/lib/effective-locales.d.ts +181 -0
- package/dist/lib/effective-locales.js +302 -0
- package/dist/lib/error-messages.d.ts +245 -0
- package/dist/lib/error-messages.js +626 -0
- package/dist/lib/events.d.ts +39 -0
- package/dist/lib/events.js +146 -0
- package/dist/lib/exclude-fields.d.ts +3 -0
- package/dist/lib/exclude-fields.js +64 -0
- package/dist/lib/field-breadcrumb.d.ts +31 -0
- package/dist/lib/field-breadcrumb.js +227 -0
- package/dist/lib/field-diff.d.ts +1 -0
- package/dist/lib/field-diff.js +25 -0
- package/dist/lib/field-empty.d.ts +2 -0
- package/dist/lib/field-empty.js +68 -0
- package/dist/lib/field-resolver.d.ts +3 -0
- package/dist/lib/field-resolver.js +164 -0
- package/dist/lib/group-soft-skips.d.ts +39 -0
- package/dist/lib/group-soft-skips.js +45 -0
- package/dist/lib/locale-merge.d.ts +44 -0
- package/dist/lib/locale-merge.js +357 -0
- package/dist/lib/locale-row-check.d.ts +30 -0
- package/dist/lib/locale-row-check.js +64 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +97 -0
- package/dist/lib/manual-edit-guard.d.ts +128 -0
- package/dist/lib/manual-edit-guard.js +393 -0
- package/dist/lib/output-validation.d.ts +48 -0
- package/dist/lib/output-validation.js +148 -0
- package/dist/lib/payload-read.d.ts +16 -0
- package/dist/lib/payload-read.js +51 -0
- package/dist/lib/per-doc-claim.d.ts +90 -0
- package/dist/lib/per-doc-claim.js +140 -0
- package/dist/lib/per-doc-lock.d.ts +94 -0
- package/dist/lib/per-doc-lock.js +119 -0
- package/dist/lib/persist-usage.d.ts +91 -0
- package/dist/lib/persist-usage.js +116 -0
- package/dist/lib/progress-store.d.ts +103 -0
- package/dist/lib/progress-store.js +314 -0
- package/dist/lib/rate-limiter.d.ts +3 -0
- package/dist/lib/rate-limiter.js +53 -0
- package/dist/lib/snapshot-select.d.ts +43 -0
- package/dist/lib/snapshot-select.js +108 -0
- package/dist/lib/translate-prompt.d.ts +31 -0
- package/dist/lib/translate-prompt.js +66 -0
- package/dist/lib/translation-token-bucket.d.ts +57 -0
- package/dist/lib/translation-token-bucket.js +365 -0
- package/dist/lib/truncate-source-value.d.ts +1 -0
- package/dist/lib/truncate-source-value.js +27 -0
- package/dist/manual-edit-collection.d.ts +22 -0
- package/dist/manual-edit-collection.js +124 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +934 -0
- package/dist/providers/ai-sdk-adapter.d.ts +35 -0
- package/dist/providers/ai-sdk-adapter.js +100 -0
- package/dist/providers/anthropic.d.ts +31 -0
- package/dist/providers/anthropic.js +66 -0
- package/dist/providers/custom.d.ts +36 -0
- package/dist/providers/custom.js +24 -0
- package/dist/providers/gemini.d.ts +20 -0
- package/dist/providers/gemini.js +48 -0
- package/dist/providers/mock.d.ts +2 -0
- package/dist/providers/mock.js +29 -0
- package/dist/providers/openai.d.ts +28 -0
- package/dist/providers/openai.js +69 -0
- package/dist/settings-global.d.ts +74 -0
- package/dist/settings-global.js +216 -0
- package/dist/tasks/bulk-translate-coordinator.d.ts +115 -0
- package/dist/tasks/bulk-translate-coordinator.js +708 -0
- package/dist/tasks/bulk-translate-doc-task.d.ts +142 -0
- package/dist/tasks/bulk-translate-doc-task.js +1000 -0
- package/dist/tasks/bulk-translate-janitor.d.ts +87 -0
- package/dist/tasks/bulk-translate-janitor.js +311 -0
- package/dist/tasks/translate-job-task.d.ts +51 -0
- package/dist/tasks/translate-job-task.js +154 -0
- package/dist/translate.d.ts +113 -0
- package/dist/translate.js +911 -0
- package/dist/translation-daily-spend-collection.d.ts +24 -0
- package/dist/translation-daily-spend-collection.js +133 -0
- package/dist/translation-rate-limits-collection.d.ts +30 -0
- package/dist/translation-rate-limits-collection.js +144 -0
- package/dist/types.d.ts +672 -0
- package/dist/types.js +1 -0
- package/dist/usage-collection.d.ts +14 -0
- package/dist/usage-collection.js +377 -0
- package/dist/views/BulkRunsHub/BatchRow.d.ts +32 -0
- package/dist/views/BulkRunsHub/BatchRow.js +1222 -0
- package/dist/views/BulkRunsHub/BucketRow.d.ts +62 -0
- package/dist/views/BulkRunsHub/BucketRow.js +982 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.d.ts +18 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.js +331 -0
- package/dist/views/BulkRunsHub/EmptyState.d.ts +6 -0
- package/dist/views/BulkRunsHub/EmptyState.js +64 -0
- package/dist/views/BulkRunsHub/FilterBar.d.ts +16 -0
- package/dist/views/BulkRunsHub/FilterBar.js +284 -0
- package/dist/views/BulkRunsHub/InFlightBanner.d.ts +14 -0
- package/dist/views/BulkRunsHub/InFlightBanner.js +59 -0
- package/dist/views/BulkRunsHub/StatusBadge.d.ts +64 -0
- package/dist/views/BulkRunsHub/StatusBadge.js +248 -0
- package/dist/views/BulkRunsHub/SummaryStrip.d.ts +22 -0
- package/dist/views/BulkRunsHub/SummaryStrip.js +249 -0
- package/dist/views/BulkRunsHub/bucket-grouping.d.ts +200 -0
- package/dist/views/BulkRunsHub/bucket-grouping.js +344 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.d.ts +9 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.js +36 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.d.ts +5 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.js +45 -0
- package/dist/views/BulkRunsHub/index.d.ts +17 -0
- package/dist/views/BulkRunsHub/index.js +80 -0
- package/dist/views/BulkRunsHub/urlFilters.d.ts +14 -0
- package/dist/views/BulkRunsHub/urlFilters.js +50 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.d.ts +26 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.js +204 -0
- package/dist/views/BulkRunsHub/useUrlFilters.d.ts +10 -0
- package/dist/views/BulkRunsHub/useUrlFilters.js +88 -0
- package/dist/views/TranslationHub/ActiveJobs.d.ts +6 -0
- package/dist/views/TranslationHub/ActiveJobs.js +320 -0
- package/dist/views/TranslationHub/AdvancedPanel.d.ts +17 -0
- package/dist/views/TranslationHub/AdvancedPanel.js +996 -0
- package/dist/views/TranslationHub/AlertBanner.d.ts +6 -0
- package/dist/views/TranslationHub/AlertBanner.js +568 -0
- package/dist/views/TranslationHub/AuditPanel.d.ts +6 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.d.ts +44 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.js +71 -0
- package/dist/views/TranslationHub/AuditPanel.js +1367 -0
- package/dist/views/TranslationHub/BulkTranslate.types.d.ts +242 -0
- package/dist/views/TranslationHub/BulkTranslate.types.js +36 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.d.ts +19 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.js +332 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.d.ts +28 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.js +305 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.d.ts +3 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.js +42 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.d.ts +26 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.js +95 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.d.ts +22 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.js +879 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.d.ts +29 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.js +445 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.d.ts +66 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.js +161 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.d.ts +33 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.js +290 -0
- package/dist/views/TranslationHub/Hub.client.d.ts +74 -0
- package/dist/views/TranslationHub/Hub.client.js +357 -0
- package/dist/views/TranslationHub/ModelCombobox.d.ts +14 -0
- package/dist/views/TranslationHub/ModelCombobox.js +415 -0
- package/dist/views/TranslationHub/PerCollectionConfig.d.ts +10 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.d.ts +16 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.js +19 -0
- package/dist/views/TranslationHub/PerCollectionConfig.js +759 -0
- package/dist/views/TranslationHub/SettingsRail.d.ts +11 -0
- package/dist/views/TranslationHub/SettingsRail.js +382 -0
- package/dist/views/TranslationHub/StatusStrip.d.ts +6 -0
- package/dist/views/TranslationHub/StatusStrip.js +451 -0
- package/dist/views/TranslationHub/UsageTable.d.ts +6 -0
- package/dist/views/TranslationHub/UsageTable.helpers.d.ts +69 -0
- package/dist/views/TranslationHub/UsageTable.helpers.js +49 -0
- package/dist/views/TranslationHub/UsageTable.js +1240 -0
- package/dist/views/TranslationHub/alertGrouping.d.ts +70 -0
- package/dist/views/TranslationHub/alertGrouping.js +99 -0
- package/dist/views/TranslationHub/index.d.ts +20 -0
- package/dist/views/TranslationHub/index.js +109 -0
- package/dist/views/TranslationHub/tabNavigation.d.ts +53 -0
- package/dist/views/TranslationHub/tabNavigation.js +74 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.d.ts +33 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.js +124 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.d.ts +49 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.js +251 -0
- package/dist/views/TranslationHub/useFocusTrap.d.ts +6 -0
- package/dist/views/TranslationHub/useFocusTrap.js +81 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.d.ts +77 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.js +267 -0
- package/dist/views/shared/EditorError.d.ts +97 -0
- package/dist/views/shared/EditorError.js +205 -0
- package/dist/views/shared/ModelCell.d.ts +18 -0
- package/dist/views/shared/ModelCell.js +31 -0
- package/dist/views/shared/docHref.d.ts +16 -0
- package/dist/views/shared/docHref.js +26 -0
- package/dist/views/shared/fetch-error-body.d.ts +25 -0
- package/dist/views/shared/fetch-error-body.js +42 -0
- package/dist/views/shared/filterPillStyle.d.ts +35 -0
- package/dist/views/shared/filterPillStyle.js +40 -0
- package/dist/views/shared/format.d.ts +75 -0
- package/dist/views/shared/format.js +131 -0
- package/package.json +141 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { useGlobalKillSwitches } from '../../client/lib/use-global-kill-switches.js';
|
|
5
|
+
import { isActiveStatus } from './BulkTranslate.types.js';
|
|
6
|
+
import { BulkTranslatePreflightModal } from './BulkTranslatePreflightModal.js';
|
|
7
|
+
import { useBulkTranslateActive } from './useBulkTranslateActive.js';
|
|
8
|
+
const SKELETON_STYLE = {
|
|
9
|
+
width: '120px',
|
|
10
|
+
height: '30px',
|
|
11
|
+
background: 'var(--theme-elevation-100)',
|
|
12
|
+
borderRadius: '4px',
|
|
13
|
+
// Visual hint that this is a placeholder, not interactive. No
|
|
14
|
+
// animation library — keyframe lives in the global Payload theme
|
|
15
|
+
// (`--theme-pulse-*`) and the simple opacity transition below is a
|
|
16
|
+
// reasonable cross-theme fallback.
|
|
17
|
+
opacity: 0.7
|
|
18
|
+
};
|
|
19
|
+
const CHIP_STYLE = {
|
|
20
|
+
display: 'inline-flex',
|
|
21
|
+
alignItems: 'center',
|
|
22
|
+
gap: '0.5rem',
|
|
23
|
+
padding: '0.4rem 0.75rem',
|
|
24
|
+
borderRadius: '4px',
|
|
25
|
+
background: 'var(--theme-warning-100, #fef3c7)',
|
|
26
|
+
border: '1px solid var(--theme-warning-500, #d97706)',
|
|
27
|
+
color: 'var(--theme-warning-500, #d97706)',
|
|
28
|
+
fontSize: '0.8125rem',
|
|
29
|
+
fontWeight: 500,
|
|
30
|
+
textDecoration: 'none'
|
|
31
|
+
};
|
|
32
|
+
const BUTTON_STYLE = {
|
|
33
|
+
display: 'inline-flex',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
gap: '0.5rem',
|
|
36
|
+
padding: '0.4rem 0.85rem',
|
|
37
|
+
background: 'transparent',
|
|
38
|
+
border: '1px solid var(--theme-elevation-300)',
|
|
39
|
+
borderRadius: '4px',
|
|
40
|
+
color: 'var(--theme-elevation-1000)',
|
|
41
|
+
fontSize: '0.8125rem',
|
|
42
|
+
fontWeight: 500,
|
|
43
|
+
cursor: 'pointer'
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Pure derivation — exported for unit tests so the tristate logic can
|
|
47
|
+
* be exercised without React.
|
|
48
|
+
*
|
|
49
|
+
* 1.2.8: also surfaces attribution when the active batch was started
|
|
50
|
+
* by a different user. The label switches from a generic
|
|
51
|
+
* "Bulk run in progress" to "Bulk run by alice@…" so editors can
|
|
52
|
+
* tell at a glance whose run is occupying the queue without
|
|
53
|
+
* navigating into the monitor card.
|
|
54
|
+
*/ export function deriveTriggerState(args) {
|
|
55
|
+
const { loading, data, monitorAnchorId, currentUserId } = args;
|
|
56
|
+
// Initial-load skeleton (closes N8 / F-DA-LOADING-FLICKER window).
|
|
57
|
+
if (loading || data === null) {
|
|
58
|
+
return {
|
|
59
|
+
kind: 'loading'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const batch = data.batch;
|
|
63
|
+
if (batch && isActiveStatus(batch.status)) {
|
|
64
|
+
const completed = batch.completedUnits ?? 0;
|
|
65
|
+
const total = batch.totalUnits ?? 0;
|
|
66
|
+
const ownedByViewer = currentUserId != null && batch.triggeredByUserId != null && String(batch.triggeredByUserId) === currentUserId;
|
|
67
|
+
let label;
|
|
68
|
+
if (ownedByViewer) {
|
|
69
|
+
label = `Your bulk run — ${completed}/${total} complete`;
|
|
70
|
+
} else if (batch.triggeredByEmail) {
|
|
71
|
+
label = `Bulk run by ${batch.triggeredByEmail} — ${completed}/${total} complete`;
|
|
72
|
+
} else {
|
|
73
|
+
label = `Bulk run in progress — ${completed}/${total} complete`;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
kind: 'active-run',
|
|
77
|
+
label,
|
|
78
|
+
href: monitorAnchorId ? `#${monitorAnchorId}` : '#'
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
kind: 'idle'
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export const BulkTranslateTrigger = ({ basePath, monitorAnchorId = 'bulk-translate-monitor', currentUserId = null })=>{
|
|
86
|
+
const { data, loading, refetch } = useBulkTranslateActive(basePath);
|
|
87
|
+
const [modalOpen, setModalOpen] = useState(false);
|
|
88
|
+
// Plugin-wide bulk-translate kill switch (v1.2.8). Top-level for
|
|
89
|
+
// rules-of-hooks; rendering decision below.
|
|
90
|
+
const killSwitches = useGlobalKillSwitches();
|
|
91
|
+
const state = deriveTriggerState({
|
|
92
|
+
loading,
|
|
93
|
+
data,
|
|
94
|
+
monitorAnchorId,
|
|
95
|
+
currentUserId
|
|
96
|
+
});
|
|
97
|
+
if (state.kind === 'loading') {
|
|
98
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
99
|
+
"aria-busy": "true",
|
|
100
|
+
"aria-label": "Loading bulk translate status",
|
|
101
|
+
"data-testid": "bulk-translate-trigger-skeleton",
|
|
102
|
+
role: "status",
|
|
103
|
+
style: SKELETON_STYLE
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (state.kind === 'active-run') {
|
|
107
|
+
return /*#__PURE__*/ _jsxs("a", {
|
|
108
|
+
"data-testid": "bulk-translate-trigger-active",
|
|
109
|
+
href: state.href,
|
|
110
|
+
style: CHIP_STYLE,
|
|
111
|
+
children: [
|
|
112
|
+
/*#__PURE__*/ _jsx("span", {
|
|
113
|
+
"aria-hidden": "true",
|
|
114
|
+
children: "●"
|
|
115
|
+
}),
|
|
116
|
+
state.label
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// Kill switch off — show paused affordance so admins can see the
|
|
121
|
+
// feature isn't broken, it's intentionally disabled. Active-run takes
|
|
122
|
+
// precedence above so an in-flight run is still visible even when
|
|
123
|
+
// new enqueues are blocked.
|
|
124
|
+
if (killSwitches && !killSwitches.bulkEnabled) {
|
|
125
|
+
return /*#__PURE__*/ _jsx("button", {
|
|
126
|
+
"aria-disabled": "true",
|
|
127
|
+
"data-testid": "bulk-translate-trigger-paused",
|
|
128
|
+
disabled: true,
|
|
129
|
+
style: {
|
|
130
|
+
...BUTTON_STYLE,
|
|
131
|
+
opacity: 0.55,
|
|
132
|
+
cursor: 'not-allowed'
|
|
133
|
+
},
|
|
134
|
+
title: "Bulk Translate is paused site-wide. An admin can re-enable it in Translation Settings.",
|
|
135
|
+
type: "button",
|
|
136
|
+
children: "Bulk Translate (paused)"
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
140
|
+
children: [
|
|
141
|
+
/*#__PURE__*/ _jsx("button", {
|
|
142
|
+
"data-testid": "bulk-translate-trigger-idle",
|
|
143
|
+
onClick: ()=>setModalOpen(true),
|
|
144
|
+
style: BUTTON_STYLE,
|
|
145
|
+
type: "button",
|
|
146
|
+
children: "Bulk Translate"
|
|
147
|
+
}),
|
|
148
|
+
modalOpen && /*#__PURE__*/ _jsx(BulkTranslatePreflightModal, {
|
|
149
|
+
basePath: basePath,
|
|
150
|
+
onClose: ()=>{
|
|
151
|
+
setModalOpen(false);
|
|
152
|
+
// Refresh active-batch state so the trigger flips to
|
|
153
|
+
// "active-run" immediately after a successful enqueue
|
|
154
|
+
// (mirrors F-UX-15 expectation that the UI never shows a
|
|
155
|
+
// stale "idle" trigger post-enqueue).
|
|
156
|
+
refetch();
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
]
|
|
160
|
+
});
|
|
161
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editor-facing "Your recent bulk runs" panel (1.2.8).
|
|
3
|
+
*
|
|
4
|
+
* Replaces the admin `UsageTable` on the Translation Hub Overview for
|
|
5
|
+
* editor-role viewers. Sourced from `bulk_translate_batches` via the
|
|
6
|
+
* `/api/translation-hub/bulk-translate` list endpoint (opened to
|
|
7
|
+
* editor+admin in 1.2.8) instead of `translation_usage` (the per-doc
|
|
8
|
+
* audit collection, which has no `triggeredByUserId` column and so
|
|
9
|
+
* can't support the attribution chip the editor experience needs).
|
|
10
|
+
*
|
|
11
|
+
* Layout: compact table of the editor's last ~5 bulk runs with an
|
|
12
|
+
* attribution chip on every row plus a CTA linking to the full
|
|
13
|
+
* BulkRunsHub for deeper history. Cost / token / model columns are
|
|
14
|
+
* absent — the field-level access mask on the batches collection
|
|
15
|
+
* strips those for non-admin viewers, and surfacing them to editors
|
|
16
|
+
* would reintroduce the cost-anxiety problem the UX critique flagged.
|
|
17
|
+
*
|
|
18
|
+
* Owned vs others' runs: per Decision #31-revised the table shows
|
|
19
|
+
* BOTH the current editor's runs and other editors' runs. The action
|
|
20
|
+
* column is only present on rows the editor owns. Rows owned by
|
|
21
|
+
* other editors render with an attribution chip and no action menu —
|
|
22
|
+
* editors coordinate by reading the chip, not by acting on each
|
|
23
|
+
* other's runs.
|
|
24
|
+
*/
|
|
25
|
+
import type React from 'react';
|
|
26
|
+
interface Props {
|
|
27
|
+
basePath: string;
|
|
28
|
+
/** Stringified user id. Drives the attribution chip + action gating. */
|
|
29
|
+
currentUserId: string | null;
|
|
30
|
+
currentUserEmail: string | null;
|
|
31
|
+
}
|
|
32
|
+
export declare const EditorRecentRunsPanel: React.FC<Props>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
4
|
+
import { readResponseError } from '../shared/fetch-error-body.js';
|
|
5
|
+
// Active polling cadence matches the rest of the Hub — 5s while a
|
|
6
|
+
// batch is in flight, 60s otherwise.
|
|
7
|
+
const POLL_INTERVAL_MS = 5_000;
|
|
8
|
+
const IDLE_POLL_INTERVAL_MS = 60_000;
|
|
9
|
+
const ROW_LIMIT = 8;
|
|
10
|
+
const SECTION_STYLE = {
|
|
11
|
+
background: 'var(--theme-elevation-50)',
|
|
12
|
+
border: '1px solid var(--theme-elevation-150)',
|
|
13
|
+
borderRadius: '6px',
|
|
14
|
+
padding: '1rem'
|
|
15
|
+
};
|
|
16
|
+
const HEADER_ROW_STYLE = {
|
|
17
|
+
display: 'grid',
|
|
18
|
+
gridTemplateColumns: '1.4fr 1fr 0.9fr 0.7fr 0.7fr',
|
|
19
|
+
gap: '0.75rem',
|
|
20
|
+
padding: '0.5rem 0',
|
|
21
|
+
fontSize: '0.75rem',
|
|
22
|
+
fontWeight: 600,
|
|
23
|
+
textTransform: 'uppercase',
|
|
24
|
+
letterSpacing: '0.05em',
|
|
25
|
+
color: 'var(--theme-elevation-500)'
|
|
26
|
+
};
|
|
27
|
+
const ROW_STYLE = {
|
|
28
|
+
display: 'grid',
|
|
29
|
+
gridTemplateColumns: '1.4fr 1fr 0.9fr 0.7fr 0.7fr',
|
|
30
|
+
gap: '0.75rem',
|
|
31
|
+
padding: '0.5rem 0',
|
|
32
|
+
alignItems: 'center',
|
|
33
|
+
fontSize: '0.875rem',
|
|
34
|
+
borderTop: '1px solid var(--theme-elevation-100)',
|
|
35
|
+
color: 'var(--theme-elevation-800)'
|
|
36
|
+
};
|
|
37
|
+
const STATUS_COLORS = {
|
|
38
|
+
queued: 'var(--theme-elevation-500)',
|
|
39
|
+
running: 'var(--theme-warning-500, #d97706)',
|
|
40
|
+
cancelling: 'var(--theme-warning-500, #d97706)',
|
|
41
|
+
success: 'var(--theme-success-500, #16a34a)',
|
|
42
|
+
partial: 'var(--theme-warning-500, #d97706)',
|
|
43
|
+
failed: 'var(--theme-error-500, #b91c1c)',
|
|
44
|
+
cancelled: 'var(--theme-elevation-500)',
|
|
45
|
+
reverted: 'var(--theme-elevation-500)'
|
|
46
|
+
};
|
|
47
|
+
function relTime(iso) {
|
|
48
|
+
if (!iso) return '—';
|
|
49
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
50
|
+
if (!Number.isFinite(diff)) return '—';
|
|
51
|
+
const s = Math.floor(diff / 1000);
|
|
52
|
+
if (s < 60) return `${s}s ago`;
|
|
53
|
+
if (s < 3600) return `${Math.floor(s / 60)}m ago`;
|
|
54
|
+
if (s < 86_400) return `${Math.floor(s / 3600)}h ago`;
|
|
55
|
+
return `${Math.floor(s / 86_400)}d ago`;
|
|
56
|
+
}
|
|
57
|
+
// Active = anything that isn't terminal. Drives the poll cadence
|
|
58
|
+
// (5s while live, 60s while idle).
|
|
59
|
+
const TERMINAL_STATUSES = new Set([
|
|
60
|
+
'success',
|
|
61
|
+
'partial',
|
|
62
|
+
'failed',
|
|
63
|
+
'cancelled',
|
|
64
|
+
'reverted'
|
|
65
|
+
]);
|
|
66
|
+
export const EditorRecentRunsPanel = ({ basePath, currentUserId, currentUserEmail })=>{
|
|
67
|
+
void currentUserEmail; // reserved for future "by you" chip styling
|
|
68
|
+
const [rows, setRows] = useState(null);
|
|
69
|
+
const [error, setError] = useState(null);
|
|
70
|
+
useEffect(()=>{
|
|
71
|
+
let cancelled = false;
|
|
72
|
+
let timer;
|
|
73
|
+
let hasActiveBatch = false;
|
|
74
|
+
async function fetchRows() {
|
|
75
|
+
const url = `${basePath}/api/translation-hub/bulk-translate?limit=${ROW_LIMIT}&sort=-enqueuedAt`;
|
|
76
|
+
const res = await fetch(url, {
|
|
77
|
+
credentials: 'include'
|
|
78
|
+
});
|
|
79
|
+
if (!res.ok) {
|
|
80
|
+
throw new Error(await readResponseError(res));
|
|
81
|
+
}
|
|
82
|
+
const json = await res.json();
|
|
83
|
+
return json.batches ?? [];
|
|
84
|
+
}
|
|
85
|
+
async function poll() {
|
|
86
|
+
try {
|
|
87
|
+
const next = await fetchRows();
|
|
88
|
+
if (cancelled) return;
|
|
89
|
+
setRows(next);
|
|
90
|
+
setError(null);
|
|
91
|
+
hasActiveBatch = next.some((r)=>!TERMINAL_STATUSES.has(r.status));
|
|
92
|
+
} catch (e) {
|
|
93
|
+
if (cancelled) return;
|
|
94
|
+
setError(e instanceof Error ? e.message : String(e));
|
|
95
|
+
} finally{
|
|
96
|
+
if (!cancelled && document.visibilityState === 'visible') {
|
|
97
|
+
const nextDelay = hasActiveBatch ? POLL_INTERVAL_MS : IDLE_POLL_INTERVAL_MS;
|
|
98
|
+
timer = setTimeout(poll, nextDelay);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function onVisibility() {
|
|
103
|
+
if (document.visibilityState === 'visible' && !cancelled) {
|
|
104
|
+
if (timer) clearTimeout(timer);
|
|
105
|
+
poll();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
document.addEventListener('visibilitychange', onVisibility);
|
|
109
|
+
poll();
|
|
110
|
+
return ()=>{
|
|
111
|
+
cancelled = true;
|
|
112
|
+
if (timer) clearTimeout(timer);
|
|
113
|
+
document.removeEventListener('visibilitychange', onVisibility);
|
|
114
|
+
};
|
|
115
|
+
}, [
|
|
116
|
+
basePath
|
|
117
|
+
]);
|
|
118
|
+
const visibleRows = useMemo(()=>rows ?? [], [
|
|
119
|
+
rows
|
|
120
|
+
]);
|
|
121
|
+
return /*#__PURE__*/ _jsxs("section", {
|
|
122
|
+
style: SECTION_STYLE,
|
|
123
|
+
children: [
|
|
124
|
+
/*#__PURE__*/ _jsxs("header", {
|
|
125
|
+
style: {
|
|
126
|
+
display: 'flex',
|
|
127
|
+
alignItems: 'baseline',
|
|
128
|
+
justifyContent: 'space-between',
|
|
129
|
+
marginBottom: '0.75rem'
|
|
130
|
+
},
|
|
131
|
+
children: [
|
|
132
|
+
/*#__PURE__*/ _jsx("h2", {
|
|
133
|
+
style: {
|
|
134
|
+
margin: 0,
|
|
135
|
+
fontSize: '1rem',
|
|
136
|
+
color: 'var(--theme-elevation-1000)'
|
|
137
|
+
},
|
|
138
|
+
children: "Recent bulk runs"
|
|
139
|
+
}),
|
|
140
|
+
/*#__PURE__*/ _jsx("a", {
|
|
141
|
+
href: `${basePath}/admin/translation-runs`,
|
|
142
|
+
style: {
|
|
143
|
+
fontSize: '0.75rem',
|
|
144
|
+
color: 'var(--theme-elevation-500)',
|
|
145
|
+
textDecoration: 'none'
|
|
146
|
+
},
|
|
147
|
+
children: "View all →"
|
|
148
|
+
})
|
|
149
|
+
]
|
|
150
|
+
}),
|
|
151
|
+
error && /*#__PURE__*/ _jsx("p", {
|
|
152
|
+
style: {
|
|
153
|
+
color: 'var(--theme-error-500, #b91c1c)',
|
|
154
|
+
fontSize: '0.875rem',
|
|
155
|
+
margin: '0 0 0.5rem'
|
|
156
|
+
},
|
|
157
|
+
children: error
|
|
158
|
+
}),
|
|
159
|
+
rows === null && /*#__PURE__*/ _jsx("p", {
|
|
160
|
+
style: {
|
|
161
|
+
margin: 0,
|
|
162
|
+
color: 'var(--theme-elevation-500)',
|
|
163
|
+
fontSize: '0.875rem'
|
|
164
|
+
},
|
|
165
|
+
children: "Loading…"
|
|
166
|
+
}),
|
|
167
|
+
rows !== null && visibleRows.length === 0 && /*#__PURE__*/ _jsx("p", {
|
|
168
|
+
style: {
|
|
169
|
+
margin: 0,
|
|
170
|
+
color: 'var(--theme-elevation-500)',
|
|
171
|
+
fontSize: '0.875rem'
|
|
172
|
+
},
|
|
173
|
+
children: "No bulk translation runs yet. Use the Bulk Translate button above to start one."
|
|
174
|
+
}),
|
|
175
|
+
visibleRows.length > 0 && /*#__PURE__*/ _jsxs(_Fragment, {
|
|
176
|
+
children: [
|
|
177
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
178
|
+
style: HEADER_ROW_STYLE,
|
|
179
|
+
children: [
|
|
180
|
+
/*#__PURE__*/ _jsx("span", {
|
|
181
|
+
children: "Run"
|
|
182
|
+
}),
|
|
183
|
+
/*#__PURE__*/ _jsx("span", {
|
|
184
|
+
children: "Triggered by"
|
|
185
|
+
}),
|
|
186
|
+
/*#__PURE__*/ _jsx("span", {
|
|
187
|
+
children: "Status"
|
|
188
|
+
}),
|
|
189
|
+
/*#__PURE__*/ _jsx("span", {
|
|
190
|
+
children: "Progress"
|
|
191
|
+
}),
|
|
192
|
+
/*#__PURE__*/ _jsx("span", {
|
|
193
|
+
style: {
|
|
194
|
+
textAlign: 'right'
|
|
195
|
+
},
|
|
196
|
+
children: "When"
|
|
197
|
+
})
|
|
198
|
+
]
|
|
199
|
+
}),
|
|
200
|
+
visibleRows.map((r)=>{
|
|
201
|
+
const total = r.totalUnits ?? 0;
|
|
202
|
+
const done = r.completedUnits ?? 0;
|
|
203
|
+
const failed = r.failedUnits ?? 0;
|
|
204
|
+
const skipped = r.skippedUnits ?? 0;
|
|
205
|
+
const owned = currentUserId != null && r.triggeredByUserId != null && String(r.triggeredByUserId) === currentUserId;
|
|
206
|
+
const triggeredBy = r.triggeredByEmail ?? (r.triggeredByUserId != null ? `user #${r.triggeredByUserId}` : '—');
|
|
207
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
208
|
+
style: ROW_STYLE,
|
|
209
|
+
children: [
|
|
210
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
211
|
+
style: {
|
|
212
|
+
overflow: 'hidden',
|
|
213
|
+
textOverflow: 'ellipsis'
|
|
214
|
+
},
|
|
215
|
+
title: `Batch ${r.id} · mode ${r.mode}`,
|
|
216
|
+
children: [
|
|
217
|
+
/*#__PURE__*/ _jsxs("code", {
|
|
218
|
+
style: {
|
|
219
|
+
fontSize: '0.75rem'
|
|
220
|
+
},
|
|
221
|
+
children: [
|
|
222
|
+
"#",
|
|
223
|
+
String(r.id)
|
|
224
|
+
]
|
|
225
|
+
}),
|
|
226
|
+
' ',
|
|
227
|
+
/*#__PURE__*/ _jsx("span", {
|
|
228
|
+
style: {
|
|
229
|
+
color: 'var(--theme-elevation-500)'
|
|
230
|
+
},
|
|
231
|
+
children: r.mode
|
|
232
|
+
})
|
|
233
|
+
]
|
|
234
|
+
}),
|
|
235
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
236
|
+
style: {
|
|
237
|
+
display: 'inline-flex',
|
|
238
|
+
alignItems: 'center',
|
|
239
|
+
gap: '0.4rem',
|
|
240
|
+
overflow: 'hidden',
|
|
241
|
+
textOverflow: 'ellipsis'
|
|
242
|
+
},
|
|
243
|
+
children: [
|
|
244
|
+
triggeredBy,
|
|
245
|
+
owned && /*#__PURE__*/ _jsx("span", {
|
|
246
|
+
style: {
|
|
247
|
+
fontSize: '0.65rem',
|
|
248
|
+
padding: '0.05rem 0.4rem',
|
|
249
|
+
borderRadius: '999px',
|
|
250
|
+
background: 'var(--theme-success-100, #dcfce7)',
|
|
251
|
+
color: 'var(--theme-success-800, #166534)',
|
|
252
|
+
fontWeight: 500
|
|
253
|
+
},
|
|
254
|
+
children: "you"
|
|
255
|
+
})
|
|
256
|
+
]
|
|
257
|
+
}),
|
|
258
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
259
|
+
style: {
|
|
260
|
+
color: STATUS_COLORS[r.status] ?? 'var(--theme-elevation-800)',
|
|
261
|
+
fontWeight: 500
|
|
262
|
+
},
|
|
263
|
+
children: [
|
|
264
|
+
r.status,
|
|
265
|
+
failed > 0 ? ` (${failed} failed)` : '',
|
|
266
|
+
skipped > 0 ? ` (${skipped} skipped)` : ''
|
|
267
|
+
]
|
|
268
|
+
}),
|
|
269
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
270
|
+
children: [
|
|
271
|
+
done,
|
|
272
|
+
"/",
|
|
273
|
+
total
|
|
274
|
+
]
|
|
275
|
+
}),
|
|
276
|
+
/*#__PURE__*/ _jsx("span", {
|
|
277
|
+
style: {
|
|
278
|
+
textAlign: 'right',
|
|
279
|
+
color: 'var(--theme-elevation-500)'
|
|
280
|
+
},
|
|
281
|
+
children: relTime(r.completedAt ?? r.startedAt ?? r.enqueuedAt)
|
|
282
|
+
})
|
|
283
|
+
]
|
|
284
|
+
}, String(r.id));
|
|
285
|
+
})
|
|
286
|
+
]
|
|
287
|
+
})
|
|
288
|
+
]
|
|
289
|
+
});
|
|
290
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
export interface TranslationSettings {
|
|
3
|
+
activeProvider?: string | null;
|
|
4
|
+
enabledTargetLocales?: string[] | null;
|
|
5
|
+
globalAutoTranslateEnabled?: boolean | null;
|
|
6
|
+
globalManualTranslateEnabled?: boolean | null;
|
|
7
|
+
globalBulkTranslateEnabled?: boolean | null;
|
|
8
|
+
perCollection?: Array<{
|
|
9
|
+
slug: string;
|
|
10
|
+
enabled?: boolean | null;
|
|
11
|
+
autoOnPublish?: boolean | null;
|
|
12
|
+
targetLocalesOverride?: string[] | null;
|
|
13
|
+
excludedFieldPaths?: string[] | null;
|
|
14
|
+
translateSlug?: boolean | null;
|
|
15
|
+
}> | null;
|
|
16
|
+
}
|
|
17
|
+
export interface OpenRouterSettings {
|
|
18
|
+
model?: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Locale list passed from the server (`req.payload.config.localization`).
|
|
22
|
+
* Source of truth for locale toggles in the Hub — replaces the prior
|
|
23
|
+
* hardcoded `['es', 'fr']` in SettingsRail that would silently drift the
|
|
24
|
+
* moment a consumer added or removed a locale in payload.config.
|
|
25
|
+
*/
|
|
26
|
+
export interface LocaleConfig {
|
|
27
|
+
defaultLocale: string;
|
|
28
|
+
locales: Array<{
|
|
29
|
+
code: string;
|
|
30
|
+
label: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
export interface JobRow {
|
|
34
|
+
collection: string;
|
|
35
|
+
completed_locales?: string[] | null;
|
|
36
|
+
created_at: string;
|
|
37
|
+
document_id: string;
|
|
38
|
+
failed_locales?: Array<{
|
|
39
|
+
locale: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
}> | null;
|
|
42
|
+
id: number;
|
|
43
|
+
job_id?: string;
|
|
44
|
+
started_at?: string | null;
|
|
45
|
+
status: 'running' | 'completed' | 'failed';
|
|
46
|
+
total_locales: number;
|
|
47
|
+
}
|
|
48
|
+
interface TranslationHubClientProps {
|
|
49
|
+
locales: LocaleConfig;
|
|
50
|
+
/**
|
|
51
|
+
* 1.2.8: viewer role. Drives which tabs render, which KPI cards
|
|
52
|
+
* appear, and whether the Recent translations table scopes by
|
|
53
|
+
* ownership. `admin` keeps the pre-1.2.8 surface; `editor` hides
|
|
54
|
+
* Configuration / Audit / Advanced tabs and reframes Overview around
|
|
55
|
+
* "your runs" (still shows other editors' runs as read-only with
|
|
56
|
+
* attribution per Decision #31-revised).
|
|
57
|
+
*/
|
|
58
|
+
role: 'admin' | 'editor';
|
|
59
|
+
/**
|
|
60
|
+
* 1.2.8: current user id (stringified, matches the persisted
|
|
61
|
+
* `triggeredByUserId` column shape). Used by the UsageTable to
|
|
62
|
+
* decide which rows are owned by the current viewer so the action
|
|
63
|
+
* menu is shown for own rows and hidden for others.
|
|
64
|
+
*/
|
|
65
|
+
currentUserId: string | null;
|
|
66
|
+
/**
|
|
67
|
+
* 1.2.8: current user email. Mirrored into modal copy ("…this
|
|
68
|
+
* conflict, you tried to start a new run while…") so the editor
|
|
69
|
+
* sees their own email in the chrome.
|
|
70
|
+
*/
|
|
71
|
+
currentUserEmail: string | null;
|
|
72
|
+
}
|
|
73
|
+
export declare const TranslationHubClient: React.FC<TranslationHubClientProps>;
|
|
74
|
+
export {};
|