Make tracker pattern category editable on detail page

The category property on the tracker pattern detail page was
read-only text. Wire in the existing MoveToCategorySelect and the
moveTrackerPatternToCategory mutation so a pattern can be recategorized
directly from its detail view, matching the table-row behaviour.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-18 19:55:14 +02:00
parent a2d3852fea
commit f56d3daa2c

View File

@@ -12,15 +12,19 @@
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
import { getTrackerSourceBadge, getTrackerTypeBadge, humanizeSeconds } from "@probo/helpers";
import { formatError, getTrackerSourceBadge, getTrackerTypeBadge, type GraphQLError, humanizeSeconds } from "@probo/helpers";
import { useTranslate } from "@probo/i18n";
import { Badge, Card, IconSquareBehindSquare2, PropertyRow, useToast } from "@probo/ui";
import { graphql, useFragment } from "react-relay";
import { graphql, useFragment, useMutation } from "react-relay";
import type { TrackerPatternPropertiesSection_trackerPattern$key } from "#/__generated__/core/TrackerPatternPropertiesSection_trackerPattern.graphql";
import type { TrackerPatternPropertiesSectionMoveMutation } from "#/__generated__/core/TrackerPatternPropertiesSectionMoveMutation.graphql";
import { MoveToCategorySelect } from "./MoveToCategorySelect";
const trackerPatternPropertiesSectionFragment = graphql`
fragment TrackerPatternPropertiesSection_trackerPattern on TrackerPattern {
id
pattern
matchType
trackerType
@@ -32,7 +36,9 @@ const trackerPatternPropertiesSectionFragment = graphql`
lastMatchedAt
commonTrackerPatternId
cookieCategory {
id
name
kind
}
thirdParty {
name
@@ -43,6 +49,31 @@ const trackerPatternPropertiesSectionFragment = graphql`
}
`;
const movePatternMutation = graphql`
mutation TrackerPatternPropertiesSectionMoveMutation(
$input: MoveTrackerPatternToCategoryInput!
) {
moveTrackerPatternToCategory(input: $input) {
trackerPattern {
id
cookieCategory {
id
name
kind
}
}
cookieBanner {
id
latestVersion {
id
version
state
}
}
}
}
`;
interface TrackerPatternPropertiesSectionProps {
trackerPatternKey: TrackerPatternPropertiesSection_trackerPattern$key;
}
@@ -57,6 +88,33 @@ export function TrackerPatternPropertiesSection({
trackerPatternKey,
);
const [movePattern]
= useMutation<TrackerPatternPropertiesSectionMoveMutation>(movePatternMutation);
const handleMove = (targetCategoryId: string) => {
if (targetCategoryId === pattern.cookieCategory?.id) {
return;
}
movePattern({
variables: {
input: {
trackerPatternId: pattern.id,
targetCookieCategoryId: targetCategoryId,
},
},
onCompleted(_, errors) {
if (errors?.length) {
toast({ title: __("Error"), description: errors[0].message, variant: "error" });
return;
}
toast({ title: __("Success"), description: __("Cookie moved"), variant: "success" });
},
onError(error) {
toast({ title: __("Error"), description: formatError(__("Failed to move cookie"), error as GraphQLError), variant: "error" });
},
});
};
const typeBadge = getTrackerTypeBadge(pattern.trackerType, __);
return (
@@ -78,9 +136,12 @@ export function TrackerPatternPropertiesSection({
</PropertyRow>
)}
<PropertyRow label={__("Category")}>
<span className="text-sm">
{pattern.cookieCategory?.name ?? "-"}
</span>
<MoveToCategorySelect
currentCategoryId={pattern.cookieCategory?.id}
currentCategoryName={pattern.cookieCategory?.name}
highlight={!!pattern.cookieCategory && pattern.cookieCategory.kind !== "UNCATEGORISED"}
onSelect={handleMove}
/>
</PropertyRow>
<PropertyRow label={__("Third party")}>
{pattern.thirdParty