@delmaredigital/payload-experiments 0.3.0-rc.4 → 0.4.0-rc.2
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 +122 -27
- package/dist/admin/MetricSourceSelect.js +3 -3
- package/dist/admin/PlacementStatus.d.ts +3 -0
- package/dist/admin/PlacementStatus.js +54 -0
- package/dist/admin/PreviewLinks.d.ts +2 -1
- package/dist/admin/PreviewLinks.js +2 -2
- package/dist/admin/TestsDashboardCards.d.ts +1 -0
- package/dist/admin/TestsDashboardCards.js +4 -8
- package/dist/admin/TestsNavLink.d.ts +1 -0
- package/dist/admin/TestsNavLink.js +4 -10
- package/dist/admin/actions/ConfirmDialog.d.ts +2 -1
- package/dist/admin/actions/ConfirmDialog.js +2 -2
- package/dist/admin/actions/DecideDialog.d.ts +2 -1
- package/dist/admin/actions/DecideDialog.js +2 -2
- package/dist/admin/api.d.ts +18 -2
- package/dist/admin/api.js +47 -2
- package/dist/admin/blocks/BlockPanel.d.ts +4 -0
- package/dist/admin/blocks/BlockPanel.js +199 -0
- package/dist/admin/blocks/TestBlockField.d.ts +5 -0
- package/dist/admin/blocks/TestBlockField.js +163 -0
- package/dist/admin/blocks/formApi.d.ts +46 -0
- package/dist/admin/blocks/formApi.js +159 -0
- package/dist/admin/blocks/inject.d.ts +7 -0
- package/dist/admin/blocks/inject.js +41 -0
- package/dist/admin/blocks/model.d.ts +17 -0
- package/dist/admin/blocks/model.js +45 -0
- package/dist/admin/blocks/statusCache.d.ts +9 -0
- package/dist/admin/blocks/statusCache.js +92 -0
- package/dist/admin/blocks/useBlockForm.d.ts +17 -0
- package/dist/admin/blocks/useBlockForm.js +46 -0
- package/dist/admin/copy/actions.d.ts +2 -0
- package/dist/admin/copy/actions.js +9 -0
- package/dist/admin/copy/blocks.d.ts +43 -0
- package/dist/admin/copy/blocks.js +64 -0
- package/dist/admin/copy/common.d.ts +1 -0
- package/dist/admin/copy/common.js +1 -1
- package/dist/admin/copy/goals.d.ts +2 -0
- package/dist/admin/copy/goals.js +4 -1
- package/dist/admin/copy/newTest.d.ts +10 -0
- package/dist/admin/copy/newTest.js +10 -0
- package/dist/admin/copy/pages.d.ts +24 -0
- package/dist/admin/copy/pages.js +24 -0
- package/dist/admin/copy/readiness.d.ts +23 -3
- package/dist/admin/copy/readiness.js +24 -3
- package/dist/admin/copy/results.d.ts +1 -0
- package/dist/admin/copy/results.js +1 -0
- package/dist/admin/copy/testPage.d.ts +4 -0
- package/dist/admin/copy/testPage.js +4 -0
- package/dist/admin/goals/XpGoalField.d.ts +4 -0
- package/dist/admin/goals/XpGoalField.js +168 -0
- package/dist/admin/goals/xpGoalField.css +48 -0
- package/dist/admin/metricSource.model.d.ts +2 -0
- package/dist/admin/metricSource.model.js +4 -0
- package/dist/admin/pageCollections.d.ts +10 -0
- package/dist/admin/pageCollections.js +20 -0
- package/dist/admin/paths.d.ts +9 -0
- package/dist/admin/paths.js +9 -0
- package/dist/admin/placementStatus.model.d.ts +2 -0
- package/dist/admin/placementStatus.model.js +19 -0
- package/dist/admin/placements/placementLabels.d.ts +11 -0
- package/dist/admin/placements/placementLabels.js +21 -0
- package/dist/admin/placements/placementLabels.model.d.ts +13 -0
- package/dist/admin/placements/placementLabels.model.js +12 -0
- package/dist/admin/placements/usePlacementLabels.d.ts +12 -0
- package/dist/admin/placements/usePlacementLabels.js +102 -0
- package/dist/admin/results/DataQualityPanel.js +4 -1
- package/dist/admin/results/results.model.d.ts +3 -0
- package/dist/admin/results/results.model.js +8 -4
- package/dist/admin/surface/TestsHome.js +39 -10
- package/dist/admin/surface/TestsSurface.js +7 -6
- package/dist/admin/surface/contracts.d.ts +6 -5
- package/dist/admin/surface/goals/GoalForm.js +71 -44
- package/dist/admin/surface/goals/GoalsList.js +5 -4
- package/dist/admin/surface/goals/data.js +4 -1
- package/dist/admin/surface/goals/goals.model.d.ts +1 -2
- package/dist/admin/surface/goals/goals.model.js +1 -3
- package/dist/admin/surface/home.model.d.ts +3 -3
- package/dist/admin/surface/home.model.js +8 -4
- package/dist/admin/surface/newTest/NewTest.js +56 -17
- package/dist/admin/surface/newTest/PageWizard.d.ts +7 -0
- package/dist/admin/surface/newTest/PageWizard.js +214 -0
- package/dist/admin/surface/pagePicker/CopyRoute.d.ts +6 -0
- package/dist/admin/surface/pagePicker/CopyRoute.js +53 -0
- package/dist/admin/surface/pagePicker/PageCombobox.d.ts +10 -0
- package/dist/admin/surface/pagePicker/PageCombobox.js +395 -0
- package/dist/admin/surface/pagePicker/pagePicker.css +10 -0
- package/dist/admin/surface/pagePicker/pagePicker.model.d.ts +27 -0
- package/dist/admin/surface/pagePicker/pagePicker.model.js +25 -0
- package/dist/admin/surface/readiness/ActionDialogs.js +99 -64
- package/dist/admin/surface/readiness/Banner.js +30 -6
- package/dist/admin/surface/readiness/readiness.model.d.ts +8 -1
- package/dist/admin/surface/readiness/readiness.model.js +92 -9
- package/dist/admin/surface/results/ReleasePages.d.ts +3 -1
- package/dist/admin/surface/results/ReleasePages.js +3 -7
- package/dist/admin/surface/results/ResultsBody.js +21 -2
- package/dist/admin/surface/results/ResultsHeader.js +5 -13
- package/dist/admin/surface/results/useResults.d.ts +20 -1
- package/dist/admin/surface/test/AdvancedSection.js +111 -104
- package/dist/admin/surface/test/GoalSection.js +94 -14
- package/dist/admin/surface/test/LengthSection.js +1 -1
- package/dist/admin/surface/test/PageHoldout.d.ts +3 -0
- package/dist/admin/surface/test/PageHoldout.js +67 -0
- package/dist/admin/surface/test/TestPage.js +5 -9
- package/dist/admin/surface/test/VersionsSection.js +12 -5
- package/dist/admin/surface/test/fields.d.ts +13 -4
- package/dist/admin/surface/test/fields.js +46 -14
- package/dist/admin/surface/test/jumpToSection.d.ts +1 -1
- package/dist/admin/surface/test/jumpToSection.js +4 -3
- package/dist/admin/surface/test/pageParts.d.ts +4 -1
- package/dist/admin/surface/test/pageParts.js +49 -1
- package/dist/admin/surface/test/testPage.css +3 -1
- package/dist/admin/surface/testDocument.model.d.ts +1 -0
- package/dist/admin/surface/testDocument.model.js +2 -1
- package/dist/admin/surface/useTestDocument.d.ts +15 -2
- package/dist/admin/surface/useTestDocument.js +53 -15
- package/dist/admin/surfaceUrls.d.ts +7 -0
- package/dist/admin/surfaceUrls.js +19 -0
- package/dist/admin/theme.css +2 -0
- package/dist/admin/useApi.d.ts +21 -2
- package/dist/admin/useApi.js +3 -5
- package/dist/admin/views/CollectionListRedirect.d.ts +1 -0
- package/dist/admin/views/CollectionListRedirect.js +1 -1
- package/dist/admin/views/ExperimentsRootView.js +28 -133
- package/dist/admin/views/GoalEditRedirect.d.ts +4 -0
- package/dist/admin/views/GoalEditRedirect.js +14 -0
- package/dist/admin/views/GoalsCollectionListView.d.ts +2 -0
- package/dist/admin/views/GoalsCollectionListView.js +4 -0
- package/dist/admin/views/TestsCollectionListView.d.ts +2 -0
- package/dist/admin/views/TestsCollectionListView.js +4 -0
- package/dist/admin/views/TestsNavLinkServer.d.ts +1 -0
- package/dist/admin/views/TestsNavLinkServer.js +1 -1
- package/dist/admin/views/buildSurfaceProps.d.ts +8 -0
- package/dist/admin/views/buildSurfaceProps.js +143 -0
- package/dist/admin/views/renderCollectionList.d.ts +2 -0
- package/dist/admin/views/renderCollectionList.js +34 -0
- package/dist/admin/views/renderTestsSurface.d.ts +3 -0
- package/dist/admin/views/renderTestsSurface.js +34 -0
- package/dist/blocks/bindings.d.ts +3 -0
- package/dist/blocks/bindings.js +34 -0
- package/dist/blocks/createExperimentBlock.d.ts +6 -0
- package/dist/blocks/createExperimentBlock.js +77 -0
- package/dist/blocks/formState.d.ts +31 -0
- package/dist/blocks/formState.js +146 -0
- package/dist/blocks/model.d.ts +41 -0
- package/dist/blocks/model.js +34 -0
- package/dist/client/ExperimentGroup.d.ts +6 -0
- package/dist/client/ExperimentGroup.js +9 -0
- package/dist/client/ExperimentsProvider.js +20 -4
- package/dist/client/clickGoals.d.ts +4 -0
- package/dist/client/clickGoals.js +43 -0
- package/dist/collections/experiments/config.js +21 -7
- package/dist/collections/experiments/deleteGuard.d.ts +2 -1
- package/dist/collections/experiments/deleteGuard.js +12 -1
- package/dist/collections/experiments/editability.js +4 -2
- package/dist/collections/experiments/pickSlug.d.ts +2 -0
- package/dist/collections/experiments/pickSlug.js +8 -0
- package/dist/collections/labels.d.ts +3 -0
- package/dist/collections/labels.js +20 -0
- package/dist/collections/metrics.js +28 -6
- package/dist/collections/phases.js +1 -0
- package/dist/collections/serialize.js +7 -0
- package/dist/db/clickGoals.d.ts +9 -0
- package/dist/db/clickGoals.js +22 -0
- package/dist/db/delete.d.ts +1 -0
- package/dist/db/delete.js +1 -0
- package/dist/db/locks.d.ts +8 -0
- package/dist/db/locks.js +27 -4
- package/dist/db/names.d.ts +4 -0
- package/dist/db/names.js +4 -0
- package/dist/db/pageBindings.d.ts +4 -0
- package/dist/db/pageBindings.js +17 -0
- package/dist/db/pageBusy.d.ts +2 -0
- package/dist/db/pageBusy.js +10 -0
- package/dist/db/pageContent.d.ts +10 -0
- package/dist/db/pageContent.js +79 -0
- package/dist/db/placements.d.ts +33 -0
- package/dist/db/placements.js +54 -0
- package/dist/db/slugs.d.ts +8 -0
- package/dist/db/slugs.js +40 -0
- package/dist/db/snapshots.d.ts +6 -0
- package/dist/db/snapshots.js +8 -5
- package/dist/endpoints/clickKeys.d.ts +5 -0
- package/dist/endpoints/clickKeys.js +17 -0
- package/dist/endpoints/events.js +4 -1
- package/dist/endpoints/index.js +28 -0
- package/dist/endpoints/pages.d.ts +5 -0
- package/dist/endpoints/pages.js +120 -0
- package/dist/endpoints/placementStatus.d.ts +6 -0
- package/dist/endpoints/placementStatus.js +238 -0
- package/dist/endpoints/readBody.d.ts +2 -0
- package/dist/endpoints/readBody.js +24 -0
- package/dist/endpoints/results.js +5 -1
- package/dist/endpoints/summary.js +11 -4
- package/dist/endpoints/wrapBlock.d.ts +6 -0
- package/dist/endpoints/wrapBlock.js +76 -0
- package/dist/errors.d.ts +3 -3
- package/dist/errors.js +4 -4
- package/dist/events/rows.d.ts +1 -1
- package/dist/events/rows.js +5 -3
- package/dist/exports/adminClient.d.ts +5 -0
- package/dist/exports/adminClient.js +5 -0
- package/dist/exports/adminRsc.d.ts +3 -0
- package/dist/exports/adminRsc.js +3 -0
- package/dist/exports/blocks.d.ts +2 -0
- package/dist/exports/blocks.js +1 -0
- package/dist/exports/client.d.ts +1 -0
- package/dist/exports/client.js +1 -0
- package/dist/exports/index.d.ts +6 -1
- package/dist/exports/index.js +3 -0
- package/dist/exports/puck.d.ts +3 -1
- package/dist/exports/puck.js +2 -0
- package/dist/exports/puckEditor.d.ts +3 -0
- package/dist/exports/puckEditor.js +2 -0
- package/dist/exports/rsc.d.ts +3 -0
- package/dist/exports/rsc.js +2 -0
- package/dist/fields/xpGoal.d.ts +3 -0
- package/dist/fields/xpGoal.js +16 -0
- package/dist/globals/state.js +10 -0
- package/dist/goals/cache.d.ts +3 -0
- package/dist/goals/cache.js +35 -0
- package/dist/goals/fairness.d.ts +40 -0
- package/dist/goals/fairness.js +200 -0
- package/dist/goals/key.d.ts +4 -0
- package/dist/goals/key.js +3 -0
- package/dist/goals/picker/clickGoalPicker.model.d.ts +29 -0
- package/dist/goals/picker/clickGoalPicker.model.js +45 -0
- package/dist/goals/picker/copy.d.ts +16 -0
- package/dist/goals/picker/copy.js +15 -0
- package/dist/goals/picker/useClickGoalPicker.d.ts +30 -0
- package/dist/goals/picker/useClickGoalPicker.js +220 -0
- package/dist/goals/validate.d.ts +3 -0
- package/dist/goals/validate.js +14 -0
- package/dist/hooks/pageGuard.d.ts +5 -1
- package/dist/hooks/pageGuard.js +157 -95
- package/dist/hooks/puckGoals.d.ts +3 -0
- package/dist/hooks/puckGoals.js +38 -0
- package/dist/onInit.js +29 -0
- package/dist/options.d.ts +2 -0
- package/dist/options.js +41 -1
- package/dist/plugin.js +50 -43
- package/dist/puck/copy.d.ts +1 -0
- package/dist/puck/copy.js +1 -0
- package/dist/puck/editor/editor.chrome.css +14 -0
- package/dist/puck/editor/editor.css +106 -0
- package/dist/puck/editor/editor.model.d.ts +4 -2
- package/dist/puck/editor/editor.model.js +6 -3
- package/dist/puck/editor/integration.d.ts +10 -0
- package/dist/puck/editor/integration.js +30 -0
- package/dist/puck/editor/xpGoalPuckEditorField.d.ts +7 -0
- package/dist/puck/editor/xpGoalPuckEditorField.js +142 -0
- package/dist/puck/integration.d.ts +6 -0
- package/dist/puck/integration.js +21 -0
- package/dist/puck/xpGoalField.d.ts +3 -0
- package/dist/puck/xpGoalField.js +6 -0
- package/dist/results/health.d.ts +4 -0
- package/dist/results/health.js +27 -0
- package/dist/results/snapshot.js +15 -2
- package/dist/sanitizeReadinessDetail.js +43 -0
- package/dist/server/pageKindSeoContract.d.ts +27 -0
- package/dist/server/pageKindSeoContract.js +80 -0
- package/dist/server/recordContentChange.js +58 -8
- package/dist/server/resolveExperimentBlocks.d.ts +5 -0
- package/dist/server/resolveExperimentBlocks.js +54 -0
- package/dist/server/runResults.js +56 -15
- package/dist/server/toClientAssignments.js +2 -1
- package/dist/transitions/addMetric.d.ts +2 -1
- package/dist/transitions/addMetric.js +28 -1
- package/dist/transitions/checkStart.d.ts +14 -1
- package/dist/transitions/checkStart.js +92 -8
- package/dist/transitions/decide.js +25 -0
- package/dist/transitions/deleteExperiment.d.ts +3 -1
- package/dist/transitions/deleteExperiment.js +27 -1
- package/dist/transitions/kernel.js +4 -0
- package/dist/transitions/makeContent.d.ts +5 -0
- package/dist/transitions/makeContent.js +39 -11
- package/dist/transitions/pageCollection.d.ts +10 -0
- package/dist/transitions/pageCollection.js +20 -0
- package/dist/transitions/pageVersions.d.ts +10 -0
- package/dist/transitions/pageVersions.js +44 -0
- package/dist/transitions/phaseRecord.d.ts +1 -0
- package/dist/transitions/placementInteractions.d.ts +40 -0
- package/dist/transitions/placementInteractions.js +94 -0
- package/dist/transitions/placements.d.ts +8 -0
- package/dist/transitions/placements.js +148 -1
- package/dist/transitions/preflightData.d.ts +2 -2
- package/dist/transitions/preflightData.js +137 -5
- package/dist/transitions/resolveCaps.d.ts +1 -0
- package/dist/transitions/resolveCaps.js +6 -2
- package/dist/transitions/start.js +46 -1
- package/dist/types/admin.d.ts +1 -1
- package/dist/types/assignments.d.ts +1 -0
- package/dist/types/contracts.d.ts +15 -0
- package/dist/types/endpoints.d.ts +92 -5
- package/dist/types/index.d.ts +3 -0
- package/dist/types/puck.d.ts +7 -1
- package/dist/types/snapshot.d.ts +17 -4
- package/dist/types/surface.d.ts +13 -0
- package/dist/ui/ui.css +4 -0
- package/package.json +8 -1
|
@@ -7,8 +7,10 @@ import { jumpToSection } from '../test/jumpToSection.js';
|
|
|
7
7
|
import { actionGroupLabel, availableActions } from '../../actions/actions.model.js';
|
|
8
8
|
import { createApi } from '../../api.js';
|
|
9
9
|
import { READINESS_COPY as C, decidedCopy, nextCopy, runningCopy, stoppedCopy } from '../../copy/readiness.js';
|
|
10
|
-
import { READINESS, daysRemaining, displayDate, nextStep } from './readiness.model.js';
|
|
10
|
+
import { READINESS, daysRemaining, displayDate, nextStep, pageReadinessContext } from './readiness.model.js';
|
|
11
11
|
import { AddMetricAction, AllocateAction, ConfirmAction } from './ActionDialogs.js';
|
|
12
|
+
import { preflightPlacementLabel } from '../../placements/placementLabels.js';
|
|
13
|
+
import { placementUncheckedCopy } from '../../copy/readiness.js';
|
|
12
14
|
import { useTransition } from './useTransition.js';
|
|
13
15
|
const RUNNING_ACTIONS = [
|
|
14
16
|
'stop',
|
|
@@ -49,10 +51,17 @@ export function ReadinessContent({ test, surface, resultsVersion, bar = false })
|
|
|
49
51
|
]);
|
|
50
52
|
const decision = doc.decision;
|
|
51
53
|
const winner = actionGroupLabel(decision?.winnerArm ?? 'control', doc.arms.find((item)=>item.key === decision?.winnerArm)?.label);
|
|
52
|
-
const
|
|
53
|
-
...
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
const labelledPreflight = test.preflight ? {
|
|
55
|
+
...test.preflight,
|
|
56
|
+
checks: test.preflight.checks.map((check)=>check.code === 'placement-unchecked' ? {
|
|
57
|
+
...check,
|
|
58
|
+
detail: {
|
|
59
|
+
...check.detail,
|
|
60
|
+
title: preflightPlacementLabel(check.detail, test.preflight, surface.adminRoute).title
|
|
61
|
+
}
|
|
62
|
+
} : check)
|
|
63
|
+
} : null;
|
|
64
|
+
const next = nextStep(labelledPreflight, pageReadinessContext(doc, test.preflight, surface));
|
|
56
65
|
const setup = doc.status === 'draft' || doc.status === 'stopped';
|
|
57
66
|
const ready = Boolean(test.preflight && !test.preflightPending && !test.preflightError && test.preflight.checks.every((check)=>check.ok));
|
|
58
67
|
const unsaved = test.hasUnsaved || test.saving === 'saving';
|
|
@@ -96,7 +105,7 @@ export function ReadinessContent({ test, surface, resultsVersion, bar = false })
|
|
|
96
105
|
href: `#section-${next.section}`,
|
|
97
106
|
onClick: (event)=>{
|
|
98
107
|
event.preventDefault();
|
|
99
|
-
if (next.section !== 'header') jumpToSection(next.section);
|
|
108
|
+
if (next.section !== 'header') jumpToSection(next.section, next.arm);
|
|
100
109
|
},
|
|
101
110
|
children: [
|
|
102
111
|
sentence,
|
|
@@ -119,6 +128,21 @@ export function ReadinessContent({ test, surface, resultsVersion, bar = false })
|
|
|
119
128
|
test.preflight?.checks.filter((check)=>check.code === 'make-content-unsupported' && check.warning).map((check)=>/*#__PURE__*/ _jsx("p", {
|
|
120
129
|
children: READINESS[check.code].next(check.detail, doc)
|
|
121
130
|
}, check.code)),
|
|
131
|
+
test.preflight?.checks.filter((check)=>check.warning && [
|
|
132
|
+
'goal-in-some-versions',
|
|
133
|
+
'placement-unchecked'
|
|
134
|
+
].includes(check.code)).map((check, index)=>{
|
|
135
|
+
const placement = check.code === 'placement-unchecked' ? preflightPlacementLabel(check.detail, test.preflight, surface.adminRoute) : undefined;
|
|
136
|
+
return /*#__PURE__*/ _jsx("p", {
|
|
137
|
+
children: placement ? placement.href ? /*#__PURE__*/ _jsx("a", {
|
|
138
|
+
href: placement.href,
|
|
139
|
+
children: placementUncheckedCopy(placement.title)
|
|
140
|
+
}) : placementUncheckedCopy(placement.title) : READINESS[check.code].next(check.detail, doc)
|
|
141
|
+
}, `${check.code}:${index}`);
|
|
142
|
+
}),
|
|
143
|
+
test.preflight?.goalNotes?.map((note)=>/*#__PURE__*/ _jsx("p", {
|
|
144
|
+
children: note.message
|
|
145
|
+
}, note.metricId)),
|
|
122
146
|
doc.status === 'stopped' ? /*#__PURE__*/ _jsx("p", {
|
|
123
147
|
children: stoppedCopy(displayDate(doc.stoppedAt))
|
|
124
148
|
}) : null,
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import type { ReadinessCode, PreflightResult } from '../../../types/endpoints.js';
|
|
2
2
|
import type { SerializedFlagPoint } from '../../../types/admin.js';
|
|
3
3
|
import type { TestDocument } from '../testDocument.model.js';
|
|
4
|
+
import type { SurfaceProps } from '../contracts.js';
|
|
4
5
|
import { type SectionId } from '../contracts.js';
|
|
5
6
|
export type ReadinessContext = Pick<TestDocument, 'arms' | 'unitType' | 'flagPoint'> & {
|
|
7
|
+
collectionLabel?: string;
|
|
8
|
+
pagePlacements?: PreflightResult['pagePlacements'];
|
|
6
9
|
flagPoints?: readonly Pick<SerializedFlagPoint, 'id' | 'params'>[];
|
|
7
10
|
};
|
|
8
11
|
/** Exhaustive mapping of the checkStart ReadinessCode union, including all ten invariant checks. */
|
|
9
12
|
export declare const READINESS: Record<ReadinessCode, {
|
|
10
13
|
section: SectionId | 'header';
|
|
11
14
|
next(detail: unknown, ctx: ReadinessContext): string | null;
|
|
12
|
-
nextStep?: string;
|
|
15
|
+
nextStep?: string | ((detail: unknown, ctx: ReadinessContext) => string);
|
|
13
16
|
}>;
|
|
14
17
|
export declare function nextStep(preflight: PreflightResult | null, ctx: ReadinessContext): {
|
|
15
18
|
nextStep?: string | undefined;
|
|
19
|
+
arm?: import("../../../types/contracts.js").ArmKey | undefined;
|
|
16
20
|
section: "header" | SectionId;
|
|
17
21
|
sentence: string;
|
|
18
22
|
code: ReadinessCode;
|
|
@@ -22,3 +26,6 @@ export declare function sectionDone(test: {
|
|
|
22
26
|
}): Record<SectionId, boolean>;
|
|
23
27
|
export declare function displayDate(value: unknown): string | null;
|
|
24
28
|
export declare function daysRemaining(doc: TestDocument, now: number): number | null;
|
|
29
|
+
export declare function pageReadinessContext(doc: TestDocument, preflight: PreflightResult | null, surface: SurfaceProps): ReadinessContext;
|
|
30
|
+
/** First affected row in arm order; shared by the wizard and the test-page jump. */
|
|
31
|
+
export declare function readinessArm(code: ReadinessCode, detail: unknown, ctx: ReadinessContext): import("../../../types/contracts.js").ArmKey | undefined;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { SURFACE_COPY } from '../../copy/surface.js';
|
|
1
2
|
import { formatDate } from '../../format/date.js';
|
|
2
3
|
import { actionGroupLabel } from '../../actions/actions.model.js';
|
|
3
|
-
import { unsupportedContentCopy, versionPageUnavailableCopy, versionPageUncheckedCopy, placementFailureCopy, pageInUseCopy, unpublishedPageCopy, READINESS_COPY as C, attributeNext, contentNext, goalPeopleNext, parameterNext, placementNext, ruleNext, versionsNext } from '../../copy/readiness.js';
|
|
4
|
+
import { asymmetricGoalsCopy, placementUncheckedCopy, interactingTestsCopy, sameAddressCopy, identicalVersionCopy, unsupportedContentCopy, versionPageUnavailableCopy, versionPageUncheckedCopy, placementFailureCopy, pageInUseCopy, unpublishedPageCopy, READINESS_COPY as C, attributeNext, contentNext, goalPeopleNext, parameterNext, placementNext, ruleNext, versionsNext } from '../../copy/readiness.js';
|
|
5
|
+
import { normalisePath } from '../../../runtime/normalisePath.js';
|
|
6
|
+
import { testPageCollection } from '../pagePicker/pagePicker.model.js';
|
|
4
7
|
import { SECTION_ORDER } from '../contracts.js';
|
|
5
8
|
const object = (value)=>value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
6
9
|
const first = (value)=>object(Array.isArray(value) ? value[0] : value);
|
|
@@ -17,8 +20,31 @@ const row = (section, next)=>({
|
|
|
17
20
|
const versions = row('versions', (detail)=>versionsNext(detailText(detail, C.versionFallback)));
|
|
18
21
|
/** Exhaustive mapping of the checkStart ReadinessCode union, including all ten invariant checks. */ export const READINESS = {
|
|
19
22
|
'make-content-unsupported': row('header', (detail)=>unsupportedContentCopy(text(detail, 'This page'))),
|
|
23
|
+
'goal-in-some-versions': {
|
|
24
|
+
...row('win', (detail)=>asymmetricGoalsCopy(detail)),
|
|
25
|
+
nextStep: 'Edit the versions'
|
|
26
|
+
},
|
|
27
|
+
'placement-unchecked': {
|
|
28
|
+
...row('versions', (detail)=>placementUncheckedCopy(text(object(detail).title ?? object(detail).path, 'This page'))),
|
|
29
|
+
nextStep: (detail)=>`Open ${text(object(detail).title ?? object(detail).path, 'the page')}`
|
|
30
|
+
},
|
|
20
31
|
'invalid-status': row('header', ()=>null),
|
|
21
32
|
'no-placements': row('what', (detail)=>detail === undefined ? C.noPlacements : placementFailureCopy(detail)),
|
|
33
|
+
'placement-removed': row('what', ()=>C.placementRemoved),
|
|
34
|
+
'placement-unpublished': {
|
|
35
|
+
...row('versions', (detail)=>(Array.isArray(detail) && detail.length ? detail : [
|
|
36
|
+
detail
|
|
37
|
+
]).map((placement)=>`The block you're testing is only on a draft of ${text(object(placement).title, 'this page')}. Publish the page before you start.`).join('\n')),
|
|
38
|
+
nextStep: 'Publish the page'
|
|
39
|
+
},
|
|
40
|
+
'duplicate-version-row': {
|
|
41
|
+
...row('versions', (detail)=>`The Experiment block on ${text(first(detail).title, 'this page')} has the same version twice. Remove one of them, then save.`),
|
|
42
|
+
nextStep: (detail)=>`Edit ${text(first(detail).title, 'this page')}`
|
|
43
|
+
},
|
|
44
|
+
'interacting-tests': {
|
|
45
|
+
...row('versions', (detail)=>interactingTestsCopy(text(first(detail).path, 'this page'), text(first(detail).status, 'running'), text(first(detail).name, 'another test'), first(detail).version === true)),
|
|
46
|
+
nextStep: (detail)=>`Open ${text(first(detail).name, 'the test')}${first(detail).version === true ? `\nEdit ${text(first(detail).path, 'this page')}` : ''}`
|
|
47
|
+
},
|
|
22
48
|
'empty-slot': row('versions', (detail, ctx)=>{
|
|
23
49
|
const placements = Array.isArray(detail) ? detail : [];
|
|
24
50
|
const missing = ctx.arms.find((item)=>item.kind !== 'holdout' && placements.some((placement)=>{
|
|
@@ -50,14 +76,39 @@ const versions = row('versions', (detail)=>versionsNext(detailText(detail, C.ver
|
|
|
50
76
|
'layer-full': row('versions', ()=>C.full),
|
|
51
77
|
'layer-unit-mismatch': row('header', ()=>C.differentPeople),
|
|
52
78
|
'page-in-use': {
|
|
53
|
-
...row('versions', (detail)=>{
|
|
79
|
+
...row('versions', (detail, ctx)=>{
|
|
54
80
|
const paths = object(detail).paths;
|
|
55
|
-
|
|
81
|
+
const path = text(Array.isArray(paths) ? paths[0] : undefined, 'this page');
|
|
82
|
+
return pageInUseCopy(path, pageArm(path, ctx)?.kind === 'variant');
|
|
56
83
|
}),
|
|
57
|
-
nextStep: C.
|
|
84
|
+
nextStep: C.choosePages
|
|
85
|
+
},
|
|
86
|
+
'page-no-targets': {
|
|
87
|
+
...row('versions', ()=>C.noTargets),
|
|
88
|
+
nextStep: 'Choose pages'
|
|
89
|
+
},
|
|
90
|
+
'unknown-collection': row('versions', ()=>"That page type isn't set up for tests."),
|
|
91
|
+
'version-identical': {
|
|
92
|
+
...row('versions', (detail, ctx)=>identicalVersionCopy(text(object(detail).path, object(detail).title ? `${group(object(detail).arm, ctx)} on ${text(object(detail).title, 'this page')}` : group(object(detail).arm, ctx)))),
|
|
93
|
+
nextStep: (detail, ctx)=>`Edit ${text(object(detail).path, group(object(detail).arm, ctx))}`
|
|
94
|
+
},
|
|
95
|
+
'version-same-address': {
|
|
96
|
+
...row('versions', (detail, ctx)=>sameAddressCopy(group(object(detail).arm, ctx), group(object(detail).otherArm, ctx), text(object(detail).path, 'this address'), ctx.collectionLabel)),
|
|
97
|
+
nextStep: 'Choose pages'
|
|
98
|
+
},
|
|
99
|
+
'page-target-unpublished': {
|
|
100
|
+
...row('versions', (detail, ctx)=>{
|
|
101
|
+
const path = text(typeof detail === 'string' ? detail : object(detail).path, 'This page');
|
|
102
|
+
const arm = ctx.arms.find((item)=>item.key === object(detail).arm) ?? pageArm(path, ctx);
|
|
103
|
+
const placement = (arm ? ctx.pagePlacements?.find((entry)=>entry.arm === arm.key) : undefined) ?? ctx.pagePlacements?.find((entry)=>normalisePath(entry.path) === normalisePath(path));
|
|
104
|
+
return unpublishedPageCopy(path, ctx.pagePlacements && ctx.collectionLabel ? {
|
|
105
|
+
original: arm?.kind === 'control',
|
|
106
|
+
found: placement?.id != null && placement.published === false,
|
|
107
|
+
collection: ctx.collectionLabel
|
|
108
|
+
} : undefined);
|
|
109
|
+
}),
|
|
110
|
+
nextStep: C.choosePages
|
|
58
111
|
},
|
|
59
|
-
'page-no-targets': row('versions', ()=>C.noTargets),
|
|
60
|
-
'page-target-unpublished': row('versions', (detail)=>unpublishedPageCopy(text(detail, 'This page'))),
|
|
61
112
|
'page-targets-unchecked': row('versions', ()=>C.uncheckedPages),
|
|
62
113
|
'version-page-unavailable': row('versions', (detail)=>versionPageUnavailableCopy(text(detail, 'This page'))),
|
|
63
114
|
'version-page-unchecked': row('versions', (detail)=>versionPageUncheckedCopy(text(detail, 'This page'))),
|
|
@@ -91,15 +142,28 @@ export function nextStep(preflight, ctx) {
|
|
|
91
142
|
...SECTION_ORDER
|
|
92
143
|
]){
|
|
93
144
|
for (const check of preflight?.checks ?? []){
|
|
145
|
+
if (!Object.hasOwn(READINESS, check.code)) {
|
|
146
|
+
if (!check.ok && section === SECTION_ORDER[0]) return {
|
|
147
|
+
section,
|
|
148
|
+
sentence: SURFACE_COPY.next,
|
|
149
|
+
code: check.code
|
|
150
|
+
};
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
94
153
|
const mapping = READINESS[check.code];
|
|
95
154
|
if (check.ok || mapping.section !== section) continue;
|
|
96
155
|
const sentence = mapping.next(check.detail, ctx);
|
|
156
|
+
const nextStep = typeof mapping.nextStep === 'function' ? mapping.nextStep(check.detail, ctx) : mapping.nextStep;
|
|
157
|
+
const arm = readinessArm(check.code, check.detail, ctx);
|
|
97
158
|
if (sentence) return {
|
|
98
159
|
section,
|
|
99
160
|
sentence,
|
|
100
161
|
code: check.code,
|
|
101
|
-
...
|
|
102
|
-
|
|
162
|
+
...arm ? {
|
|
163
|
+
arm
|
|
164
|
+
} : {},
|
|
165
|
+
...nextStep ? {
|
|
166
|
+
nextStep
|
|
103
167
|
} : {}
|
|
104
168
|
};
|
|
105
169
|
}
|
|
@@ -109,7 +173,7 @@ export function nextStep(preflight, ctx) {
|
|
|
109
173
|
export function sectionDone(test) {
|
|
110
174
|
return Object.fromEntries(SECTION_ORDER.map((section)=>[
|
|
111
175
|
section,
|
|
112
|
-
test.preflight ? !test.preflight.checks.some((check)=>!check.ok && READINESS[check.code].section === section) : section === 'who' || section === 'advanced'
|
|
176
|
+
test.preflight ? !test.preflight.checks.some((check)=>!check.ok && (Object.hasOwn(READINESS, check.code) ? READINESS[check.code].section : SECTION_ORDER[0]) === section) : section === 'who' || section === 'advanced'
|
|
113
177
|
]));
|
|
114
178
|
}
|
|
115
179
|
export function displayDate(value) {
|
|
@@ -121,3 +185,22 @@ export function daysRemaining(doc, now) {
|
|
|
121
185
|
const start = typeof doc.startedAt === 'string' ? Date.parse(doc.startedAt) : NaN;
|
|
122
186
|
return typeof days === 'number' && days > 0 && Number.isFinite(start) ? Math.max(0, Math.ceil(days - (now - start) / 86_400_000)) : null;
|
|
123
187
|
}
|
|
188
|
+
function pageArm(path, ctx) {
|
|
189
|
+
return ctx.arms.find((arm)=>arm.pageTarget && normalisePath(arm.pageTarget) === normalisePath(path));
|
|
190
|
+
}
|
|
191
|
+
export function pageReadinessContext(doc, preflight, surface) {
|
|
192
|
+
return {
|
|
193
|
+
...doc,
|
|
194
|
+
flagPoints: surface.flagPoints,
|
|
195
|
+
pagePlacements: preflight?.pagePlacements,
|
|
196
|
+
collectionLabel: testPageCollection(surface.pageCollections, doc, preflight?.pagePlacements)?.label
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/** First affected row in arm order; shared by the wizard and the test-page jump. */ export function readinessArm(code, detail, ctx) {
|
|
200
|
+
if (code === 'version-same-address') return ctx.arms.find((arm)=>arm.key === object(detail).arm)?.key;
|
|
201
|
+
if (code === 'page-no-targets') return ctx.arms.find((arm)=>arm.kind !== 'holdout' && !arm.pageTarget)?.key;
|
|
202
|
+
const paths = code === 'page-in-use' ? object(detail).paths : code === 'page-target-unpublished' ? [
|
|
203
|
+
detail
|
|
204
|
+
] : [];
|
|
205
|
+
return ctx.arms.find((arm)=>arm.kind !== 'holdout' && arm.pageTarget && Array.isArray(paths) && paths.some((path)=>typeof path === 'string' && normalisePath(path) === normalisePath(arm.pageTarget)))?.key;
|
|
206
|
+
}
|
|
@@ -8,7 +8,9 @@ export declare function ReleasePagesDialog({ id, apiRoute, onClose, onSuccess, o
|
|
|
8
8
|
onRefusal(message: string): void;
|
|
9
9
|
}): import("react").JSX.Element;
|
|
10
10
|
/** An inaccessible or deleted author never hides the recorded release date. */
|
|
11
|
-
export declare function PagesReleased({ decision, apiRoute }: {
|
|
11
|
+
export declare function PagesReleased({ decision, apiRoute, userId, userCollection: collection }: {
|
|
12
12
|
decision: PageReleaseDecision;
|
|
13
13
|
apiRoute: string;
|
|
14
|
+
userId?: DocId;
|
|
15
|
+
userCollection?: string;
|
|
14
16
|
}): import("react").JSX.Element;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { useAuth, useConfig } from '@payloadcms/ui';
|
|
5
4
|
import { Button } from '../../../ui/Button.js';
|
|
6
5
|
import { Dialog } from '../../../ui/Dialog.js';
|
|
7
6
|
import { createApi } from '../../api.js';
|
|
@@ -63,10 +62,7 @@ export function ReleasePagesDialog({ id, apiRoute, onClose, onSuccess, onRefusal
|
|
|
63
62
|
]
|
|
64
63
|
});
|
|
65
64
|
}
|
|
66
|
-
/** An inaccessible or deleted author never hides the recorded release date. */ export function PagesReleased({ decision, apiRoute }) {
|
|
67
|
-
const { user } = useAuth();
|
|
68
|
-
const { config } = useConfig();
|
|
69
|
-
const collection = config.admin.user;
|
|
65
|
+
/** An inaccessible or deleted author never hides the recorded release date. */ export function PagesReleased({ decision, apiRoute, userId, userCollection: collection }) {
|
|
70
66
|
const by = decision.pagesReleasedBy;
|
|
71
67
|
const [resolved, setResolved] = useState(null);
|
|
72
68
|
const key = JSON.stringify([
|
|
@@ -74,7 +70,7 @@ export function ReleasePagesDialog({ id, apiRoute, onClose, onSuccess, onRefusal
|
|
|
74
70
|
collection,
|
|
75
71
|
by
|
|
76
72
|
]);
|
|
77
|
-
const own = pagesReleasedBy(by,
|
|
73
|
+
const own = pagesReleasedBy(by, userId);
|
|
78
74
|
useEffect(()=>{
|
|
79
75
|
if (!by || own || !collection) return;
|
|
80
76
|
const controller = new AbortController();
|
|
@@ -109,7 +105,7 @@ export function ReleasePagesDialog({ id, apiRoute, onClose, onSuccess, onRefusal
|
|
|
109
105
|
key,
|
|
110
106
|
own
|
|
111
107
|
]);
|
|
112
|
-
const name = own ?? pagesReleasedBy(by,
|
|
108
|
+
const name = own ?? pagesReleasedBy(by, userId, resolved?.key === key ? resolved.author : null);
|
|
113
109
|
return /*#__PURE__*/ _jsx("p", {
|
|
114
110
|
children: pagesReleasedCopy(formatDate(decision.pagesReleasedAt), name)
|
|
115
111
|
});
|
|
@@ -27,6 +27,7 @@ import { DecideDialog } from '../../actions/DecideDialog.js';
|
|
|
27
27
|
import { Banner } from '../../../ui/Banner.js';
|
|
28
28
|
import { canReleasePages } from '../../results/releasePages.model.js';
|
|
29
29
|
import { PagesReleased, ReleasePagesDialog } from './ReleasePages.js';
|
|
30
|
+
import { usePlacementLabels } from '../../placements/usePlacementLabels.js';
|
|
30
31
|
export function ResultsBody({ id, surface, onRecomputed, onPagesReleased, renderPage }) {
|
|
31
32
|
// A different test owns an independent selection and action lifecycle.
|
|
32
33
|
return /*#__PURE__*/ _jsx(ResultsContent, {
|
|
@@ -116,12 +117,20 @@ function ResultsContent({ id, surface, onRecomputed, onPagesReleased, renderPage
|
|
|
116
117
|
isDecidedTestRound,
|
|
117
118
|
winnerLabel: winner
|
|
118
119
|
}) : null;
|
|
120
|
+
const placementLabels = usePlacementLabels({
|
|
121
|
+
details: shown?.health?.filter((item)=>item.code === 'placement-unchecked').map((item)=>item.detail) ?? [],
|
|
122
|
+
apiRoute: surface.apiRoute,
|
|
123
|
+
adminRoute: surface.adminRoute,
|
|
124
|
+
canManage: manage,
|
|
125
|
+
collectionTitles: surface.collectionTitles
|
|
126
|
+
});
|
|
119
127
|
const context = {
|
|
120
128
|
status,
|
|
121
129
|
phase,
|
|
122
130
|
inLayer: doc?.layer != null,
|
|
123
131
|
layerSlices: doc?.layerSlices,
|
|
124
|
-
allocation: doc?.allocation
|
|
132
|
+
allocation: doc?.allocation,
|
|
133
|
+
placementLabels
|
|
125
134
|
};
|
|
126
135
|
const primary = phase?.metrics.find((metric)=>metric.role === 'primary');
|
|
127
136
|
// The endpoint decides the current round; historical rounds are read-only.
|
|
@@ -147,7 +156,9 @@ function ResultsContent({ id, surface, onRecomputed, onPagesReleased, renderPage
|
|
|
147
156
|
// Release details come only from the manager's own document, never the results response.
|
|
148
157
|
const released = manage && doc?.decision?.pagesReleasedAt ? /*#__PURE__*/ _jsx(PagesReleased, {
|
|
149
158
|
decision: doc.decision,
|
|
150
|
-
apiRoute: surface.apiRoute
|
|
159
|
+
apiRoute: surface.apiRoute,
|
|
160
|
+
userId: surface.userId,
|
|
161
|
+
userCollection: surface.userCollection
|
|
151
162
|
}) : null;
|
|
152
163
|
const meta = /*#__PURE__*/ _jsxs(_Fragment, {
|
|
153
164
|
children: [
|
|
@@ -263,6 +274,9 @@ function ResultsContent({ id, surface, onRecomputed, onPagesReleased, renderPage
|
|
|
263
274
|
}, context),
|
|
264
275
|
sinceShipping: rolloutLine(shown, phase, phases, decision ?? undefined)
|
|
265
276
|
}),
|
|
277
|
+
primary?.clickGoal ? /*#__PURE__*/ _jsx("p", {
|
|
278
|
+
children: C.clickPrimary
|
|
279
|
+
}) : null,
|
|
266
280
|
/*#__PURE__*/ _jsxs("div", {
|
|
267
281
|
className: "xp-stat-tiles",
|
|
268
282
|
children: [
|
|
@@ -309,6 +323,9 @@ function ResultsContent({ id, surface, onRecomputed, onPagesReleased, renderPage
|
|
|
309
323
|
})
|
|
310
324
|
]
|
|
311
325
|
}) : null,
|
|
326
|
+
shown.goalFairnessNotice ? /*#__PURE__*/ _jsx("p", {
|
|
327
|
+
children: shown.goalFairnessNotice
|
|
328
|
+
}) : null,
|
|
312
329
|
/*#__PURE__*/ _jsx(DataQualityPanel, {
|
|
313
330
|
problem: shown.verdict.code === 'data-problem',
|
|
314
331
|
items: dataQuality(shown, context)
|
|
@@ -340,6 +357,7 @@ function ResultsContent({ id, surface, onRecomputed, onPagesReleased, renderPage
|
|
|
340
357
|
})
|
|
341
358
|
}),
|
|
342
359
|
/*#__PURE__*/ _jsx(PreviewLinks, {
|
|
360
|
+
apiRoute: surface.apiRoute,
|
|
343
361
|
experimentId: id,
|
|
344
362
|
flagPoint: doc?.flagPoint,
|
|
345
363
|
placements: placements,
|
|
@@ -360,6 +378,7 @@ function ResultsContent({ id, surface, onRecomputed, onPagesReleased, renderPage
|
|
|
360
378
|
]
|
|
361
379
|
}) : null,
|
|
362
380
|
deciding && manage && phase ? /*#__PURE__*/ _jsx(DecideDialog, {
|
|
381
|
+
apiRoute: surface.apiRoute,
|
|
363
382
|
id: id,
|
|
364
383
|
arms: phase.arms,
|
|
365
384
|
checks: checks,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { surfaceUrls } from '../../surfaceUrls.js';
|
|
3
4
|
import { useEffect, useState } from 'react';
|
|
4
5
|
import { formatAdminURL } from 'payload/shared';
|
|
5
6
|
import { SurfaceShell } from '../SurfaceShell.js';
|
|
@@ -8,7 +9,7 @@ import { Banner, StatusChip } from '../../../ui/Feedback.js';
|
|
|
8
9
|
import { createApi } from '../../api.js';
|
|
9
10
|
import { availableActions, actionGroupLabel } from '../../actions/actions.model.js';
|
|
10
11
|
import { AllocateAction, ConfirmAction } from '../readiness/ActionDialogs.js';
|
|
11
|
-
import { READINESS, daysRemaining, displayDate, nextStep } from '../readiness/readiness.model.js';
|
|
12
|
+
import { READINESS, daysRemaining, displayDate, nextStep, pageReadinessContext } from '../readiness/readiness.model.js';
|
|
12
13
|
import { READINESS_COPY as R, runningCopy, stoppedCopy, decidedCopy } from '../../copy/readiness.js';
|
|
13
14
|
import { RESULTS_COPY as C } from '../../copy/results.js';
|
|
14
15
|
import { TEST_PAGE } from '../../copy/testPage.js';
|
|
@@ -54,10 +55,7 @@ export function ResultsHeader({ test, surface, resultsVersion, children, actions
|
|
|
54
55
|
'allocate',
|
|
55
56
|
'stop'
|
|
56
57
|
].indexOf(b.id) : 0);
|
|
57
|
-
const next = nextStep(test.preflight,
|
|
58
|
-
...doc,
|
|
59
|
-
flagPoints: surface.flagPoints
|
|
60
|
-
});
|
|
58
|
+
const next = nextStep(test.preflight, pageReadinessContext(doc, test.preflight, surface));
|
|
61
59
|
const ready = Boolean(test.preflight && !test.preflightPending && !test.preflightError && test.preflight.checks.every((check)=>check.ok));
|
|
62
60
|
const startReason = next?.sentence ?? (!ready ? test.preflightError ? R.checkError : R.checking : undefined);
|
|
63
61
|
const action = available.find((item)=>item.id === selected);
|
|
@@ -72,10 +70,7 @@ export function ResultsHeader({ test, surface, resultsVersion, children, actions
|
|
|
72
70
|
crumbs: [
|
|
73
71
|
{
|
|
74
72
|
label: C.tests,
|
|
75
|
-
href:
|
|
76
|
-
adminRoute: surface.adminRoute,
|
|
77
|
-
path: '/experiments'
|
|
78
|
-
})
|
|
73
|
+
href: surface.canManage ? surfaceUrls.home(surface.adminRoute) : undefined
|
|
79
74
|
},
|
|
80
75
|
{
|
|
81
76
|
label: doc.name,
|
|
@@ -160,10 +155,7 @@ export function ReaderResultsShell({ surface, children, data }) {
|
|
|
160
155
|
crumbs: [
|
|
161
156
|
{
|
|
162
157
|
label: C.tests,
|
|
163
|
-
href:
|
|
164
|
-
adminRoute: surface.adminRoute,
|
|
165
|
-
path: '/experiments'
|
|
166
|
-
})
|
|
158
|
+
href: surface.canManage ? surfaceUrls.home(surface.adminRoute) : undefined
|
|
167
159
|
},
|
|
168
160
|
{
|
|
169
161
|
label: title
|
|
@@ -29,17 +29,34 @@ export declare function useResults(id: DocId, { apiRoute, canReadResults, canMan
|
|
|
29
29
|
canManage?: boolean;
|
|
30
30
|
}): {
|
|
31
31
|
api: {
|
|
32
|
+
findTestIdBySlug: (slug: string) => Promise<Extract<ApiResult<DocId>, {
|
|
33
|
+
ok: false;
|
|
34
|
+
}> | {
|
|
35
|
+
ok: true;
|
|
36
|
+
data: DocId;
|
|
37
|
+
}>;
|
|
38
|
+
deleteTest: (id: DocId) => Promise<ApiResult<unknown>>;
|
|
39
|
+
wrapBlock: (body: import("../../../types/endpoints.js").WrapBlockBody) => Promise<ApiResult<Record<string, unknown>>>;
|
|
40
|
+
pages: (query: {
|
|
41
|
+
collection: string;
|
|
42
|
+
q?: string;
|
|
43
|
+
path?: string;
|
|
44
|
+
page?: number;
|
|
45
|
+
}, signal?: AbortSignal) => Promise<ApiResult<import("../../../types/endpoints.js").PagesResult>>;
|
|
46
|
+
placementStatus: (body: import("../../../types/endpoints.js").PlacementStatusBody) => Promise<ApiResult<import("../../../types/endpoints.js").PlacementStatusResult>>;
|
|
32
47
|
start: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
|
|
33
48
|
allocate: (id: DocId, body: import("../../../types/endpoints.js").AllocateBody, options?: {
|
|
34
49
|
notFound?: string;
|
|
50
|
+
forbidden?: string;
|
|
35
51
|
codes?: Readonly<Record<string, string>>;
|
|
36
52
|
fallback?: string;
|
|
37
53
|
}) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
|
|
38
54
|
addMetric: (id: DocId, body: import("../../../types/endpoints.js").AddMetricBody, options?: {
|
|
39
55
|
notFound?: string;
|
|
56
|
+
forbidden?: string;
|
|
40
57
|
codes?: Readonly<Record<string, string>>;
|
|
41
58
|
fallback?: string;
|
|
42
|
-
}) => Promise<ApiResult<import("../../../types/endpoints.js").
|
|
59
|
+
}) => Promise<ApiResult<import("../../../types/endpoints.js").AddMetricResult>>;
|
|
43
60
|
stop: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
|
|
44
61
|
decide: (id: DocId, body: import("../../../types/endpoints.js").DecideBody) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
|
|
45
62
|
releaseHoldout: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
|
|
@@ -48,6 +65,7 @@ export declare function useResults(id: DocId, { apiRoute, canReadResults, canMan
|
|
|
48
65
|
dismissContentEntry: (id: DocId, body: import("../../../types/endpoints.js").DismissContentEntryBody) => Promise<ApiResult<import("../../../types/endpoints.js").DismissContentEntryResult>>;
|
|
49
66
|
restoreContentEntry: (id: DocId, body: import("../../../types/endpoints.js").RestoreContentEntryBody) => Promise<ApiResult<import("../../../types/endpoints.js").RestoreContentEntryResult>>;
|
|
50
67
|
archive: (id: DocId, body: import("../../../types/endpoints.js").ArchiveBody) => Promise<ApiResult<import("../../../types/endpoints.js").TransitionSuccess>>;
|
|
68
|
+
clickKeys: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").ClickKeysResult>>;
|
|
51
69
|
preflight: (id: DocId) => Promise<ApiResult<import("../../../types/endpoints.js").PreflightResult>>;
|
|
52
70
|
previewToken: (id: DocId, arm: string) => Promise<ApiResult<import("../../../types/endpoints.js").PreviewTokenResult>>;
|
|
53
71
|
results: (id: DocId, options?: {
|
|
@@ -55,6 +73,7 @@ export declare function useResults(id: DocId, { apiRoute, canReadResults, canMan
|
|
|
55
73
|
series?: boolean;
|
|
56
74
|
} & {
|
|
57
75
|
notFound?: string;
|
|
76
|
+
forbidden?: string;
|
|
58
77
|
codes?: Readonly<Record<string, string>>;
|
|
59
78
|
fallback?: string;
|
|
60
79
|
}) => Promise<ApiResult<ResultsResponse>>;
|