Add GCM consent type mapping to console UI
Display Google Consent Mode mappings as badges on each category and add a checkbox selector in the edit form so users can configure which GCM signals each category controls. Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -59,6 +59,7 @@ export const categorySectionFragment = graphql`
|
|||||||
slug
|
slug
|
||||||
description
|
description
|
||||||
kind
|
kind
|
||||||
|
gcmConsentTypes
|
||||||
cookies(first: 100, orderBy: { field: CREATED_AT, direction: ASC })
|
cookies(first: 100, orderBy: { field: CREATED_AT, direction: ASC })
|
||||||
@connection(key: "CategorySection_cookies", filters: [])
|
@connection(key: "CategorySection_cookies", filters: [])
|
||||||
@required(action: THROW) {
|
@required(action: THROW) {
|
||||||
@@ -97,6 +98,7 @@ const updateCategoryMutation = graphql`
|
|||||||
slug
|
slug
|
||||||
description
|
description
|
||||||
rank
|
rank
|
||||||
|
gcmConsentTypes
|
||||||
updatedAt
|
updatedAt
|
||||||
}
|
}
|
||||||
cookieBanner {
|
cookieBanner {
|
||||||
@@ -237,7 +239,7 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
|||||||
const cookies = category.cookies.edges.map(e => e.node);
|
const cookies = category.cookies.edges.map(e => e.node);
|
||||||
const isMutating = isUpdating || isCreating || isUpdatingCookie;
|
const isMutating = isUpdating || isCreating || isUpdatingCookie;
|
||||||
|
|
||||||
const handleSaveCategory = (name: string, slug: string, description: string) => {
|
const handleSaveCategory = (name: string, slug: string, description: string, gcmConsentTypes: string[]) => {
|
||||||
updateCategory({
|
updateCategory({
|
||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
@@ -245,6 +247,7 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
|||||||
name,
|
name,
|
||||||
slug,
|
slug,
|
||||||
description,
|
description,
|
||||||
|
gcmConsentTypes,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onCompleted(_response, errors) {
|
onCompleted(_response, errors) {
|
||||||
@@ -481,6 +484,7 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
|||||||
name={category.name}
|
name={category.name}
|
||||||
slug={category.slug}
|
slug={category.slug}
|
||||||
description={category.description}
|
description={category.description}
|
||||||
|
gcmConsentTypes={[...category.gcmConsentTypes]}
|
||||||
isUpdating={isUpdating}
|
isUpdating={isUpdating}
|
||||||
onSave={handleSaveCategory}
|
onSave={handleSaveCategory}
|
||||||
onCancel={() => setIsEditingCategory(false)}
|
onCancel={() => setIsEditingCategory(false)}
|
||||||
@@ -525,6 +529,18 @@ export function CategorySection({ categoryKey, onDelete }: CategorySectionProps)
|
|||||||
"
|
"
|
||||||
</code>
|
</code>
|
||||||
</p>
|
</p>
|
||||||
|
{category.gcmConsentTypes.length > 0 && (
|
||||||
|
<div className="mt-2 flex items-center gap-1.5">
|
||||||
|
<span className="text-xs text-txt-secondary/70">
|
||||||
|
{__("Google Consent Mode:")}
|
||||||
|
</span>
|
||||||
|
{category.gcmConsentTypes.map(type => (
|
||||||
|
<Badge key={type} variant="neutral">
|
||||||
|
{type}
|
||||||
|
</Badge>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,12 +16,23 @@ import { useTranslate } from "@probo/i18n";
|
|||||||
import { Button, Input, Textarea } from "@probo/ui";
|
import { Button, Input, Textarea } from "@probo/ui";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
const GCM_CONSENT_TYPES = [
|
||||||
|
"analytics_storage",
|
||||||
|
"ad_storage",
|
||||||
|
"ad_user_data",
|
||||||
|
"ad_personalization",
|
||||||
|
"functionality_storage",
|
||||||
|
"personalization_storage",
|
||||||
|
"security_storage",
|
||||||
|
] as const;
|
||||||
|
|
||||||
interface EditCategoryFormProps {
|
interface EditCategoryFormProps {
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
gcmConsentTypes: string[];
|
||||||
isUpdating: boolean;
|
isUpdating: boolean;
|
||||||
onSave: (name: string, slug: string, description: string) => void;
|
onSave: (name: string, slug: string, description: string, gcmConsentTypes: string[]) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +40,7 @@ export function EditCategoryForm({
|
|||||||
name,
|
name,
|
||||||
slug,
|
slug,
|
||||||
description,
|
description,
|
||||||
|
gcmConsentTypes,
|
||||||
isUpdating,
|
isUpdating,
|
||||||
onSave,
|
onSave,
|
||||||
onCancel,
|
onCancel,
|
||||||
@@ -37,6 +49,15 @@ export function EditCategoryForm({
|
|||||||
const [editName, setEditName] = useState(name);
|
const [editName, setEditName] = useState(name);
|
||||||
const [editSlug, setEditSlug] = useState(slug);
|
const [editSlug, setEditSlug] = useState(slug);
|
||||||
const [editDescription, setEditDescription] = useState(description);
|
const [editDescription, setEditDescription] = useState(description);
|
||||||
|
const [editGcmTypes, setEditGcmTypes] = useState<string[]>(gcmConsentTypes);
|
||||||
|
|
||||||
|
const toggleGcmType = (type: string) => {
|
||||||
|
setEditGcmTypes(prev =>
|
||||||
|
prev.includes(type)
|
||||||
|
? prev.filter(t => t !== type)
|
||||||
|
: [...prev, type],
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
@@ -57,11 +78,35 @@ export function EditCategoryForm({
|
|||||||
placeholder={__("Category description")}
|
placeholder={__("Category description")}
|
||||||
rows={2}
|
rows={2}
|
||||||
/>
|
/>
|
||||||
|
<div>
|
||||||
|
<label className="text-sm font-medium">
|
||||||
|
{__("Google Consent Mode")}
|
||||||
|
</label>
|
||||||
|
<p className="text-xs text-muted-foreground mb-2">
|
||||||
|
{__("Select the Google Consent Mode signals this category controls.")}
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{GCM_CONSENT_TYPES.map(type => (
|
||||||
|
<label
|
||||||
|
key={type}
|
||||||
|
className="flex items-center gap-1.5 text-xs cursor-pointer"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={editGcmTypes.includes(type)}
|
||||||
|
onChange={() => toggleGcmType(type)}
|
||||||
|
className="rounded"
|
||||||
|
/>
|
||||||
|
<code className="font-mono">{type}</code>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(editSlug)) return;
|
if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(editSlug)) return;
|
||||||
onSave(editName, editSlug, editDescription);
|
onSave(editName, editSlug, editDescription, editGcmTypes);
|
||||||
}}
|
}}
|
||||||
disabled={isUpdating}
|
disabled={isUpdating}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user