155 lines
4.7 KiB
TypeScript
155 lines
4.7 KiB
TypeScript
import { GlobalConfig } from "payload";
|
||
import { requirePermission } from "@/utils/access-control/hasPermission";
|
||
|
||
export const Shims: GlobalConfig = {
|
||
slug: "shims",
|
||
access: {
|
||
read: requirePermission("shims:read"),
|
||
update: requirePermission("shims:update"),
|
||
},
|
||
fields: [
|
||
{
|
||
name: "shims",
|
||
type: "array",
|
||
fields: [
|
||
{
|
||
name: "name",
|
||
type: "text",
|
||
required: true,
|
||
unique: true,
|
||
admin: {
|
||
description: "Unique identifier for this shim. Used internally for stable hashing.",
|
||
},
|
||
},
|
||
{
|
||
name: "summary",
|
||
type: "text",
|
||
admin: {
|
||
description: "Brief description of what this shim does (for admin reference).",
|
||
},
|
||
},
|
||
{
|
||
name: "enabled",
|
||
type: "checkbox",
|
||
defaultValue: false,
|
||
admin: {
|
||
description: "Disabled shims are never injected, regardless of targeting rules.",
|
||
},
|
||
},
|
||
{
|
||
name: "type",
|
||
type: "select",
|
||
options: [
|
||
{ label: "CSS", value: "css" },
|
||
{ label: "JavaScript", value: "js" },
|
||
],
|
||
required: true,
|
||
defaultValue: "css",
|
||
},
|
||
{
|
||
name: "content",
|
||
type: "code",
|
||
required: true,
|
||
admin: {
|
||
components: {
|
||
Field: "@/components/admin/shims/ShimContentField",
|
||
},
|
||
description:
|
||
"CSS or JS code to inject. CSS is added as a <style> tag; JS is added as an inline <script>.",
|
||
},
|
||
},
|
||
{
|
||
name: "targeting",
|
||
type: "group",
|
||
label: "Targeting",
|
||
admin: {
|
||
description: "Who should this shim be applied to?",
|
||
},
|
||
fields: [
|
||
{
|
||
name: "audience",
|
||
type: "select",
|
||
required: true,
|
||
defaultValue: "all",
|
||
options: [
|
||
{ label: "All Users", value: "all" },
|
||
{ label: "Percentage of Users", value: "percentage" },
|
||
{ label: "Specific Users", value: "users" },
|
||
{ label: "By Role", value: "roles" },
|
||
],
|
||
},
|
||
{
|
||
name: "percentage",
|
||
type: "number",
|
||
min: 0,
|
||
max: 100,
|
||
defaultValue: 50,
|
||
admin: {
|
||
condition: (_data, siblingData) => siblingData?.audience === "percentage",
|
||
description:
|
||
"Percentage of users (0–100) who receive this shim. Assignment is deterministic per user.",
|
||
},
|
||
},
|
||
{
|
||
name: "users",
|
||
type: "relationship",
|
||
relationTo: "users",
|
||
hasMany: true,
|
||
admin: {
|
||
condition: (_data, siblingData) => siblingData?.audience === "users",
|
||
description: "Only these specific users will receive this shim.",
|
||
},
|
||
},
|
||
{
|
||
name: "roles",
|
||
type: "select",
|
||
hasMany: true,
|
||
options: [
|
||
{ label: "Guest", value: "guest" },
|
||
{ label: "User", value: "user" },
|
||
{ label: "Trusted", value: "trusted" },
|
||
{ label: "Admin", value: "admin" },
|
||
{ label: "Developer", value: "developer" },
|
||
],
|
||
admin: {
|
||
condition: (_data, siblingData) => siblingData?.audience === "roles",
|
||
description: "Users with any of these roles will receive this shim.",
|
||
},
|
||
},
|
||
],
|
||
},
|
||
{
|
||
name: "paths",
|
||
type: "group",
|
||
label: "Path Matching",
|
||
admin: {
|
||
description: "Which pages should this shim be active on?",
|
||
},
|
||
fields: [
|
||
{
|
||
name: "matchType",
|
||
type: "select",
|
||
required: true,
|
||
defaultValue: "all",
|
||
options: [
|
||
{ label: "All Pages", value: "all" },
|
||
{ label: "Include Only", value: "include" },
|
||
{ label: "Exclude", value: "exclude" },
|
||
],
|
||
},
|
||
{
|
||
name: "paths",
|
||
type: "text",
|
||
hasMany: true,
|
||
admin: {
|
||
condition: (_data, siblingData) => siblingData?.matchType !== "all",
|
||
description:
|
||
"URL path prefixes to match. E.g. '/logistics' matches /logistics and /logistics/market. Leading slash required.",
|
||
},
|
||
},
|
||
],
|
||
},
|
||
],
|
||
},
|
||
],
|
||
};
|