Display cookie pattern source badge in category table
Show the origin of each cookie pattern (Script vs Pre-existing) as a badge with a tooltip in the cookies configuration table. Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -51,6 +51,7 @@ export function AddCookieRow({
|
||||
name: data.name,
|
||||
maxAgeSeconds: toMaxAgeSeconds(data.duration.value, data.duration.unit),
|
||||
description: data.description,
|
||||
excluded: false,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -62,6 +63,7 @@ export function AddCookieRow({
|
||||
placeholder={__("Cookie name")}
|
||||
/>
|
||||
</Td>
|
||||
<Td />
|
||||
<Td className="pr-3">
|
||||
<Controller
|
||||
name="duration"
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
Td,
|
||||
Th,
|
||||
Thead,
|
||||
Toggle,
|
||||
Tr,
|
||||
useToast,
|
||||
} from "@probo/ui";
|
||||
@@ -50,6 +51,7 @@ export interface CookieEntry {
|
||||
name: string;
|
||||
maxAgeSeconds: number | null;
|
||||
description: string;
|
||||
excluded: boolean;
|
||||
}
|
||||
|
||||
export const categorySectionFragment = graphql`
|
||||
@@ -71,6 +73,8 @@ export const categorySectionFragment = graphql`
|
||||
displayName
|
||||
maxAgeSeconds
|
||||
description
|
||||
excluded
|
||||
source
|
||||
...EditCookieRowFragment
|
||||
}
|
||||
}
|
||||
@@ -127,6 +131,8 @@ const createPatternMutation = graphql`
|
||||
displayName
|
||||
maxAgeSeconds
|
||||
description
|
||||
excluded
|
||||
source
|
||||
...EditCookieRowFragment
|
||||
}
|
||||
}
|
||||
@@ -152,6 +158,7 @@ const updatePatternMutation = graphql`
|
||||
displayName
|
||||
maxAgeSeconds
|
||||
description
|
||||
excluded
|
||||
updatedAt
|
||||
}
|
||||
cookieBanner {
|
||||
@@ -342,6 +349,7 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
||||
displayName: cookie.name,
|
||||
maxAgeSeconds: cookie.maxAgeSeconds,
|
||||
description: cookie.description,
|
||||
excluded: cookie.excluded,
|
||||
},
|
||||
},
|
||||
onCompleted(_response, errors) {
|
||||
@@ -378,6 +386,37 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
||||
});
|
||||
};
|
||||
|
||||
const handleToggleExcluded = (patternId: string, excluded: boolean) => {
|
||||
updatePattern({
|
||||
variables: {
|
||||
input: {
|
||||
cookiePatternId: patternId,
|
||||
excluded,
|
||||
},
|
||||
},
|
||||
onCompleted(_response, errors) {
|
||||
if (errors?.length) {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: errors[0].message,
|
||||
variant: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
},
|
||||
onError(error) {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: formatError(
|
||||
__("Failed to update cookie"),
|
||||
error as GraphQLError,
|
||||
),
|
||||
variant: "error",
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteCookie = (patternId: string) => {
|
||||
deletePattern({
|
||||
variables: {
|
||||
@@ -568,7 +607,8 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
||||
<table className="w-full text-left">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{__("Name")}</Th>
|
||||
<Th><span className="pl-10">{__("Name")}</span></Th>
|
||||
<Th>{__("Source")}</Th>
|
||||
<Th>{__("Duration")}</Th>
|
||||
<Th>{__("Description")}</Th>
|
||||
<Th className="w-20" />
|
||||
@@ -587,9 +627,30 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<Tr key={pattern.id}>
|
||||
<Tr key={pattern.id} className={pattern.excluded ? "opacity-50" : undefined}>
|
||||
<Td>
|
||||
<code className="text-sm font-mono">{pattern.displayName}</code>
|
||||
<div className="flex items-center gap-2">
|
||||
<Toggle
|
||||
size="sm"
|
||||
checked={!pattern.excluded}
|
||||
onChange={() => handleToggleExcluded(pattern.id, !pattern.excluded)}
|
||||
disabled={isUpdatingPattern}
|
||||
title={__("Include this cookie in the banner")}
|
||||
/>
|
||||
<code className="text-sm font-mono">{pattern.displayName}</code>
|
||||
</div>
|
||||
</Td>
|
||||
<Td>
|
||||
<Badge
|
||||
variant={pattern.source === "SCRIPT" ? "info" : "neutral"}
|
||||
title={
|
||||
pattern.source === "SCRIPT"
|
||||
? __("Set by a script at runtime")
|
||||
: __("Already present when the page was loaded")
|
||||
}
|
||||
>
|
||||
{pattern.source === "SCRIPT" ? __("Script") : __("Pre-existing")}
|
||||
</Badge>
|
||||
</Td>
|
||||
<Td className="text-sm text-muted-foreground">
|
||||
{humanizeSeconds(pattern.maxAgeSeconds ?? null)}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import { fromMaxAgeSeconds, toMaxAgeSeconds } from "@probo/helpers";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { Button, DurationInput, Input, Td, Tr } from "@probo/ui";
|
||||
import { Button, DurationInput, Input, Td, Toggle, Tr } from "@probo/ui";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { useFragment } from "react-relay";
|
||||
import { graphql } from "relay-runtime";
|
||||
@@ -28,6 +28,7 @@ export const editCookieRowFragment = graphql`
|
||||
displayName
|
||||
maxAgeSeconds
|
||||
description
|
||||
excluded
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -35,6 +36,7 @@ interface CookieFormValues {
|
||||
name: string;
|
||||
duration: { value: string; unit: string };
|
||||
description: string;
|
||||
excluded: boolean;
|
||||
}
|
||||
|
||||
interface EditCookieRowProps {
|
||||
@@ -59,6 +61,7 @@ export function EditCookieRow({
|
||||
name: cookie.displayName,
|
||||
duration: initial,
|
||||
description: cookie.description,
|
||||
excluded: cookie.excluded,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -67,17 +70,33 @@ export function EditCookieRow({
|
||||
name: data.name,
|
||||
maxAgeSeconds: toMaxAgeSeconds(data.duration.value, data.duration.unit),
|
||||
description: data.description,
|
||||
excluded: data.excluded,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Tr>
|
||||
<Td className="pr-3">
|
||||
<Input
|
||||
{...register("name")}
|
||||
placeholder={__("Cookie name")}
|
||||
/>
|
||||
<div className="flex items-center gap-2">
|
||||
<Controller
|
||||
name="excluded"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Toggle
|
||||
size="sm"
|
||||
checked={!field.value}
|
||||
onChange={checked => field.onChange(!checked)}
|
||||
title={__("Include this cookie in the banner")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Input
|
||||
{...register("name")}
|
||||
placeholder={__("Cookie name")}
|
||||
/>
|
||||
</div>
|
||||
</Td>
|
||||
<Td />
|
||||
<Td className="pr-3">
|
||||
<Controller
|
||||
name="duration"
|
||||
@@ -99,7 +118,7 @@ export function EditCookieRow({
|
||||
/>
|
||||
</Td>
|
||||
<Td>
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
onClick={() => void handleSubmit(onSubmit)()}
|
||||
disabled={isUpdating}
|
||||
|
||||
Reference in New Issue
Block a user