frontend: rename detection page to trackers, drop SCRIPT/IFRAME branches

- Rename configuration/detection/ to configuration/trackers/.
- Rename files: CookieBannerDetectionPage* → CookieBannerTrackersPage*,
  DetectionPatternRow* → TrackerPatternRow*.
- Update GraphQL operation/fragment names and connection keys.
- Update route path "detection" → "trackers" and tab label.
- Remove SCRIPT/IFRAME cases from trackerTypeLabel() switch.

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-05-08 19:13:45 +04:00
parent 36dbe47192
commit 030fdf4be3
8 changed files with 67 additions and 60 deletions

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
import { ClipboardTextIcon, MagnifyingGlassIcon } from "@phosphor-icons/react"; import { ClipboardTextIcon, CodeIcon, MagnifyingGlassIcon } from "@phosphor-icons/react";
import { formatError, type GraphQLError } from "@probo/helpers"; import { formatError, type GraphQLError } from "@probo/helpers";
import { useTranslate } from "@probo/i18n"; import { useTranslate } from "@probo/i18n";
import { import {
@@ -247,9 +247,13 @@ export default function CookieBannerConfigLayout({ queryRef }: CookieBannerConfi
<IconGlobe size={20} /> <IconGlobe size={20} />
{__("Translations")} {__("Translations")}
</TabLink> </TabLink>
<TabLink to={`/organizations/${organizationId}/cookie-banners/${cookieBannerId}/detection`}> <TabLink to={`/organizations/${organizationId}/cookie-banners/${cookieBannerId}/trackers`}>
<MagnifyingGlassIcon size={20} /> <MagnifyingGlassIcon size={20} />
{__("Detection")} {__("Trackers")}
</TabLink>
<TabLink to={`/organizations/${organizationId}/cookie-banners/${cookieBannerId}/resources`}>
<CodeIcon size={20} />
{__("Resources")}
</TabLink> </TabLink>
<TabLink to={`/organizations/${organizationId}/cookie-banners/${cookieBannerId}/consent-records`}> <TabLink to={`/organizations/${organizationId}/cookie-banners/${cookieBannerId}/consent-records`}>
<ClipboardTextIcon size={20} /> <ClipboardTextIcon size={20} />

View File

@@ -31,31 +31,31 @@ import {
usePreloadedQuery, usePreloadedQuery,
} from "react-relay"; } from "react-relay";
import type { CookieBannerDetectionPageFragment$key } from "#/__generated__/core/CookieBannerDetectionPageFragment.graphql"; import type { CookieBannerTrackersPageFragment$key } from "#/__generated__/core/CookieBannerTrackersPageFragment.graphql";
import type { CookieBannerDetectionPageQuery } from "#/__generated__/core/CookieBannerDetectionPageQuery.graphql"; import type { CookieBannerTrackersPageQuery } from "#/__generated__/core/CookieBannerTrackersPageQuery.graphql";
import type { import type {
CookieBannerDetectionPageRefetchQuery, CookieBannerTrackersPageRefetchQuery,
CookieSource, CookieSource,
TrackerPatternOrderField, TrackerPatternOrderField,
} from "#/__generated__/core/CookieBannerDetectionPageRefetchQuery.graphql"; } from "#/__generated__/core/CookieBannerTrackersPageRefetchQuery.graphql";
import { SortableTable, SortableTh } from "#/components/SortableTable"; import { SortableTable, SortableTh } from "#/components/SortableTable";
import { DetectionPatternRow } from "./_components/DetectionPatternRow"; import { TrackerPatternRow } from "./_components/TrackerPatternRow";
export const cookieBannerDetectionPageQuery = graphql` export const cookieBannerTrackersPageQuery = graphql`
query CookieBannerDetectionPageQuery($cookieBannerId: ID!) { query CookieBannerTrackersPageQuery($cookieBannerId: ID!) {
node(id: $cookieBannerId) @required(action: THROW) { node(id: $cookieBannerId) @required(action: THROW) {
__typename __typename
... on CookieBanner { ... on CookieBanner {
...CookieBannerDetectionPageFragment ...CookieBannerTrackersPageFragment
} }
} }
} }
`; `;
const detectionFragment = graphql` const trackersFragment = graphql`
fragment CookieBannerDetectionPageFragment on CookieBanner fragment CookieBannerTrackersPageFragment on CookieBanner
@refetchable(queryName: "CookieBannerDetectionPageRefetchQuery") @refetchable(queryName: "CookieBannerTrackersPageRefetchQuery")
@argumentDefinitions( @argumentDefinitions(
first: { type: "Int", defaultValue: 50 } first: { type: "Int", defaultValue: 50 }
order: { type: "TrackerPatternOrder", defaultValue: { field: NAME, direction: ASC } } order: { type: "TrackerPatternOrder", defaultValue: { field: NAME, direction: ASC } }
@@ -74,7 +74,7 @@ const detectionFragment = graphql`
filter: { query: $query, source: $source } filter: { query: $query, source: $source }
) )
@connection( @connection(
key: "CookieBannerDetectionPage_uncategorisedTrackerPatterns" key: "CookieBannerTrackersPage_uncategorisedTrackerPatterns"
filters: ["filter", "orderBy"] filters: ["filter", "orderBy"]
) )
@required(action: THROW) { @required(action: THROW) {
@@ -82,22 +82,22 @@ const detectionFragment = graphql`
edges { edges {
node { node {
id id
...DetectionPatternRowFragment ...TrackerPatternRowFragment
} }
} }
} }
} }
`; `;
interface CookieBannerDetectionPageProps { interface CookieBannerTrackersPageProps {
queryRef: PreloadedQuery<CookieBannerDetectionPageQuery>; queryRef: PreloadedQuery<CookieBannerTrackersPageQuery>;
} }
export default function CookieBannerDetectionPage({ export default function CookieBannerTrackersPage({
queryRef, queryRef,
}: CookieBannerDetectionPageProps) { }: CookieBannerTrackersPageProps) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const data = usePreloadedQuery(cookieBannerDetectionPageQuery, queryRef); const data = usePreloadedQuery(cookieBannerTrackersPageQuery, queryRef);
if (data.node.__typename !== "CookieBanner") { if (data.node.__typename !== "CookieBanner") {
throw new Error("invalid type for node"); throw new Error("invalid type for node");
@@ -108,9 +108,9 @@ export default function CookieBannerDetectionPage({
const [sourceFilter, setSourceFilter] = useState<CookieSource | null>(null); const [sourceFilter, setSourceFilter] = useState<CookieSource | null>(null);
const { data: fragmentData, ...pagination } = usePaginationFragment< const { data: fragmentData, ...pagination } = usePaginationFragment<
CookieBannerDetectionPageRefetchQuery, CookieBannerTrackersPageRefetchQuery,
CookieBannerDetectionPageFragment$key CookieBannerTrackersPageFragment$key
>(detectionFragment, data.node); >(trackersFragment, data.node);
const connectionId = fragmentData.uncategorisedTrackerPatterns.__id; const connectionId = fragmentData.uncategorisedTrackerPatterns.__id;
const patterns = fragmentData.uncategorisedTrackerPatterns.edges.map(edge => edge.node) ?? []; const patterns = fragmentData.uncategorisedTrackerPatterns.edges.map(edge => edge.node) ?? [];
@@ -187,7 +187,7 @@ export default function CookieBannerDetectionPage({
</Thead> </Thead>
<Tbody> <Tbody>
{patterns.map(pattern => ( {patterns.map(pattern => (
<DetectionPatternRow <TrackerPatternRow
key={pattern.id} key={pattern.id}
patternKey={pattern} patternKey={pattern}
connectionId={connectionId} connectionId={connectionId}

View File

@@ -16,19 +16,19 @@ import { Suspense, useEffect } from "react";
import { useQueryLoader } from "react-relay"; import { useQueryLoader } from "react-relay";
import { useParams } from "react-router"; import { useParams } from "react-router";
import type { CookieBannerDetectionPageQuery } from "#/__generated__/core/CookieBannerDetectionPageQuery.graphql"; import type { CookieBannerTrackersPageQuery } from "#/__generated__/core/CookieBannerTrackersPageQuery.graphql";
import CookieBannerDetectionPage, { cookieBannerDetectionPageQuery } from "./CookieBannerDetectionPage"; import CookieBannerTrackersPage, { cookieBannerTrackersPageQuery } from "./CookieBannerTrackersPage";
import { CookieBannerDetectionPageSkeleton } from "./CookieBannerDetectionPageSkeleton"; import { CookieBannerTrackersPageSkeleton } from "./CookieBannerTrackersPageSkeleton";
export default function CookieBannerDetectionPageLoader() { export default function CookieBannerTrackersPageLoader() {
const { cookieBannerId } = useParams<{ cookieBannerId: string }>(); const { cookieBannerId } = useParams<{ cookieBannerId: string }>();
if (typeof cookieBannerId !== "string") { if (typeof cookieBannerId !== "string") {
throw new Error("Missing cookieBannerId parameter"); throw new Error("Missing cookieBannerId parameter");
} }
const [queryRef, loadQuery] = useQueryLoader<CookieBannerDetectionPageQuery>( const [queryRef, loadQuery] = useQueryLoader<CookieBannerTrackersPageQuery>(
cookieBannerDetectionPageQuery, cookieBannerTrackersPageQuery,
); );
useEffect(() => { useEffect(() => {
@@ -36,12 +36,12 @@ export default function CookieBannerDetectionPageLoader() {
}, [loadQuery, cookieBannerId]); }, [loadQuery, cookieBannerId]);
if (!queryRef) { if (!queryRef) {
return <CookieBannerDetectionPageSkeleton />; return <CookieBannerTrackersPageSkeleton />;
} }
return ( return (
<Suspense fallback={<CookieBannerDetectionPageSkeleton />}> <Suspense fallback={<CookieBannerTrackersPageSkeleton />}>
<CookieBannerDetectionPage queryRef={queryRef} /> <CookieBannerTrackersPage queryRef={queryRef} />
</Suspense> </Suspense>
); );
} }

View File

@@ -12,7 +12,7 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE. // PERFORMANCE OF THIS SOFTWARE.
export function CookieBannerDetectionPageSkeleton() { export function CookieBannerTrackersPageSkeleton() {
return ( return (
<div className="space-y-4 animate-pulse"> <div className="space-y-4 animate-pulse">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">

View File

@@ -31,20 +31,20 @@ import { graphql, useFragment, useMutation, useQueryLoader } from "react-relay";
import { useParams } from "react-router"; import { useParams } from "react-router";
import { ConnectionHandler } from "relay-runtime"; import { ConnectionHandler } from "relay-runtime";
import type { DetectionPatternRowDeleteMutation } from "#/__generated__/core/DetectionPatternRowDeleteMutation.graphql"; import type { TrackerPatternRowDeleteMutation } from "#/__generated__/core/TrackerPatternRowDeleteMutation.graphql";
import type { DetectionPatternRowFragment$key } from "#/__generated__/core/DetectionPatternRowFragment.graphql"; import type { TrackerPatternRowFragment$key } from "#/__generated__/core/TrackerPatternRowFragment.graphql";
import type { DetectionPatternRowMoveMutation } from "#/__generated__/core/DetectionPatternRowMoveMutation.graphql"; import type { TrackerPatternRowMoveMutation } from "#/__generated__/core/TrackerPatternRowMoveMutation.graphql";
import type { DetectionPatternRowUpdateMutation } from "#/__generated__/core/DetectionPatternRowUpdateMutation.graphql"; import type { TrackerPatternRowUpdateMutation } from "#/__generated__/core/TrackerPatternRowUpdateMutation.graphql";
import type { MoveToCategoryDropdownQuery } from "#/__generated__/core/MoveToCategoryDropdownQuery.graphql"; import type { MoveToCategoryDropdownQuery } from "#/__generated__/core/MoveToCategoryDropdownQuery.graphql";
import { DetectionPatternRowEdit } from "./DetectionPatternRowEdit"; import { TrackerPatternRowEdit } from "./TrackerPatternRowEdit";
import { import {
MoveToCategoryDropdown, MoveToCategoryDropdown,
moveToCategoryDropdownQuery, moveToCategoryDropdownQuery,
} from "./MoveToCategoryDropdown"; } from "./MoveToCategoryDropdown";
const detectionPatternFragment = graphql` const trackerPatternFragment = graphql`
fragment DetectionPatternRowFragment on TrackerPattern { fragment TrackerPatternRowFragment on TrackerPattern {
id id
trackerType trackerType
displayName displayName
@@ -58,7 +58,7 @@ const detectionPatternFragment = graphql`
`; `;
const deletePatternMutation = graphql` const deletePatternMutation = graphql`
mutation DetectionPatternRowDeleteMutation( mutation TrackerPatternRowDeleteMutation(
$input: DeleteTrackerPatternInput! $input: DeleteTrackerPatternInput!
$connections: [ID!]! $connections: [ID!]!
) { ) {
@@ -77,7 +77,7 @@ const deletePatternMutation = graphql`
`; `;
const movePatternMutation = graphql` const movePatternMutation = graphql`
mutation DetectionPatternRowMoveMutation( mutation TrackerPatternRowMoveMutation(
$input: MoveTrackerPatternToCategoryInput! $input: MoveTrackerPatternToCategoryInput!
) { ) {
moveTrackerPatternToCategory(input: $input) { moveTrackerPatternToCategory(input: $input) {
@@ -100,7 +100,7 @@ const movePatternMutation = graphql`
`; `;
const updatePatternMutation = graphql` const updatePatternMutation = graphql`
mutation DetectionPatternRowUpdateMutation( mutation TrackerPatternRowUpdateMutation(
$input: UpdateTrackerPatternInput! $input: UpdateTrackerPatternInput!
) { ) {
updateTrackerPattern(input: $input) { updateTrackerPattern(input: $input) {
@@ -130,23 +130,21 @@ function trackerTypeLabel(type: string, __: (s: string) => string): string {
case "LOCAL_STORAGE": return __("localStorage"); case "LOCAL_STORAGE": return __("localStorage");
case "SESSION_STORAGE": return __("sessionStorage"); case "SESSION_STORAGE": return __("sessionStorage");
case "INDEXED_DB": return __("IndexedDB"); case "INDEXED_DB": return __("IndexedDB");
case "SCRIPT": return __("Script");
case "IFRAME": return __("Iframe");
default: return type; default: return type;
} }
} }
interface DetectionPatternRowProps { interface TrackerPatternRowProps {
patternKey: DetectionPatternRowFragment$key; patternKey: TrackerPatternRowFragment$key;
connectionId: string; connectionId: string;
} }
export function DetectionPatternRow({ patternKey, connectionId }: DetectionPatternRowProps) { export function TrackerPatternRow({ patternKey, connectionId }: TrackerPatternRowProps) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const { toast } = useToast(); const { toast } = useToast();
const confirm = useConfirm(); const confirm = useConfirm();
const { cookieBannerId } = useParams<{ cookieBannerId: string }>(); const { cookieBannerId } = useParams<{ cookieBannerId: string }>();
const pattern = useFragment(detectionPatternFragment, patternKey); const pattern = useFragment(trackerPatternFragment, patternKey);
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [categoryQueryRef, loadCategoryQuery] const [categoryQueryRef, loadCategoryQuery]
@@ -162,11 +160,11 @@ export function DetectionPatternRow({ patternKey, connectionId }: DetectionPatte
); );
const [deletePattern] const [deletePattern]
= useMutation<DetectionPatternRowDeleteMutation>(deletePatternMutation); = useMutation<TrackerPatternRowDeleteMutation>(deletePatternMutation);
const [movePattern] const [movePattern]
= useMutation<DetectionPatternRowMoveMutation>(movePatternMutation); = useMutation<TrackerPatternRowMoveMutation>(movePatternMutation);
const [updatePattern, isUpdating] const [updatePattern, isUpdating]
= useMutation<DetectionPatternRowUpdateMutation>(updatePatternMutation); = useMutation<TrackerPatternRowUpdateMutation>(updatePatternMutation);
const handleDelete = () => { const handleDelete = () => {
confirm( confirm(
@@ -276,7 +274,7 @@ export function DetectionPatternRow({ patternKey, connectionId }: DetectionPatte
if (isEditing) { if (isEditing) {
return ( return (
<DetectionPatternRowEdit <TrackerPatternRowEdit
pattern={pattern.displayName} pattern={pattern.displayName}
description={pattern.description} description={pattern.description}
maxAgeSeconds={pattern.maxAgeSeconds ?? null} maxAgeSeconds={pattern.maxAgeSeconds ?? null}

View File

@@ -22,7 +22,7 @@ interface FormValues {
description: string; description: string;
} }
interface DetectionPatternRowEditProps { interface TrackerPatternRowEditProps {
pattern: string; pattern: string;
description: string; description: string;
maxAgeSeconds: number | null; maxAgeSeconds: number | null;
@@ -31,14 +31,14 @@ interface DetectionPatternRowEditProps {
onCancel: () => void; onCancel: () => void;
} }
export function DetectionPatternRowEdit({ export function TrackerPatternRowEdit({
pattern, pattern,
description, description,
maxAgeSeconds, maxAgeSeconds,
isUpdating, isUpdating,
onSave, onSave,
onCancel, onCancel,
}: DetectionPatternRowEditProps) { }: TrackerPatternRowEditProps) {
const { __ } = useTranslate(); const { __ } = useTranslate();
const initial = fromMaxAgeSeconds(maxAgeSeconds); const initial = fromMaxAgeSeconds(maxAgeSeconds);

View File

@@ -65,9 +65,14 @@ export const cookieBannerRoutes = [
Component: lazy(() => import("#/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordsPageLoader")), Component: lazy(() => import("#/pages/organizations/cookie-banners/configuration/consent-records/CookieBannerConsentRecordsPageLoader")),
}, },
{ {
path: "detection", path: "trackers",
Fallback: LinkCardSkeleton, Fallback: LinkCardSkeleton,
Component: lazy(() => import("#/pages/organizations/cookie-banners/configuration/detection/CookieBannerDetectionPageLoader")), Component: lazy(() => import("#/pages/organizations/cookie-banners/configuration/trackers/CookieBannerTrackersPageLoader")),
},
{
path: "resources",
Fallback: LinkCardSkeleton,
Component: lazy(() => import("#/pages/organizations/cookie-banners/configuration/resources/CookieBannerResourcesPageLoader")),
}, },
], ],
}, },