Skip to content

Commit 5d48009

Browse files
committed
add activatable status indicator
1 parent 5308540 commit 5d48009

6 files changed

Lines changed: 69 additions & 13 deletions

File tree

packages/client/src/clients/guide/client.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@ const predicate = (
217217
return false;
218218
}
219219

220+
return checkActivatable(guide, location);
221+
};
222+
223+
export const checkActivatable = (
224+
guide: KnockGuide,
225+
location: string | undefined,
226+
) => {
220227
const url = location ? newUrl(location) : undefined;
221228

222229
const urlRules = guide.activation_url_rules || [];

packages/client/src/clients/guide/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
export { KnockGuideClient, DEBUG_QUERY_PARAMS } from "./client";
1+
export {
2+
KnockGuideClient,
3+
DEBUG_QUERY_PARAMS,
4+
checkActivatable,
5+
} from "./client";
26
export type {
37
KnockGuide,
48
KnockGuideStep,

packages/react/src/modules/guide/components/Toolbar/V2/GuideRow.tsx

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import { Button } from "@telegraph/button";
2-
import { Stack } from "@telegraph/layout";
2+
import { Box, Stack } from "@telegraph/layout";
33
import { Tag } from "@telegraph/tag";
44
import { Tooltip } from "@telegraph/tooltip";
55
import { Text } from "@telegraph/typography";
6-
import { CheckCircle2, CircleDashed, Eye, UserCircle2 } from "lucide-react";
6+
import {
7+
CheckCircle2,
8+
CircleDashed,
9+
Eye,
10+
LocateFixed,
11+
UserCircle2,
12+
} from "lucide-react";
713
import * as React from "react";
814

915
import { GuideHoverCard } from "./GuideHoverCard";
@@ -39,6 +45,27 @@ export const GuideRow = ({ guide, orderIndex }: Props) => {
3945
</Stack>
4046

4147
<Stack justify="flex-end">
48+
{guide.__typename === "Guide" && (
49+
<Stack gap="1">
50+
<Tooltip
51+
label="Current location does not match the activation conditions"
52+
enabled={!guide.inspection.activatable.status}
53+
>
54+
<Button
55+
px="1"
56+
size="1"
57+
variant="soft"
58+
color={guide.inspection.activatable.status ? "green" : "red"}
59+
leadingIcon={{ icon: LocateFixed, alt: "Target" }}
60+
/>
61+
</Tooltip>
62+
</Stack>
63+
)}
64+
{guide.__typename === "Guide" && (
65+
<Stack px="1" align="center">
66+
<Box h="3" borderLeft="px" borderColor="gray-6" />
67+
</Stack>
68+
)}
4269
<Stack gap="1">
4370
{guide.__typename === "Guide" && (
4471
<>
@@ -49,6 +76,7 @@ export const GuideRow = ({ guide, orderIndex }: Props) => {
4976
: guide.inspection.targetable.message
5077
}
5178
// enabled={!guide.inspection.targetable.status}
79+
enabled={!guide.inspection.targetable.status}
5280
>
5381
<Button
5482
px="1"

packages/react/src/modules/guide/components/Toolbar/V2/GuidesListDisplaySelect.tsx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@ export const GuidesListDisplaySelect = ({ value, onChange }: Props) => {
2222
style: { zIndex: MAX_Z_INDEX },
2323
}}
2424
>
25-
{/* NOTE: Commented out until we can show relevant indicators.
26-
<Select.Option size="1" value="current-page">
27-
Displayable on current page
28-
</Select.Option>
29-
*/}
25+
<Select.Option size="1" value="current-page">
26+
Displayable on current page
27+
</Select.Option>
3028
<Select.Option size="1" value="all-eligible">
3129
All eligible guides for user
3230
</Select.Option>

packages/react/src/modules/guide/components/Toolbar/V2/V2.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import { detectToolbarParam } from "./helpers";
1717
import {
1818
InspectionResult,
19+
checkUsable,
1920
useInspectGuideClientStore,
2021
} from "./useInspectGuideClientStore";
2122

@@ -27,10 +28,12 @@ const GuidesList = ({
2728
displayOption: DisplayOption;
2829
}) => {
2930
return guides.map((guide, idx) => {
31+
if (displayOption === "current-page" && !checkUsable(guide)) {
32+
return null;
33+
}
3034
if (displayOption === "all-eligible" && !guide.annotation.isEligible) {
3135
return null;
3236
}
33-
3437
return <GuideRow key={guide.key} guide={guide} orderIndex={idx} />;
3538
});
3639
};
@@ -39,7 +42,7 @@ export const V2 = () => {
3942
const { client } = useGuideContext();
4043

4144
const [guidesListDisplayed, setGuidesListDisplayed] =
42-
React.useState<DisplayOption>("all-eligible");
45+
React.useState<DisplayOption>("current-page");
4346

4447
const [isVisible, setIsVisible] = React.useState(detectToolbarParam());
4548
const [isCollapsed, setIsCollapsed] = React.useState(true);

packages/react/src/modules/guide/components/Toolbar/V2/useInspectGuideClientStore.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
KnockGuide,
33
KnockGuideClientStoreState,
44
KnockGuideIneligibilityMarker,
5+
checkActivatable,
56
} from "@knocklabs/client";
67
import { useGuideContext, useStore } from "@knocklabs/react-core";
78

@@ -21,6 +22,10 @@ type TargetableStatusFalse = {
2122
};
2223
type TargetableStatus = TargetableStatusTrue | TargetableStatusFalse;
2324

25+
type ActivatableStatus = {
26+
status: boolean;
27+
};
28+
2429
// Archived: `false` status = good
2530
type ArchivedStatus = {
2631
status: boolean;
@@ -31,6 +36,7 @@ type AnnotatedStatuses = {
3136
active: ActiveStatus;
3237
targetable: TargetableStatus;
3338
archived: ArchivedStatus;
39+
activatable: ActivatableStatus;
3440
};
3541

3642
type GuideAnnotation = AnnotatedStatuses & {
@@ -43,6 +49,14 @@ export type AnnotatedGuide = KnockGuide & {
4349
annotation: GuideAnnotation;
4450
};
4551

52+
export const checkUsable = (guide: AnnotatedGuide | MissingGuide) => {
53+
if (guide.__typename === "MissingGuide") return false;
54+
if (!checkEligible(guide)) return false;
55+
if (!guide.annotation.activatable.status) return false;
56+
57+
return true;
58+
};
59+
4660
// Exists and ordered in control but absent in switchboard (therefore not
4761
// included in the api response), which implies a newly created guide that has
4862
// never been published to switchboard.
@@ -101,19 +115,20 @@ const resolveIsEligible = ({
101115

102116
type StoreStateSnapshot = Pick<
103117
KnockGuideClientStoreState,
104-
"guides" | "guideGroups" | "ineligibleGuides" | "debug"
118+
"location" | "guides" | "guideGroups" | "ineligibleGuides" | "debug"
105119
>;
106120

107121
const annotateGuide = (
108122
guide: KnockGuide,
109123
snapshot: StoreStateSnapshot,
110124
): AnnotatedGuide => {
111-
const { ineligibleGuides } = snapshot;
125+
const { ineligibleGuides, location } = snapshot;
112126
const marker = ineligibleGuides[guide.key];
113127

114128
const statuses: AnnotatedStatuses = {
115129
active: { status: guide.active },
116130
targetable: marker ? toTargetableStatus(marker) : { status: true },
131+
activatable: { status: checkActivatable(guide, location) },
117132
archived: marker ? toArchivedStatus(marker) : { status: false },
118133
};
119134

@@ -143,8 +158,9 @@ export const useInspectGuideClientStore = (): InspectionResult | undefined => {
143158
const { client } = useGuideContext();
144159

145160
// Extract a snapshot of the client store state for debugging.
146-
const snapshot = useStore(client.store, (state) => {
161+
const snapshot: StoreStateSnapshot = useStore(client.store, (state) => {
147162
return {
163+
location: state.location,
148164
guides: state.guides,
149165
guideGroups: state.guideGroups,
150166
ineligibleGuides: state.ineligibleGuides,

0 commit comments

Comments
 (0)