strapi-plugin-bulk-updater 1.2.12 → 1.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{BulkUpdater-CQ9zGdat.js → BulkUpdater-CWJYmuGU.js} +84 -7
- package/dist/_chunks/BulkUpdater-CWJYmuGU.js.map +1 -0
- package/dist/_chunks/{BulkUpdater-DvCSr1vU.mjs → BulkUpdater-Cfig2f7d.mjs} +84 -7
- package/dist/_chunks/BulkUpdater-Cfig2f7d.mjs.map +1 -0
- package/dist/_chunks/{SettingsPage-BRGTrW9H.js → SettingsPage-BAvuOb7V.js} +2 -2
- package/dist/_chunks/{SettingsPage-BRGTrW9H.js.map → SettingsPage-BAvuOb7V.js.map} +1 -1
- package/dist/_chunks/{SettingsPage-ieu-Out8.mjs → SettingsPage-BWo4l6Gd.mjs} +2 -2
- package/dist/_chunks/{SettingsPage-ieu-Out8.mjs.map → SettingsPage-BWo4l6Gd.mjs.map} +1 -1
- package/dist/_chunks/{ValidationRulesTab-BoqhoTjo.js → ValidationRulesTab-BLZWPGrZ.js} +3 -2
- package/dist/_chunks/{ValidationRulesTab-BoqhoTjo.js.map → ValidationRulesTab-BLZWPGrZ.js.map} +1 -1
- package/dist/_chunks/{ValidationRulesTab-BGcqM9cN.mjs → ValidationRulesTab-Dt53h-Ke.mjs} +3 -2
- package/dist/_chunks/{ValidationRulesTab-BGcqM9cN.mjs.map → ValidationRulesTab-Dt53h-Ke.mjs.map} +1 -1
- package/dist/admin/index.js +2 -2
- package/dist/admin/index.mjs +2 -2
- package/dist/server/index.js +293 -78
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +293 -78
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/_chunks/BulkUpdater-CQ9zGdat.js.map +0 -1
- package/dist/_chunks/BulkUpdater-DvCSr1vU.mjs.map +0 -1
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const designSystem = require("@strapi/design-system");
|
|
5
5
|
const icons = require("@strapi/icons");
|
|
6
|
-
const ValidationRulesTab = require("./ValidationRulesTab-
|
|
6
|
+
const ValidationRulesTab = require("./ValidationRulesTab-BLZWPGrZ.js");
|
|
7
7
|
const ALL_FEATURES = [
|
|
8
8
|
"Cross-collection batch attribute & relationship updates",
|
|
9
9
|
"Interactive schema compatibility & target selection",
|
|
@@ -40,4 +40,4 @@ const SettingsPage = () => {
|
|
|
40
40
|
] });
|
|
41
41
|
};
|
|
42
42
|
exports.default = SettingsPage;
|
|
43
|
-
//# sourceMappingURL=SettingsPage-
|
|
43
|
+
//# sourceMappingURL=SettingsPage-BAvuOb7V.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsPage-
|
|
1
|
+
{"version":3,"file":"SettingsPage-BAvuOb7V.js","sources":["../../admin/src/pages/SettingsPage.tsx"],"sourcesContent":["import React from 'react';\nimport {\n Box,\n Flex,\n Typography,\n Badge,\n} from '@strapi/design-system';\nimport { Check } from '@strapi/icons';\nimport ValidationRulesTab from './ValidationRulesTab';\n\nconst ALL_FEATURES = [\n 'Cross-collection batch attribute & relationship updates',\n 'Interactive schema compatibility & target selection',\n 'Full regex find & replace with live diff previews',\n 'Dynamic cross-component quota validation (UI-configurable)',\n 'Enterprise Maker-Checker 4-Eyes approval workflow',\n 'Server-enforced off-peak execution maintenance window',\n '3-Tier comprehensive audit logging with one-click reversible rollback',\n 'Zero-infra memory caching & pod-level ETag optimization',\n];\n\nconst SettingsPage: React.FC = () => {\n return (\n <Box padding={8} background=\"neutral100\">\n <Flex direction=\"column\" alignItems=\"flex-start\" gap={2} marginBottom={6}>\n <Flex justifyContent=\"space-between\" width=\"100%\">\n <Box>\n <Typography variant=\"alpha\" tag=\"h1\" fontWeight=\"bold\">\n Bulk Attribute Updater Settings\n </Typography>\n <Typography variant=\"omega\" textColor=\"neutral600\">\n Configure cross-component validation rules, manage quotas, and view active plugin capabilities.\n </Typography>\n </Box>\n </Flex>\n </Flex>\n\n {/* Plugin Status Card */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius marginBottom={6}>\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={4}>\n <Box>\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"semiBold\">\n Plugin Status\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n All features are fully unlocked, active, and free under the MIT open-source license.\n </Typography>\n </Box>\n <Badge backgroundColor=\"success100\" textColor=\"success700\" size=\"M\">\n COMMUNITY & ENTERPRISE UNLOCKED\n </Badge>\n </Flex>\n\n {/* Features Checklist */}\n <Box marginTop={4}>\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral700\" marginBottom={3}>\n Active Capabilities:\n </Typography>\n <Flex direction=\"column\" gap={2} alignItems=\"flex-start\" marginTop={2}>\n {ALL_FEATURES.map((feat, i) => (\n <Flex key={i} gap={2} alignItems=\"center\">\n <Check width=\"16px\" height=\"16px\" color=\"#328048\" />\n <Typography variant=\"omega\">{feat}</Typography>\n </Flex>\n ))}\n </Flex>\n </Box>\n </Box>\n\n {/* Validation Rules Section */}\n <Box marginTop={6}>\n <ValidationRulesTab />\n </Box>\n </Box>\n );\n};\n\nexport default SettingsPage;\n"],"names":["jsxs","Box","jsx","Flex","Typography","Badge","Check","ValidationRulesTab"],"mappings":";;;;;;AAUA,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,eAAyB,MAAM;AACnC,SACEA,2BAAAA,KAACC,aAAAA,KAAA,EAAI,SAAS,GAAG,YAAW,cAC1B,UAAA;AAAA,IAAAC,2BAAAA,IAACC,aAAAA,QAAK,WAAU,UAAS,YAAW,cAAa,KAAK,GAAG,cAAc,GACrE,UAAAD,2BAAAA,IAACC,qBAAK,gBAAe,iBAAgB,OAAM,QACzC,0CAACF,kBAAA,EACC,UAAA;AAAA,MAAAC,2BAAAA,IAACE,aAAAA,cAAW,SAAQ,SAAQ,KAAI,MAAK,YAAW,QAAO,UAAA,kCAAA,CAEvD;AAAA,qCACCA,aAAAA,YAAA,EAAW,SAAQ,SAAQ,WAAU,cAAa,UAAA,kGAAA,CAEnD;AAAA,IAAA,EAAA,CACF,GACF,GACF;AAAA,IAGAJ,2BAAAA,KAACC,aAAAA,KAAA,EAAI,SAAS,GAAG,YAAW,YAAW,QAAO,gBAAe,WAAS,MAAC,cAAc,GACnF,UAAA;AAAA,MAAAD,gCAACG,aAAAA,QAAK,gBAAe,iBAAgB,YAAW,UAAS,cAAc,GACrE,UAAA;AAAA,QAAAH,gCAACC,aAAAA,KAAA,EACC,UAAA;AAAA,UAAAC,2BAAAA,IAACE,aAAAA,cAAW,SAAQ,SAAQ,KAAI,MAAK,YAAW,YAAW,UAAA,gBAAA,CAE3D;AAAA,yCACCA,aAAAA,YAAA,EAAW,SAAQ,MAAK,WAAU,cAAa,UAAA,uFAAA,CAEhD;AAAA,QAAA,GACF;AAAA,QACAF,2BAAAA,IAACG,aAAAA,SAAM,iBAAgB,cAAa,WAAU,cAAa,MAAK,KAAI,UAAA,kCAAA,CAEpE;AAAA,MAAA,GACF;AAAA,MAGAL,2BAAAA,KAACC,aAAAA,KAAA,EAAI,WAAW,GACd,UAAA;AAAA,QAAAC,2BAAAA,IAACE,aAAAA,YAAA,EAAW,SAAQ,MAAK,YAAW,QAAO,WAAU,cAAa,cAAc,GAAG,UAAA,uBAAA,CAEnF;AAAA,QACAF,2BAAAA,IAACC,aAAAA,QAAK,WAAU,UAAS,KAAK,GAAG,YAAW,cAAa,WAAW,GACjE,uBAAa,IAAI,CAAC,MAAM,MACvBH,gCAACG,aAAAA,QAAa,KAAK,GAAG,YAAW,UAC/B,UAAA;AAAA,UAAAD,+BAACI,MAAAA,SAAM,OAAM,QAAO,QAAO,QAAO,OAAM,WAAU;AAAA,UAClDJ,2BAAAA,IAACE,aAAAA,YAAA,EAAW,SAAQ,SAAS,UAAA,KAAA,CAAK;AAAA,QAAA,EAAA,GAFzB,CAGX,CACD,EAAA,CACH;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,GACF;AAAA,mCAGCH,aAAAA,KAAA,EAAI,WAAW,GACd,UAAAC,2BAAAA,IAACK,yCAAmB,EAAA,CACtB;AAAA,EAAA,GACF;AAEJ;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Flex, Typography, Badge } from "@strapi/design-system";
|
|
3
3
|
import { Check } from "@strapi/icons";
|
|
4
|
-
import { V as ValidationRulesTab } from "./ValidationRulesTab-
|
|
4
|
+
import { V as ValidationRulesTab } from "./ValidationRulesTab-Dt53h-Ke.mjs";
|
|
5
5
|
const ALL_FEATURES = [
|
|
6
6
|
"Cross-collection batch attribute & relationship updates",
|
|
7
7
|
"Interactive schema compatibility & target selection",
|
|
@@ -40,4 +40,4 @@ const SettingsPage = () => {
|
|
|
40
40
|
export {
|
|
41
41
|
SettingsPage as default
|
|
42
42
|
};
|
|
43
|
-
//# sourceMappingURL=SettingsPage-
|
|
43
|
+
//# sourceMappingURL=SettingsPage-BWo4l6Gd.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsPage-
|
|
1
|
+
{"version":3,"file":"SettingsPage-BWo4l6Gd.mjs","sources":["../../admin/src/pages/SettingsPage.tsx"],"sourcesContent":["import React from 'react';\nimport {\n Box,\n Flex,\n Typography,\n Badge,\n} from '@strapi/design-system';\nimport { Check } from '@strapi/icons';\nimport ValidationRulesTab from './ValidationRulesTab';\n\nconst ALL_FEATURES = [\n 'Cross-collection batch attribute & relationship updates',\n 'Interactive schema compatibility & target selection',\n 'Full regex find & replace with live diff previews',\n 'Dynamic cross-component quota validation (UI-configurable)',\n 'Enterprise Maker-Checker 4-Eyes approval workflow',\n 'Server-enforced off-peak execution maintenance window',\n '3-Tier comprehensive audit logging with one-click reversible rollback',\n 'Zero-infra memory caching & pod-level ETag optimization',\n];\n\nconst SettingsPage: React.FC = () => {\n return (\n <Box padding={8} background=\"neutral100\">\n <Flex direction=\"column\" alignItems=\"flex-start\" gap={2} marginBottom={6}>\n <Flex justifyContent=\"space-between\" width=\"100%\">\n <Box>\n <Typography variant=\"alpha\" tag=\"h1\" fontWeight=\"bold\">\n Bulk Attribute Updater Settings\n </Typography>\n <Typography variant=\"omega\" textColor=\"neutral600\">\n Configure cross-component validation rules, manage quotas, and view active plugin capabilities.\n </Typography>\n </Box>\n </Flex>\n </Flex>\n\n {/* Plugin Status Card */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius marginBottom={6}>\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={4}>\n <Box>\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"semiBold\">\n Plugin Status\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n All features are fully unlocked, active, and free under the MIT open-source license.\n </Typography>\n </Box>\n <Badge backgroundColor=\"success100\" textColor=\"success700\" size=\"M\">\n COMMUNITY & ENTERPRISE UNLOCKED\n </Badge>\n </Flex>\n\n {/* Features Checklist */}\n <Box marginTop={4}>\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral700\" marginBottom={3}>\n Active Capabilities:\n </Typography>\n <Flex direction=\"column\" gap={2} alignItems=\"flex-start\" marginTop={2}>\n {ALL_FEATURES.map((feat, i) => (\n <Flex key={i} gap={2} alignItems=\"center\">\n <Check width=\"16px\" height=\"16px\" color=\"#328048\" />\n <Typography variant=\"omega\">{feat}</Typography>\n </Flex>\n ))}\n </Flex>\n </Box>\n </Box>\n\n {/* Validation Rules Section */}\n <Box marginTop={6}>\n <ValidationRulesTab />\n </Box>\n </Box>\n );\n};\n\nexport default SettingsPage;\n"],"names":[],"mappings":";;;;AAUA,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,eAAyB,MAAM;AACnC,SACE,qBAAC,KAAA,EAAI,SAAS,GAAG,YAAW,cAC1B,UAAA;AAAA,IAAA,oBAAC,QAAK,WAAU,UAAS,YAAW,cAAa,KAAK,GAAG,cAAc,GACrE,UAAA,oBAAC,QAAK,gBAAe,iBAAgB,OAAM,QACzC,+BAAC,KAAA,EACC,UAAA;AAAA,MAAA,oBAAC,cAAW,SAAQ,SAAQ,KAAI,MAAK,YAAW,QAAO,UAAA,kCAAA,CAEvD;AAAA,0BACC,YAAA,EAAW,SAAQ,SAAQ,WAAU,cAAa,UAAA,kGAAA,CAEnD;AAAA,IAAA,EAAA,CACF,GACF,GACF;AAAA,IAGA,qBAAC,KAAA,EAAI,SAAS,GAAG,YAAW,YAAW,QAAO,gBAAe,WAAS,MAAC,cAAc,GACnF,UAAA;AAAA,MAAA,qBAAC,QAAK,gBAAe,iBAAgB,YAAW,UAAS,cAAc,GACrE,UAAA;AAAA,QAAA,qBAAC,KAAA,EACC,UAAA;AAAA,UAAA,oBAAC,cAAW,SAAQ,SAAQ,KAAI,MAAK,YAAW,YAAW,UAAA,gBAAA,CAE3D;AAAA,8BACC,YAAA,EAAW,SAAQ,MAAK,WAAU,cAAa,UAAA,uFAAA,CAEhD;AAAA,QAAA,GACF;AAAA,QACA,oBAAC,SAAM,iBAAgB,cAAa,WAAU,cAAa,MAAK,KAAI,UAAA,kCAAA,CAEpE;AAAA,MAAA,GACF;AAAA,MAGA,qBAAC,KAAA,EAAI,WAAW,GACd,UAAA;AAAA,QAAA,oBAAC,YAAA,EAAW,SAAQ,MAAK,YAAW,QAAO,WAAU,cAAa,cAAc,GAAG,UAAA,uBAAA,CAEnF;AAAA,QACA,oBAAC,QAAK,WAAU,UAAS,KAAK,GAAG,YAAW,cAAa,WAAW,GACjE,uBAAa,IAAI,CAAC,MAAM,MACvB,qBAAC,QAAa,KAAK,GAAG,YAAW,UAC/B,UAAA;AAAA,UAAA,oBAAC,SAAM,OAAM,QAAO,QAAO,QAAO,OAAM,WAAU;AAAA,UAClD,oBAAC,YAAA,EAAW,SAAQ,SAAS,UAAA,KAAA,CAAK;AAAA,QAAA,EAAA,GAFzB,CAGX,CACD,EAAA,CACH;AAAA,MAAA,EAAA,CACF;AAAA,IAAA,GACF;AAAA,wBAGC,KAAA,EAAI,WAAW,GACd,UAAA,oBAAC,sBAAmB,EAAA,CACtB;AAAA,EAAA,GACF;AAEJ;"}
|
|
@@ -561,7 +561,8 @@ function ValidationRulesTab() {
|
|
|
561
561
|
});
|
|
562
562
|
return;
|
|
563
563
|
}
|
|
564
|
-
const
|
|
564
|
+
const safeContent = csvStr.startsWith("\uFEFF") ? csvStr : "\uFEFF" + csvStr;
|
|
565
|
+
const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
|
|
565
566
|
const url = URL.createObjectURL(blob);
|
|
566
567
|
const link = document.createElement("a");
|
|
567
568
|
link.href = url;
|
|
@@ -594,4 +595,4 @@ function ValidationRulesTab() {
|
|
|
594
595
|
] });
|
|
595
596
|
}
|
|
596
597
|
exports.ValidationRulesTab = ValidationRulesTab;
|
|
597
|
-
//# sourceMappingURL=ValidationRulesTab-
|
|
598
|
+
//# sourceMappingURL=ValidationRulesTab-BLZWPGrZ.js.map
|
package/dist/_chunks/{ValidationRulesTab-BoqhoTjo.js.map → ValidationRulesTab-BLZWPGrZ.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationRulesTab-BoqhoTjo.js","sources":["../../admin/src/pages/ValidationRulesTab.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { useFetchClient, useNotification } from '@strapi/strapi/admin';\nimport {\n Box,\n Flex,\n Typography,\n Button,\n TextInput,\n Textarea,\n SingleSelect,\n SingleSelectOption,\n Badge,\n Table,\n Thead,\n Tbody,\n Tr,\n Th,\n Td,\n Alert,\n} from '@strapi/design-system';\nimport { Plus, Trash, Check, ArrowClockwise, Search, Download } from '@strapi/icons';\n\nexport interface ValidationRule {\n id: string;\n name: string;\n description?: string;\n targetField: string;\n quotas: Record<string, number>;\n exceededAction: 'disable' | 'hide';\n enabled: boolean;\n scope: 'entry' | 'document';\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport default function ValidationRulesTab() {\n const { get, post, del } = useFetchClient();\n const { toggleNotification } = useNotification();\n\n const [rules, setRules] = useState<ValidationRule[]>([]);\n const [loading, setLoading] = useState<boolean>(true);\n const [modalOpen, setModalOpen] = useState<boolean>(false);\n const [editingRule, setEditingRule] = useState<ValidationRule | null>(null);\n\n // Form state for creating/editing a rule\n const [formName, setFormName] = useState<string>('');\n const [formDesc, setFormDesc] = useState<string>('');\n const [formField, setFormField] = useState<string>('');\n const [formAction, setFormAction] = useState<'disable' | 'hide'>('disable');\n const [formQuotas, setFormQuotas] = useState<Array<{ key: string; maxAllowed: number }>>([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n const [saving, setSaving] = useState<boolean>(false);\n\n // Scan modal state\n const [scanModalOpen, setScanModalOpen] = useState<boolean>(false);\n const [scanningRuleId, setScanningRuleId] = useState<string | null>(null);\n const [scanReport, setScanReport] = useState<any>(null);\n\n const handleScanRule = async (rule: ValidationRule) => {\n try {\n setScanningRuleId(rule.id);\n const res = await get(`/bulk-updater/validation-rules/${rule.id}/scan`);\n if (res.data && res.data.success) {\n setScanReport(res.data);\n setScanModalOpen(true);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Scan failed: ${err.message}`,\n });\n } finally {\n setScanningRuleId(null);\n }\n };\n\n const fetchRules = async () => {\n try {\n setLoading(true);\n const res = await get('/bulk-updater/validation-rules');\n if (res.data && res.data.success) {\n setRules(res.data.rules || []);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to load rules: ${err.message}`,\n });\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n fetchRules();\n }, []);\n\n const openCreateModal = () => {\n setEditingRule(null);\n setFormName('');\n setFormDesc('');\n setFormField('headingLevel');\n setFormAction('disable');\n setFormQuotas([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n setModalOpen(true);\n };\n\n const openEditModal = (rule: ValidationRule) => {\n setEditingRule(rule);\n setFormName(rule.name);\n setFormDesc(rule.description || '');\n setFormField(rule.targetField);\n setFormAction(rule.exceededAction || 'disable');\n const quotaPairs = Object.entries(rule.quotas || {}).map(([k, v]) => ({\n key: k,\n maxAllowed: v,\n }));\n setFormQuotas(quotaPairs.length > 0 ? quotaPairs : [{ key: 'h1', maxAllowed: 1 }]);\n setModalOpen(true);\n };\n\n const handleAddQuotaRow = () => {\n setFormQuotas((prev) => [...prev, { key: '', maxAllowed: 1 }]);\n };\n\n const handleRemoveQuotaRow = (idx: number) => {\n setFormQuotas((prev) => prev.filter((_, i) => i !== idx));\n };\n\n const handleQuotaChange = (idx: number, field: 'key' | 'maxAllowed', value: any) => {\n setFormQuotas((prev) =>\n prev.map((row, i) => {\n if (i === idx) {\n return {\n ...row,\n [field]: field === 'maxAllowed' ? Math.max(1, parseInt(value, 10) || 1) : String(value).trim(),\n };\n }\n return row;\n })\n );\n };\n\n const handleSave = async () => {\n if (!formName.trim() || !formField.trim()) {\n toggleNotification({\n type: 'warning',\n message: 'Rule Name and Target Field are required.',\n });\n return;\n }\n\n const quotasRecord: Record<string, number> = {};\n for (const q of formQuotas) {\n if (q.key.trim()) {\n quotasRecord[q.key.trim().toLowerCase()] = q.maxAllowed;\n }\n }\n\n if (Object.keys(quotasRecord).length === 0) {\n toggleNotification({\n type: 'warning',\n message: 'At least one quota option with a limit is required.',\n });\n return;\n }\n\n try {\n setSaving(true);\n const payload: Partial<ValidationRule> = {\n id: editingRule ? editingRule.id : undefined,\n name: formName.trim(),\n description: formDesc.trim(),\n targetField: formField.trim(),\n quotas: quotasRecord,\n exceededAction: formAction,\n enabled: editingRule ? editingRule.enabled : true,\n scope: 'entry',\n };\n\n const res = await post('/bulk-updater/validation-rules', { rule: payload });\n if (res.data && res.data.success) {\n toggleNotification({\n type: 'success',\n message: `Rule \"${payload.name}\" saved successfully!`,\n });\n setModalOpen(false);\n fetchRules();\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to save rule: ${err.message}`,\n });\n } finally {\n setSaving(false);\n }\n };\n\n const handleToggle = async (rule: ValidationRule) => {\n try {\n const res = await post(`/bulk-updater/validation-rules/${rule.id}/toggle`, {\n enabled: !rule.enabled,\n });\n if (res.data && res.data.success) {\n setRules((prev) =>\n prev.map((r) => (r.id === rule.id ? { ...r, enabled: !rule.enabled } : r))\n );\n toggleNotification({\n type: 'info',\n message: `Rule \"${rule.name}\" is now ${!rule.enabled ? 'ACTIVE' : 'DISABLED'}.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to update rule status: ${err.message}`,\n });\n }\n };\n\n const handleDelete = async (ruleId: string, ruleName: string) => {\n if (!window.confirm(`Are you sure you want to delete the rule \"${ruleName}\"?`)) return;\n\n try {\n const res = await del(`/bulk-updater/validation-rules/${ruleId}`);\n if (res.data && res.data.success) {\n setRules((prev) => prev.filter((r) => r.id !== ruleId));\n toggleNotification({\n type: 'success',\n message: `Rule \"${ruleName}\" deleted.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to delete rule: ${err.message}`,\n });\n }\n };\n\n return (\n <Box>\n {/* Header Panel */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius marginBottom={6}>\n <Flex justifyContent=\"space-between\" alignItems=\"center\" wrap=\"wrap\" gap={3}>\n <Box>\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\">\n Cross-Component Validation & Quota Rules\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ marginTop: 4 }}>\n Define and enforce limits across Dynamic Zone components without writing code. Changes take effect immediately in both Admin edit view and Document Service APIs.\n </Typography>\n </Box>\n <Flex gap={2}>\n <Button\n variant=\"tertiary\"\n startIcon={<ArrowClockwise />}\n onClick={fetchRules}\n loading={loading}\n >\n Refresh\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Plus />}\n onClick={openCreateModal}\n >\n Create New Rule\n </Button>\n </Flex>\n </Flex>\n </Box>\n\n {/* Rules Table */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius>\n <Typography variant=\"sigma\" textColor=\"neutral600\" marginBottom={3} style={{ display: 'block' }}>\n CONFIGURED RULES ({rules.length})\n </Typography>\n\n {loading ? (\n <Typography variant=\"omega\" textColor=\"neutral500\">Loading validation rules...</Typography>\n ) : rules.length === 0 ? (\n <Alert variant=\"info\" title=\"No Rules Defined\">\n Click \"Create New Rule\" above to add your first cross-component quota rule.\n </Alert>\n ) : (\n <Table colCount={6} rowCount={rules.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">RULE NAME & TARGET FIELD</Typography></Th>\n <Th><Typography variant=\"sigma\">DESCRIPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">QUOTA CONSTRAINTS</Typography></Th>\n <Th><Typography variant=\"sigma\">EXCEEDED ACTION</Typography></Th>\n <Th><Typography variant=\"sigma\">STATUS</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTIONS</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {rules.map((rule) => {\n const quotaKeys = Object.entries(rule.quotas || {});\n return (\n <Tr key={rule.id}>\n <Td style={{ minWidth: 200 }}>\n <Typography variant=\"omega\" fontWeight=\"bold\" textColor=\"neutral800\" display=\"block\">\n {rule.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n Target Field: <code>{rule.targetField}</code>\n </Typography>\n </Td>\n <Td style={{ maxWidth: 300 }}>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {rule.description || '—'}\n </Typography>\n </Td>\n <Td style={{ minWidth: 220 }}>\n <Flex gap={1} wrap=\"wrap\">\n {quotaKeys.map(([optVal, maxVal]) => (\n <Badge key={optVal} backgroundColor=\"neutral100\" textColor=\"primary700\">\n <strong>{optVal.toUpperCase()}</strong>: max {maxVal}\n </Badge>\n ))}\n </Flex>\n </Td>\n <Td style={{ minWidth: 120 }}>\n <Badge\n backgroundColor={rule.exceededAction === 'hide' ? 'secondary100' : 'warning100'}\n textColor={rule.exceededAction === 'hide' ? 'secondary700' : 'warning700'}\n >\n {rule.exceededAction.toUpperCase()}\n </Badge>\n </Td>\n <Td style={{ minWidth: 100 }}>\n <Button\n variant={rule.enabled ? 'success-light' : 'tertiary'}\n size=\"S\"\n onClick={() => handleToggle(rule)}\n >\n {rule.enabled ? '● ACTIVE' : '○ DISABLED'}\n </Button>\n </Td>\n <Td style={{ textAlign: 'right', minWidth: 260 }}>\n <Flex gap={2} justifyContent=\"flex-end\">\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Search />}\n onClick={() => handleScanRule(rule)}\n loading={scanningRuleId === rule.id}\n >\n Scan Violations\n </Button>\n <Button\n variant=\"tertiary\"\n size=\"S\"\n onClick={() => openEditModal(rule)}\n >\n Edit\n </Button>\n <Button\n variant=\"danger-light\"\n size=\"S\"\n startIcon={<Trash />}\n onClick={() => handleDelete(rule.id, rule.name)}\n >\n Delete\n </Button>\n </Flex>\n </Td>\n </Tr>\n );\n })}\n </Tbody>\n </Table>\n )}\n </Box>\n\n {/* Create / Edit Rule Modal */}\n {modalOpen && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 620, maxHeight: '90vh', overflowY: 'auto' }}\n >\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\" marginBottom={1}>\n {editingRule ? 'Edit Validation Rule' : 'Create New Validation Rule'}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" marginBottom={4} style={{ display: 'block' }}>\n Configure cross-component limits. The rule will automatically apply to any Dynamic Zone or Component using this attribute.\n </Typography>\n\n <Flex direction=\"column\" gap={4} alignItems=\"stretch\">\n <TextInput\n label=\"Rule Name\"\n placeholder=\"e.g. SEO Single H1 Rule\"\n value={formName}\n onChange={(e: any) => setFormName(e.target.value)}\n required\n />\n\n <TextInput\n label=\"Target Field Name\"\n placeholder=\"e.g. headingLevel, titleStyle, or color\"\n value={formField}\n onChange={(e: any) => setFormField(e.target.value)}\n hint=\"Attribute name on the component/customField to monitor across the entry.\"\n required\n />\n\n <Textarea\n label=\"Rule Description\"\n placeholder=\"Briefly explain what this constraint accomplishes...\"\n value={formDesc}\n onChange={(e: any) => setFormDesc(e.target.value)}\n />\n\n <SingleSelect\n label=\"When Quota Is Exceeded in Another Component\"\n value={formAction}\n onChange={(val: any) => setFormAction(val as 'disable' | 'hide')}\n >\n <SingleSelectOption value=\"disable\">\n Disable Option with Usage Badge [(1/1 used)]\n </SingleSelectOption>\n <SingleSelectOption value=\"hide\">\n Hide Option completely from dropdown menu\n </SingleSelectOption>\n </SingleSelect>\n\n {/* Quotas Editor */}\n <Box\n padding={4}\n background=\"neutral100\"\n hasRadius\n style={{ border: '1px solid #e0e0e0' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={3}>\n <Box>\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral800\">\n Option Quotas (Max Allowed per Entry)\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ display: 'block' }}>\n Options left unlisted will have unlimited usage.\n </Typography>\n </Box>\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={handleAddQuotaRow}\n >\n Add Option\n </Button>\n </Flex>\n\n <Flex direction=\"column\" gap={2}>\n {formQuotas.map((q, idx) => (\n <Flex key={idx} gap={2} alignItems=\"center\">\n <Box style={{ flex: 2 }}>\n <TextInput\n placeholder=\"Option key (e.g. h1)\"\n value={q.key}\n onChange={(e: any) => handleQuotaChange(idx, 'key', e.target.value)}\n />\n </Box>\n <Box style={{ flex: 1 }}>\n <TextInput\n type=\"number\"\n placeholder=\"Max\"\n value={String(q.maxAllowed)}\n onChange={(e: any) => handleQuotaChange(idx, 'maxAllowed', e.target.value)}\n />\n </Box>\n <Button\n variant=\"ghost\"\n size=\"S\"\n onClick={() => handleRemoveQuotaRow(idx)}\n disabled={formQuotas.length <= 1}\n >\n ✕\n </Button>\n </Flex>\n ))}\n </Flex>\n </Box>\n </Flex>\n\n {/* Modal Actions */}\n <Flex justifyContent=\"flex-end\" gap={2} marginTop={6}>\n <Button\n variant=\"tertiary\"\n onClick={() => setModalOpen(false)}\n disabled={saving}\n >\n Cancel\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Check />}\n onClick={handleSave}\n loading={saving}\n >\n Save Rule\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n\n {/* Scan Results Modal */}\n {scanModalOpen && scanReport && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 780, maxHeight: '85vh', overflowY: 'auto' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={4}>\n <Box>\n <Typography variant=\"beta\" tag=\"h2\" fontWeight=\"bold\">\n Rule Violation Audit: {scanReport.rule?.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n Target Field: <code>{scanReport.rule?.targetField}</code> • Total Entries Scanned: {scanReport.totalScanned}\n </Typography>\n </Box>\n <Badge\n backgroundColor={scanReport.totalViolations > 0 ? 'danger100' : 'success100'}\n textColor={scanReport.totalViolations > 0 ? 'danger700' : 'success700'}\n size=\"M\"\n >\n {scanReport.totalViolations > 0\n ? `${scanReport.totalViolations} VIOLATION(S) FOUND`\n : '100% COMPLIANT'}\n </Badge>\n </Flex>\n\n {scanReport.totalViolations === 0 ? (\n <Alert variant=\"success\" title=\"No Pre-Existing Violations Detected\" marginBottom={4}>\n All existing documents across your collections adhere strictly to the configured quota limits.\n </Alert>\n ) : (\n <Box>\n <Alert variant=\"danger\" title=\"Legacy Records Found Exceeding Quota\" marginBottom={4}>\n The following {scanReport.totalViolations} record(s) contain more instances of restricted options than currently permitted by this rule.\n </Alert>\n\n <Table colCount={4} rowCount={scanReport.violations.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">CONTENT TYPE & ENTRY</Typography></Th>\n <Th><Typography variant=\"sigma\">RESTRICTED OPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">COUNT VS LIMIT</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTION</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {scanReport.violations.map((v: any, idx: number) => (\n <Tr key={idx}>\n <Td>\n <Typography variant=\"omega\" fontWeight=\"bold\">\n {v.entryLabel}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\" display=\"block\">\n Collection: {v.collectionDisplayName}\n </Typography>\n </Td>\n <Td>\n <Badge backgroundColor=\"warning100\" textColor=\"warning700\">\n {v.violatingOption}\n </Badge>\n </Td>\n <Td>\n <Typography variant=\"omega\" textColor=\"danger600\" fontWeight=\"bold\">\n {v.foundCount} used\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {' '}(Allowed max: {v.maxAllowed})\n </Typography>\n </Td>\n <Td style={{ textAlign: 'right' }}>\n <Button\n variant=\"secondary\"\n size=\"S\"\n onClick={() => window.open(v.editUrl, '_blank')}\n >\n Open in Editor ↗\n </Button>\n </Td>\n </Tr>\n ))}\n </Tbody>\n </Table>\n </Box>\n )}\n\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginTop={6}>\n {scanReport.totalViolations > 0 ? (\n <Button\n variant=\"secondary\"\n startIcon={<Download />}\n onClick={async () => {\n try {\n const res = await get(`/bulk-updater/csv/export-violations/${scanReport.rule.id}`);\n const csvStr = res.data?.csvContent || (typeof res.data === 'string' ? res.data : '');\n if (!csvStr) {\n toggleNotification({\n type: 'warning',\n message: 'No violation data to export',\n });\n return;\n }\n const blob = new Blob([csvStr], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `violations_${scanReport.rule.id}.csv`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n toggleNotification({\n type: 'success',\n message: 'Violations exported to CSV successfully',\n });\n } catch (e: any) {\n toggleNotification({\n type: 'danger',\n message: e.message || 'Failed exporting violations CSV',\n });\n }\n }}\n >\n Export Violations CSV\n </Button>\n ) : (\n <Box />\n )}\n <Button variant=\"default\" onClick={() => setScanModalOpen(false)}>\n Close Report\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n"],"names":["useFetchClient","useNotification","useState","useEffect","Box","jsx","jsxs","Flex","Typography","Button","ArrowClockwise","Plus","Alert","Table","Thead","Tr","Th","Tbody","Td","Badge","Search","Trash","TextInput","Textarea","SingleSelect","SingleSelectOption","Check","Download"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ValidationRulesTab-BLZWPGrZ.js","sources":["../../admin/src/pages/ValidationRulesTab.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { useFetchClient, useNotification } from '@strapi/strapi/admin';\nimport {\n Box,\n Flex,\n Typography,\n Button,\n TextInput,\n Textarea,\n SingleSelect,\n SingleSelectOption,\n Badge,\n Table,\n Thead,\n Tbody,\n Tr,\n Th,\n Td,\n Alert,\n} from '@strapi/design-system';\nimport { Plus, Trash, Check, ArrowClockwise, Search, Download } from '@strapi/icons';\n\nexport interface ValidationRule {\n id: string;\n name: string;\n description?: string;\n targetField: string;\n quotas: Record<string, number>;\n exceededAction: 'disable' | 'hide';\n enabled: boolean;\n scope: 'entry' | 'document';\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport default function ValidationRulesTab() {\n const { get, post, del } = useFetchClient();\n const { toggleNotification } = useNotification();\n\n const [rules, setRules] = useState<ValidationRule[]>([]);\n const [loading, setLoading] = useState<boolean>(true);\n const [modalOpen, setModalOpen] = useState<boolean>(false);\n const [editingRule, setEditingRule] = useState<ValidationRule | null>(null);\n\n // Form state for creating/editing a rule\n const [formName, setFormName] = useState<string>('');\n const [formDesc, setFormDesc] = useState<string>('');\n const [formField, setFormField] = useState<string>('');\n const [formAction, setFormAction] = useState<'disable' | 'hide'>('disable');\n const [formQuotas, setFormQuotas] = useState<Array<{ key: string; maxAllowed: number }>>([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n const [saving, setSaving] = useState<boolean>(false);\n\n // Scan modal state\n const [scanModalOpen, setScanModalOpen] = useState<boolean>(false);\n const [scanningRuleId, setScanningRuleId] = useState<string | null>(null);\n const [scanReport, setScanReport] = useState<any>(null);\n\n const handleScanRule = async (rule: ValidationRule) => {\n try {\n setScanningRuleId(rule.id);\n const res = await get(`/bulk-updater/validation-rules/${rule.id}/scan`);\n if (res.data && res.data.success) {\n setScanReport(res.data);\n setScanModalOpen(true);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Scan failed: ${err.message}`,\n });\n } finally {\n setScanningRuleId(null);\n }\n };\n\n const fetchRules = async () => {\n try {\n setLoading(true);\n const res = await get('/bulk-updater/validation-rules');\n if (res.data && res.data.success) {\n setRules(res.data.rules || []);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to load rules: ${err.message}`,\n });\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n fetchRules();\n }, []);\n\n const openCreateModal = () => {\n setEditingRule(null);\n setFormName('');\n setFormDesc('');\n setFormField('headingLevel');\n setFormAction('disable');\n setFormQuotas([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n setModalOpen(true);\n };\n\n const openEditModal = (rule: ValidationRule) => {\n setEditingRule(rule);\n setFormName(rule.name);\n setFormDesc(rule.description || '');\n setFormField(rule.targetField);\n setFormAction(rule.exceededAction || 'disable');\n const quotaPairs = Object.entries(rule.quotas || {}).map(([k, v]) => ({\n key: k,\n maxAllowed: v,\n }));\n setFormQuotas(quotaPairs.length > 0 ? quotaPairs : [{ key: 'h1', maxAllowed: 1 }]);\n setModalOpen(true);\n };\n\n const handleAddQuotaRow = () => {\n setFormQuotas((prev) => [...prev, { key: '', maxAllowed: 1 }]);\n };\n\n const handleRemoveQuotaRow = (idx: number) => {\n setFormQuotas((prev) => prev.filter((_, i) => i !== idx));\n };\n\n const handleQuotaChange = (idx: number, field: 'key' | 'maxAllowed', value: any) => {\n setFormQuotas((prev) =>\n prev.map((row, i) => {\n if (i === idx) {\n return {\n ...row,\n [field]: field === 'maxAllowed' ? Math.max(1, parseInt(value, 10) || 1) : String(value).trim(),\n };\n }\n return row;\n })\n );\n };\n\n const handleSave = async () => {\n if (!formName.trim() || !formField.trim()) {\n toggleNotification({\n type: 'warning',\n message: 'Rule Name and Target Field are required.',\n });\n return;\n }\n\n const quotasRecord: Record<string, number> = {};\n for (const q of formQuotas) {\n if (q.key.trim()) {\n quotasRecord[q.key.trim().toLowerCase()] = q.maxAllowed;\n }\n }\n\n if (Object.keys(quotasRecord).length === 0) {\n toggleNotification({\n type: 'warning',\n message: 'At least one quota option with a limit is required.',\n });\n return;\n }\n\n try {\n setSaving(true);\n const payload: Partial<ValidationRule> = {\n id: editingRule ? editingRule.id : undefined,\n name: formName.trim(),\n description: formDesc.trim(),\n targetField: formField.trim(),\n quotas: quotasRecord,\n exceededAction: formAction,\n enabled: editingRule ? editingRule.enabled : true,\n scope: 'entry',\n };\n\n const res = await post('/bulk-updater/validation-rules', { rule: payload });\n if (res.data && res.data.success) {\n toggleNotification({\n type: 'success',\n message: `Rule \"${payload.name}\" saved successfully!`,\n });\n setModalOpen(false);\n fetchRules();\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to save rule: ${err.message}`,\n });\n } finally {\n setSaving(false);\n }\n };\n\n const handleToggle = async (rule: ValidationRule) => {\n try {\n const res = await post(`/bulk-updater/validation-rules/${rule.id}/toggle`, {\n enabled: !rule.enabled,\n });\n if (res.data && res.data.success) {\n setRules((prev) =>\n prev.map((r) => (r.id === rule.id ? { ...r, enabled: !rule.enabled } : r))\n );\n toggleNotification({\n type: 'info',\n message: `Rule \"${rule.name}\" is now ${!rule.enabled ? 'ACTIVE' : 'DISABLED'}.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to update rule status: ${err.message}`,\n });\n }\n };\n\n const handleDelete = async (ruleId: string, ruleName: string) => {\n if (!window.confirm(`Are you sure you want to delete the rule \"${ruleName}\"?`)) return;\n\n try {\n const res = await del(`/bulk-updater/validation-rules/${ruleId}`);\n if (res.data && res.data.success) {\n setRules((prev) => prev.filter((r) => r.id !== ruleId));\n toggleNotification({\n type: 'success',\n message: `Rule \"${ruleName}\" deleted.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to delete rule: ${err.message}`,\n });\n }\n };\n\n return (\n <Box>\n {/* Header Panel */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius marginBottom={6}>\n <Flex justifyContent=\"space-between\" alignItems=\"center\" wrap=\"wrap\" gap={3}>\n <Box>\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\">\n Cross-Component Validation & Quota Rules\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ marginTop: 4 }}>\n Define and enforce limits across Dynamic Zone components without writing code. Changes take effect immediately in both Admin edit view and Document Service APIs.\n </Typography>\n </Box>\n <Flex gap={2}>\n <Button\n variant=\"tertiary\"\n startIcon={<ArrowClockwise />}\n onClick={fetchRules}\n loading={loading}\n >\n Refresh\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Plus />}\n onClick={openCreateModal}\n >\n Create New Rule\n </Button>\n </Flex>\n </Flex>\n </Box>\n\n {/* Rules Table */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius>\n <Typography variant=\"sigma\" textColor=\"neutral600\" marginBottom={3} style={{ display: 'block' }}>\n CONFIGURED RULES ({rules.length})\n </Typography>\n\n {loading ? (\n <Typography variant=\"omega\" textColor=\"neutral500\">Loading validation rules...</Typography>\n ) : rules.length === 0 ? (\n <Alert variant=\"info\" title=\"No Rules Defined\">\n Click \"Create New Rule\" above to add your first cross-component quota rule.\n </Alert>\n ) : (\n <Table colCount={6} rowCount={rules.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">RULE NAME & TARGET FIELD</Typography></Th>\n <Th><Typography variant=\"sigma\">DESCRIPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">QUOTA CONSTRAINTS</Typography></Th>\n <Th><Typography variant=\"sigma\">EXCEEDED ACTION</Typography></Th>\n <Th><Typography variant=\"sigma\">STATUS</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTIONS</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {rules.map((rule) => {\n const quotaKeys = Object.entries(rule.quotas || {});\n return (\n <Tr key={rule.id}>\n <Td style={{ minWidth: 200 }}>\n <Typography variant=\"omega\" fontWeight=\"bold\" textColor=\"neutral800\" display=\"block\">\n {rule.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n Target Field: <code>{rule.targetField}</code>\n </Typography>\n </Td>\n <Td style={{ maxWidth: 300 }}>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {rule.description || '—'}\n </Typography>\n </Td>\n <Td style={{ minWidth: 220 }}>\n <Flex gap={1} wrap=\"wrap\">\n {quotaKeys.map(([optVal, maxVal]) => (\n <Badge key={optVal} backgroundColor=\"neutral100\" textColor=\"primary700\">\n <strong>{optVal.toUpperCase()}</strong>: max {maxVal}\n </Badge>\n ))}\n </Flex>\n </Td>\n <Td style={{ minWidth: 120 }}>\n <Badge\n backgroundColor={rule.exceededAction === 'hide' ? 'secondary100' : 'warning100'}\n textColor={rule.exceededAction === 'hide' ? 'secondary700' : 'warning700'}\n >\n {rule.exceededAction.toUpperCase()}\n </Badge>\n </Td>\n <Td style={{ minWidth: 100 }}>\n <Button\n variant={rule.enabled ? 'success-light' : 'tertiary'}\n size=\"S\"\n onClick={() => handleToggle(rule)}\n >\n {rule.enabled ? '● ACTIVE' : '○ DISABLED'}\n </Button>\n </Td>\n <Td style={{ textAlign: 'right', minWidth: 260 }}>\n <Flex gap={2} justifyContent=\"flex-end\">\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Search />}\n onClick={() => handleScanRule(rule)}\n loading={scanningRuleId === rule.id}\n >\n Scan Violations\n </Button>\n <Button\n variant=\"tertiary\"\n size=\"S\"\n onClick={() => openEditModal(rule)}\n >\n Edit\n </Button>\n <Button\n variant=\"danger-light\"\n size=\"S\"\n startIcon={<Trash />}\n onClick={() => handleDelete(rule.id, rule.name)}\n >\n Delete\n </Button>\n </Flex>\n </Td>\n </Tr>\n );\n })}\n </Tbody>\n </Table>\n )}\n </Box>\n\n {/* Create / Edit Rule Modal */}\n {modalOpen && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 620, maxHeight: '90vh', overflowY: 'auto' }}\n >\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\" marginBottom={1}>\n {editingRule ? 'Edit Validation Rule' : 'Create New Validation Rule'}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" marginBottom={4} style={{ display: 'block' }}>\n Configure cross-component limits. The rule will automatically apply to any Dynamic Zone or Component using this attribute.\n </Typography>\n\n <Flex direction=\"column\" gap={4} alignItems=\"stretch\">\n <TextInput\n label=\"Rule Name\"\n placeholder=\"e.g. SEO Single H1 Rule\"\n value={formName}\n onChange={(e: any) => setFormName(e.target.value)}\n required\n />\n\n <TextInput\n label=\"Target Field Name\"\n placeholder=\"e.g. headingLevel, titleStyle, or color\"\n value={formField}\n onChange={(e: any) => setFormField(e.target.value)}\n hint=\"Attribute name on the component/customField to monitor across the entry.\"\n required\n />\n\n <Textarea\n label=\"Rule Description\"\n placeholder=\"Briefly explain what this constraint accomplishes...\"\n value={formDesc}\n onChange={(e: any) => setFormDesc(e.target.value)}\n />\n\n <SingleSelect\n label=\"When Quota Is Exceeded in Another Component\"\n value={formAction}\n onChange={(val: any) => setFormAction(val as 'disable' | 'hide')}\n >\n <SingleSelectOption value=\"disable\">\n Disable Option with Usage Badge [(1/1 used)]\n </SingleSelectOption>\n <SingleSelectOption value=\"hide\">\n Hide Option completely from dropdown menu\n </SingleSelectOption>\n </SingleSelect>\n\n {/* Quotas Editor */}\n <Box\n padding={4}\n background=\"neutral100\"\n hasRadius\n style={{ border: '1px solid #e0e0e0' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={3}>\n <Box>\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral800\">\n Option Quotas (Max Allowed per Entry)\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ display: 'block' }}>\n Options left unlisted will have unlimited usage.\n </Typography>\n </Box>\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={handleAddQuotaRow}\n >\n Add Option\n </Button>\n </Flex>\n\n <Flex direction=\"column\" gap={2}>\n {formQuotas.map((q, idx) => (\n <Flex key={idx} gap={2} alignItems=\"center\">\n <Box style={{ flex: 2 }}>\n <TextInput\n placeholder=\"Option key (e.g. h1)\"\n value={q.key}\n onChange={(e: any) => handleQuotaChange(idx, 'key', e.target.value)}\n />\n </Box>\n <Box style={{ flex: 1 }}>\n <TextInput\n type=\"number\"\n placeholder=\"Max\"\n value={String(q.maxAllowed)}\n onChange={(e: any) => handleQuotaChange(idx, 'maxAllowed', e.target.value)}\n />\n </Box>\n <Button\n variant=\"ghost\"\n size=\"S\"\n onClick={() => handleRemoveQuotaRow(idx)}\n disabled={formQuotas.length <= 1}\n >\n ✕\n </Button>\n </Flex>\n ))}\n </Flex>\n </Box>\n </Flex>\n\n {/* Modal Actions */}\n <Flex justifyContent=\"flex-end\" gap={2} marginTop={6}>\n <Button\n variant=\"tertiary\"\n onClick={() => setModalOpen(false)}\n disabled={saving}\n >\n Cancel\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Check />}\n onClick={handleSave}\n loading={saving}\n >\n Save Rule\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n\n {/* Scan Results Modal */}\n {scanModalOpen && scanReport && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 780, maxHeight: '85vh', overflowY: 'auto' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={4}>\n <Box>\n <Typography variant=\"beta\" tag=\"h2\" fontWeight=\"bold\">\n Rule Violation Audit: {scanReport.rule?.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n Target Field: <code>{scanReport.rule?.targetField}</code> • Total Entries Scanned: {scanReport.totalScanned}\n </Typography>\n </Box>\n <Badge\n backgroundColor={scanReport.totalViolations > 0 ? 'danger100' : 'success100'}\n textColor={scanReport.totalViolations > 0 ? 'danger700' : 'success700'}\n size=\"M\"\n >\n {scanReport.totalViolations > 0\n ? `${scanReport.totalViolations} VIOLATION(S) FOUND`\n : '100% COMPLIANT'}\n </Badge>\n </Flex>\n\n {scanReport.totalViolations === 0 ? (\n <Alert variant=\"success\" title=\"No Pre-Existing Violations Detected\" marginBottom={4}>\n All existing documents across your collections adhere strictly to the configured quota limits.\n </Alert>\n ) : (\n <Box>\n <Alert variant=\"danger\" title=\"Legacy Records Found Exceeding Quota\" marginBottom={4}>\n The following {scanReport.totalViolations} record(s) contain more instances of restricted options than currently permitted by this rule.\n </Alert>\n\n <Table colCount={4} rowCount={scanReport.violations.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">CONTENT TYPE & ENTRY</Typography></Th>\n <Th><Typography variant=\"sigma\">RESTRICTED OPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">COUNT VS LIMIT</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTION</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {scanReport.violations.map((v: any, idx: number) => (\n <Tr key={idx}>\n <Td>\n <Typography variant=\"omega\" fontWeight=\"bold\">\n {v.entryLabel}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\" display=\"block\">\n Collection: {v.collectionDisplayName}\n </Typography>\n </Td>\n <Td>\n <Badge backgroundColor=\"warning100\" textColor=\"warning700\">\n {v.violatingOption}\n </Badge>\n </Td>\n <Td>\n <Typography variant=\"omega\" textColor=\"danger600\" fontWeight=\"bold\">\n {v.foundCount} used\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {' '}(Allowed max: {v.maxAllowed})\n </Typography>\n </Td>\n <Td style={{ textAlign: 'right' }}>\n <Button\n variant=\"secondary\"\n size=\"S\"\n onClick={() => window.open(v.editUrl, '_blank')}\n >\n Open in Editor ↗\n </Button>\n </Td>\n </Tr>\n ))}\n </Tbody>\n </Table>\n </Box>\n )}\n\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginTop={6}>\n {scanReport.totalViolations > 0 ? (\n <Button\n variant=\"secondary\"\n startIcon={<Download />}\n onClick={async () => {\n try {\n const res = await get(`/bulk-updater/csv/export-violations/${scanReport.rule.id}`);\n const csvStr = res.data?.csvContent || (typeof res.data === 'string' ? res.data : '');\n if (!csvStr) {\n toggleNotification({\n type: 'warning',\n message: 'No violation data to export',\n });\n return;\n }\n const safeContent = csvStr.startsWith('\\uFEFF') ? csvStr : '\\uFEFF' + csvStr;\n const blob = new Blob([safeContent], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `violations_${scanReport.rule.id}.csv`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n toggleNotification({\n type: 'success',\n message: 'Violations exported to CSV successfully',\n });\n } catch (e: any) {\n toggleNotification({\n type: 'danger',\n message: e.message || 'Failed exporting violations CSV',\n });\n }\n }}\n >\n Export Violations CSV\n </Button>\n ) : (\n <Box />\n )}\n <Button variant=\"default\" onClick={() => setScanModalOpen(false)}>\n Close Report\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n"],"names":["useFetchClient","useNotification","useState","useEffect","Box","jsx","jsxs","Flex","Typography","Button","ArrowClockwise","Plus","Alert","Table","Thead","Tr","Th","Tbody","Td","Badge","Search","Trash","TextInput","Textarea","SingleSelect","SingleSelectOption","Check","Download"],"mappings":"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"}
|
|
@@ -560,7 +560,8 @@ function ValidationRulesTab() {
|
|
|
560
560
|
});
|
|
561
561
|
return;
|
|
562
562
|
}
|
|
563
|
-
const
|
|
563
|
+
const safeContent = csvStr.startsWith("\uFEFF") ? csvStr : "\uFEFF" + csvStr;
|
|
564
|
+
const blob = new Blob([safeContent], { type: "text/csv;charset=utf-8;" });
|
|
564
565
|
const url = URL.createObjectURL(blob);
|
|
565
566
|
const link = document.createElement("a");
|
|
566
567
|
link.href = url;
|
|
@@ -595,4 +596,4 @@ function ValidationRulesTab() {
|
|
|
595
596
|
export {
|
|
596
597
|
ValidationRulesTab as V
|
|
597
598
|
};
|
|
598
|
-
//# sourceMappingURL=ValidationRulesTab-
|
|
599
|
+
//# sourceMappingURL=ValidationRulesTab-Dt53h-Ke.mjs.map
|
package/dist/_chunks/{ValidationRulesTab-BGcqM9cN.mjs.map → ValidationRulesTab-Dt53h-Ke.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationRulesTab-BGcqM9cN.mjs","sources":["../../admin/src/pages/ValidationRulesTab.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { useFetchClient, useNotification } from '@strapi/strapi/admin';\nimport {\n Box,\n Flex,\n Typography,\n Button,\n TextInput,\n Textarea,\n SingleSelect,\n SingleSelectOption,\n Badge,\n Table,\n Thead,\n Tbody,\n Tr,\n Th,\n Td,\n Alert,\n} from '@strapi/design-system';\nimport { Plus, Trash, Check, ArrowClockwise, Search, Download } from '@strapi/icons';\n\nexport interface ValidationRule {\n id: string;\n name: string;\n description?: string;\n targetField: string;\n quotas: Record<string, number>;\n exceededAction: 'disable' | 'hide';\n enabled: boolean;\n scope: 'entry' | 'document';\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport default function ValidationRulesTab() {\n const { get, post, del } = useFetchClient();\n const { toggleNotification } = useNotification();\n\n const [rules, setRules] = useState<ValidationRule[]>([]);\n const [loading, setLoading] = useState<boolean>(true);\n const [modalOpen, setModalOpen] = useState<boolean>(false);\n const [editingRule, setEditingRule] = useState<ValidationRule | null>(null);\n\n // Form state for creating/editing a rule\n const [formName, setFormName] = useState<string>('');\n const [formDesc, setFormDesc] = useState<string>('');\n const [formField, setFormField] = useState<string>('');\n const [formAction, setFormAction] = useState<'disable' | 'hide'>('disable');\n const [formQuotas, setFormQuotas] = useState<Array<{ key: string; maxAllowed: number }>>([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n const [saving, setSaving] = useState<boolean>(false);\n\n // Scan modal state\n const [scanModalOpen, setScanModalOpen] = useState<boolean>(false);\n const [scanningRuleId, setScanningRuleId] = useState<string | null>(null);\n const [scanReport, setScanReport] = useState<any>(null);\n\n const handleScanRule = async (rule: ValidationRule) => {\n try {\n setScanningRuleId(rule.id);\n const res = await get(`/bulk-updater/validation-rules/${rule.id}/scan`);\n if (res.data && res.data.success) {\n setScanReport(res.data);\n setScanModalOpen(true);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Scan failed: ${err.message}`,\n });\n } finally {\n setScanningRuleId(null);\n }\n };\n\n const fetchRules = async () => {\n try {\n setLoading(true);\n const res = await get('/bulk-updater/validation-rules');\n if (res.data && res.data.success) {\n setRules(res.data.rules || []);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to load rules: ${err.message}`,\n });\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n fetchRules();\n }, []);\n\n const openCreateModal = () => {\n setEditingRule(null);\n setFormName('');\n setFormDesc('');\n setFormField('headingLevel');\n setFormAction('disable');\n setFormQuotas([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n setModalOpen(true);\n };\n\n const openEditModal = (rule: ValidationRule) => {\n setEditingRule(rule);\n setFormName(rule.name);\n setFormDesc(rule.description || '');\n setFormField(rule.targetField);\n setFormAction(rule.exceededAction || 'disable');\n const quotaPairs = Object.entries(rule.quotas || {}).map(([k, v]) => ({\n key: k,\n maxAllowed: v,\n }));\n setFormQuotas(quotaPairs.length > 0 ? quotaPairs : [{ key: 'h1', maxAllowed: 1 }]);\n setModalOpen(true);\n };\n\n const handleAddQuotaRow = () => {\n setFormQuotas((prev) => [...prev, { key: '', maxAllowed: 1 }]);\n };\n\n const handleRemoveQuotaRow = (idx: number) => {\n setFormQuotas((prev) => prev.filter((_, i) => i !== idx));\n };\n\n const handleQuotaChange = (idx: number, field: 'key' | 'maxAllowed', value: any) => {\n setFormQuotas((prev) =>\n prev.map((row, i) => {\n if (i === idx) {\n return {\n ...row,\n [field]: field === 'maxAllowed' ? Math.max(1, parseInt(value, 10) || 1) : String(value).trim(),\n };\n }\n return row;\n })\n );\n };\n\n const handleSave = async () => {\n if (!formName.trim() || !formField.trim()) {\n toggleNotification({\n type: 'warning',\n message: 'Rule Name and Target Field are required.',\n });\n return;\n }\n\n const quotasRecord: Record<string, number> = {};\n for (const q of formQuotas) {\n if (q.key.trim()) {\n quotasRecord[q.key.trim().toLowerCase()] = q.maxAllowed;\n }\n }\n\n if (Object.keys(quotasRecord).length === 0) {\n toggleNotification({\n type: 'warning',\n message: 'At least one quota option with a limit is required.',\n });\n return;\n }\n\n try {\n setSaving(true);\n const payload: Partial<ValidationRule> = {\n id: editingRule ? editingRule.id : undefined,\n name: formName.trim(),\n description: formDesc.trim(),\n targetField: formField.trim(),\n quotas: quotasRecord,\n exceededAction: formAction,\n enabled: editingRule ? editingRule.enabled : true,\n scope: 'entry',\n };\n\n const res = await post('/bulk-updater/validation-rules', { rule: payload });\n if (res.data && res.data.success) {\n toggleNotification({\n type: 'success',\n message: `Rule \"${payload.name}\" saved successfully!`,\n });\n setModalOpen(false);\n fetchRules();\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to save rule: ${err.message}`,\n });\n } finally {\n setSaving(false);\n }\n };\n\n const handleToggle = async (rule: ValidationRule) => {\n try {\n const res = await post(`/bulk-updater/validation-rules/${rule.id}/toggle`, {\n enabled: !rule.enabled,\n });\n if (res.data && res.data.success) {\n setRules((prev) =>\n prev.map((r) => (r.id === rule.id ? { ...r, enabled: !rule.enabled } : r))\n );\n toggleNotification({\n type: 'info',\n message: `Rule \"${rule.name}\" is now ${!rule.enabled ? 'ACTIVE' : 'DISABLED'}.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to update rule status: ${err.message}`,\n });\n }\n };\n\n const handleDelete = async (ruleId: string, ruleName: string) => {\n if (!window.confirm(`Are you sure you want to delete the rule \"${ruleName}\"?`)) return;\n\n try {\n const res = await del(`/bulk-updater/validation-rules/${ruleId}`);\n if (res.data && res.data.success) {\n setRules((prev) => prev.filter((r) => r.id !== ruleId));\n toggleNotification({\n type: 'success',\n message: `Rule \"${ruleName}\" deleted.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to delete rule: ${err.message}`,\n });\n }\n };\n\n return (\n <Box>\n {/* Header Panel */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius marginBottom={6}>\n <Flex justifyContent=\"space-between\" alignItems=\"center\" wrap=\"wrap\" gap={3}>\n <Box>\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\">\n Cross-Component Validation & Quota Rules\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ marginTop: 4 }}>\n Define and enforce limits across Dynamic Zone components without writing code. Changes take effect immediately in both Admin edit view and Document Service APIs.\n </Typography>\n </Box>\n <Flex gap={2}>\n <Button\n variant=\"tertiary\"\n startIcon={<ArrowClockwise />}\n onClick={fetchRules}\n loading={loading}\n >\n Refresh\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Plus />}\n onClick={openCreateModal}\n >\n Create New Rule\n </Button>\n </Flex>\n </Flex>\n </Box>\n\n {/* Rules Table */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius>\n <Typography variant=\"sigma\" textColor=\"neutral600\" marginBottom={3} style={{ display: 'block' }}>\n CONFIGURED RULES ({rules.length})\n </Typography>\n\n {loading ? (\n <Typography variant=\"omega\" textColor=\"neutral500\">Loading validation rules...</Typography>\n ) : rules.length === 0 ? (\n <Alert variant=\"info\" title=\"No Rules Defined\">\n Click \"Create New Rule\" above to add your first cross-component quota rule.\n </Alert>\n ) : (\n <Table colCount={6} rowCount={rules.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">RULE NAME & TARGET FIELD</Typography></Th>\n <Th><Typography variant=\"sigma\">DESCRIPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">QUOTA CONSTRAINTS</Typography></Th>\n <Th><Typography variant=\"sigma\">EXCEEDED ACTION</Typography></Th>\n <Th><Typography variant=\"sigma\">STATUS</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTIONS</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {rules.map((rule) => {\n const quotaKeys = Object.entries(rule.quotas || {});\n return (\n <Tr key={rule.id}>\n <Td style={{ minWidth: 200 }}>\n <Typography variant=\"omega\" fontWeight=\"bold\" textColor=\"neutral800\" display=\"block\">\n {rule.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n Target Field: <code>{rule.targetField}</code>\n </Typography>\n </Td>\n <Td style={{ maxWidth: 300 }}>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {rule.description || '—'}\n </Typography>\n </Td>\n <Td style={{ minWidth: 220 }}>\n <Flex gap={1} wrap=\"wrap\">\n {quotaKeys.map(([optVal, maxVal]) => (\n <Badge key={optVal} backgroundColor=\"neutral100\" textColor=\"primary700\">\n <strong>{optVal.toUpperCase()}</strong>: max {maxVal}\n </Badge>\n ))}\n </Flex>\n </Td>\n <Td style={{ minWidth: 120 }}>\n <Badge\n backgroundColor={rule.exceededAction === 'hide' ? 'secondary100' : 'warning100'}\n textColor={rule.exceededAction === 'hide' ? 'secondary700' : 'warning700'}\n >\n {rule.exceededAction.toUpperCase()}\n </Badge>\n </Td>\n <Td style={{ minWidth: 100 }}>\n <Button\n variant={rule.enabled ? 'success-light' : 'tertiary'}\n size=\"S\"\n onClick={() => handleToggle(rule)}\n >\n {rule.enabled ? '● ACTIVE' : '○ DISABLED'}\n </Button>\n </Td>\n <Td style={{ textAlign: 'right', minWidth: 260 }}>\n <Flex gap={2} justifyContent=\"flex-end\">\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Search />}\n onClick={() => handleScanRule(rule)}\n loading={scanningRuleId === rule.id}\n >\n Scan Violations\n </Button>\n <Button\n variant=\"tertiary\"\n size=\"S\"\n onClick={() => openEditModal(rule)}\n >\n Edit\n </Button>\n <Button\n variant=\"danger-light\"\n size=\"S\"\n startIcon={<Trash />}\n onClick={() => handleDelete(rule.id, rule.name)}\n >\n Delete\n </Button>\n </Flex>\n </Td>\n </Tr>\n );\n })}\n </Tbody>\n </Table>\n )}\n </Box>\n\n {/* Create / Edit Rule Modal */}\n {modalOpen && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 620, maxHeight: '90vh', overflowY: 'auto' }}\n >\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\" marginBottom={1}>\n {editingRule ? 'Edit Validation Rule' : 'Create New Validation Rule'}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" marginBottom={4} style={{ display: 'block' }}>\n Configure cross-component limits. The rule will automatically apply to any Dynamic Zone or Component using this attribute.\n </Typography>\n\n <Flex direction=\"column\" gap={4} alignItems=\"stretch\">\n <TextInput\n label=\"Rule Name\"\n placeholder=\"e.g. SEO Single H1 Rule\"\n value={formName}\n onChange={(e: any) => setFormName(e.target.value)}\n required\n />\n\n <TextInput\n label=\"Target Field Name\"\n placeholder=\"e.g. headingLevel, titleStyle, or color\"\n value={formField}\n onChange={(e: any) => setFormField(e.target.value)}\n hint=\"Attribute name on the component/customField to monitor across the entry.\"\n required\n />\n\n <Textarea\n label=\"Rule Description\"\n placeholder=\"Briefly explain what this constraint accomplishes...\"\n value={formDesc}\n onChange={(e: any) => setFormDesc(e.target.value)}\n />\n\n <SingleSelect\n label=\"When Quota Is Exceeded in Another Component\"\n value={formAction}\n onChange={(val: any) => setFormAction(val as 'disable' | 'hide')}\n >\n <SingleSelectOption value=\"disable\">\n Disable Option with Usage Badge [(1/1 used)]\n </SingleSelectOption>\n <SingleSelectOption value=\"hide\">\n Hide Option completely from dropdown menu\n </SingleSelectOption>\n </SingleSelect>\n\n {/* Quotas Editor */}\n <Box\n padding={4}\n background=\"neutral100\"\n hasRadius\n style={{ border: '1px solid #e0e0e0' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={3}>\n <Box>\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral800\">\n Option Quotas (Max Allowed per Entry)\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ display: 'block' }}>\n Options left unlisted will have unlimited usage.\n </Typography>\n </Box>\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={handleAddQuotaRow}\n >\n Add Option\n </Button>\n </Flex>\n\n <Flex direction=\"column\" gap={2}>\n {formQuotas.map((q, idx) => (\n <Flex key={idx} gap={2} alignItems=\"center\">\n <Box style={{ flex: 2 }}>\n <TextInput\n placeholder=\"Option key (e.g. h1)\"\n value={q.key}\n onChange={(e: any) => handleQuotaChange(idx, 'key', e.target.value)}\n />\n </Box>\n <Box style={{ flex: 1 }}>\n <TextInput\n type=\"number\"\n placeholder=\"Max\"\n value={String(q.maxAllowed)}\n onChange={(e: any) => handleQuotaChange(idx, 'maxAllowed', e.target.value)}\n />\n </Box>\n <Button\n variant=\"ghost\"\n size=\"S\"\n onClick={() => handleRemoveQuotaRow(idx)}\n disabled={formQuotas.length <= 1}\n >\n ✕\n </Button>\n </Flex>\n ))}\n </Flex>\n </Box>\n </Flex>\n\n {/* Modal Actions */}\n <Flex justifyContent=\"flex-end\" gap={2} marginTop={6}>\n <Button\n variant=\"tertiary\"\n onClick={() => setModalOpen(false)}\n disabled={saving}\n >\n Cancel\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Check />}\n onClick={handleSave}\n loading={saving}\n >\n Save Rule\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n\n {/* Scan Results Modal */}\n {scanModalOpen && scanReport && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 780, maxHeight: '85vh', overflowY: 'auto' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={4}>\n <Box>\n <Typography variant=\"beta\" tag=\"h2\" fontWeight=\"bold\">\n Rule Violation Audit: {scanReport.rule?.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n Target Field: <code>{scanReport.rule?.targetField}</code> • Total Entries Scanned: {scanReport.totalScanned}\n </Typography>\n </Box>\n <Badge\n backgroundColor={scanReport.totalViolations > 0 ? 'danger100' : 'success100'}\n textColor={scanReport.totalViolations > 0 ? 'danger700' : 'success700'}\n size=\"M\"\n >\n {scanReport.totalViolations > 0\n ? `${scanReport.totalViolations} VIOLATION(S) FOUND`\n : '100% COMPLIANT'}\n </Badge>\n </Flex>\n\n {scanReport.totalViolations === 0 ? (\n <Alert variant=\"success\" title=\"No Pre-Existing Violations Detected\" marginBottom={4}>\n All existing documents across your collections adhere strictly to the configured quota limits.\n </Alert>\n ) : (\n <Box>\n <Alert variant=\"danger\" title=\"Legacy Records Found Exceeding Quota\" marginBottom={4}>\n The following {scanReport.totalViolations} record(s) contain more instances of restricted options than currently permitted by this rule.\n </Alert>\n\n <Table colCount={4} rowCount={scanReport.violations.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">CONTENT TYPE & ENTRY</Typography></Th>\n <Th><Typography variant=\"sigma\">RESTRICTED OPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">COUNT VS LIMIT</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTION</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {scanReport.violations.map((v: any, idx: number) => (\n <Tr key={idx}>\n <Td>\n <Typography variant=\"omega\" fontWeight=\"bold\">\n {v.entryLabel}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\" display=\"block\">\n Collection: {v.collectionDisplayName}\n </Typography>\n </Td>\n <Td>\n <Badge backgroundColor=\"warning100\" textColor=\"warning700\">\n {v.violatingOption}\n </Badge>\n </Td>\n <Td>\n <Typography variant=\"omega\" textColor=\"danger600\" fontWeight=\"bold\">\n {v.foundCount} used\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {' '}(Allowed max: {v.maxAllowed})\n </Typography>\n </Td>\n <Td style={{ textAlign: 'right' }}>\n <Button\n variant=\"secondary\"\n size=\"S\"\n onClick={() => window.open(v.editUrl, '_blank')}\n >\n Open in Editor ↗\n </Button>\n </Td>\n </Tr>\n ))}\n </Tbody>\n </Table>\n </Box>\n )}\n\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginTop={6}>\n {scanReport.totalViolations > 0 ? (\n <Button\n variant=\"secondary\"\n startIcon={<Download />}\n onClick={async () => {\n try {\n const res = await get(`/bulk-updater/csv/export-violations/${scanReport.rule.id}`);\n const csvStr = res.data?.csvContent || (typeof res.data === 'string' ? res.data : '');\n if (!csvStr) {\n toggleNotification({\n type: 'warning',\n message: 'No violation data to export',\n });\n return;\n }\n const blob = new Blob([csvStr], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `violations_${scanReport.rule.id}.csv`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n toggleNotification({\n type: 'success',\n message: 'Violations exported to CSV successfully',\n });\n } catch (e: any) {\n toggleNotification({\n type: 'danger',\n message: e.message || 'Failed exporting violations CSV',\n });\n }\n }}\n >\n Export Violations CSV\n </Button>\n ) : (\n <Box />\n )}\n <Button variant=\"default\" onClick={() => setScanModalOpen(false)}>\n Close Report\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ValidationRulesTab-Dt53h-Ke.mjs","sources":["../../admin/src/pages/ValidationRulesTab.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { useFetchClient, useNotification } from '@strapi/strapi/admin';\nimport {\n Box,\n Flex,\n Typography,\n Button,\n TextInput,\n Textarea,\n SingleSelect,\n SingleSelectOption,\n Badge,\n Table,\n Thead,\n Tbody,\n Tr,\n Th,\n Td,\n Alert,\n} from '@strapi/design-system';\nimport { Plus, Trash, Check, ArrowClockwise, Search, Download } from '@strapi/icons';\n\nexport interface ValidationRule {\n id: string;\n name: string;\n description?: string;\n targetField: string;\n quotas: Record<string, number>;\n exceededAction: 'disable' | 'hide';\n enabled: boolean;\n scope: 'entry' | 'document';\n createdAt?: string;\n updatedAt?: string;\n}\n\nexport default function ValidationRulesTab() {\n const { get, post, del } = useFetchClient();\n const { toggleNotification } = useNotification();\n\n const [rules, setRules] = useState<ValidationRule[]>([]);\n const [loading, setLoading] = useState<boolean>(true);\n const [modalOpen, setModalOpen] = useState<boolean>(false);\n const [editingRule, setEditingRule] = useState<ValidationRule | null>(null);\n\n // Form state for creating/editing a rule\n const [formName, setFormName] = useState<string>('');\n const [formDesc, setFormDesc] = useState<string>('');\n const [formField, setFormField] = useState<string>('');\n const [formAction, setFormAction] = useState<'disable' | 'hide'>('disable');\n const [formQuotas, setFormQuotas] = useState<Array<{ key: string; maxAllowed: number }>>([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n const [saving, setSaving] = useState<boolean>(false);\n\n // Scan modal state\n const [scanModalOpen, setScanModalOpen] = useState<boolean>(false);\n const [scanningRuleId, setScanningRuleId] = useState<string | null>(null);\n const [scanReport, setScanReport] = useState<any>(null);\n\n const handleScanRule = async (rule: ValidationRule) => {\n try {\n setScanningRuleId(rule.id);\n const res = await get(`/bulk-updater/validation-rules/${rule.id}/scan`);\n if (res.data && res.data.success) {\n setScanReport(res.data);\n setScanModalOpen(true);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Scan failed: ${err.message}`,\n });\n } finally {\n setScanningRuleId(null);\n }\n };\n\n const fetchRules = async () => {\n try {\n setLoading(true);\n const res = await get('/bulk-updater/validation-rules');\n if (res.data && res.data.success) {\n setRules(res.data.rules || []);\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to load rules: ${err.message}`,\n });\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n fetchRules();\n }, []);\n\n const openCreateModal = () => {\n setEditingRule(null);\n setFormName('');\n setFormDesc('');\n setFormField('headingLevel');\n setFormAction('disable');\n setFormQuotas([\n { key: 'h1', maxAllowed: 1 },\n { key: 'h2', maxAllowed: 3 },\n ]);\n setModalOpen(true);\n };\n\n const openEditModal = (rule: ValidationRule) => {\n setEditingRule(rule);\n setFormName(rule.name);\n setFormDesc(rule.description || '');\n setFormField(rule.targetField);\n setFormAction(rule.exceededAction || 'disable');\n const quotaPairs = Object.entries(rule.quotas || {}).map(([k, v]) => ({\n key: k,\n maxAllowed: v,\n }));\n setFormQuotas(quotaPairs.length > 0 ? quotaPairs : [{ key: 'h1', maxAllowed: 1 }]);\n setModalOpen(true);\n };\n\n const handleAddQuotaRow = () => {\n setFormQuotas((prev) => [...prev, { key: '', maxAllowed: 1 }]);\n };\n\n const handleRemoveQuotaRow = (idx: number) => {\n setFormQuotas((prev) => prev.filter((_, i) => i !== idx));\n };\n\n const handleQuotaChange = (idx: number, field: 'key' | 'maxAllowed', value: any) => {\n setFormQuotas((prev) =>\n prev.map((row, i) => {\n if (i === idx) {\n return {\n ...row,\n [field]: field === 'maxAllowed' ? Math.max(1, parseInt(value, 10) || 1) : String(value).trim(),\n };\n }\n return row;\n })\n );\n };\n\n const handleSave = async () => {\n if (!formName.trim() || !formField.trim()) {\n toggleNotification({\n type: 'warning',\n message: 'Rule Name and Target Field are required.',\n });\n return;\n }\n\n const quotasRecord: Record<string, number> = {};\n for (const q of formQuotas) {\n if (q.key.trim()) {\n quotasRecord[q.key.trim().toLowerCase()] = q.maxAllowed;\n }\n }\n\n if (Object.keys(quotasRecord).length === 0) {\n toggleNotification({\n type: 'warning',\n message: 'At least one quota option with a limit is required.',\n });\n return;\n }\n\n try {\n setSaving(true);\n const payload: Partial<ValidationRule> = {\n id: editingRule ? editingRule.id : undefined,\n name: formName.trim(),\n description: formDesc.trim(),\n targetField: formField.trim(),\n quotas: quotasRecord,\n exceededAction: formAction,\n enabled: editingRule ? editingRule.enabled : true,\n scope: 'entry',\n };\n\n const res = await post('/bulk-updater/validation-rules', { rule: payload });\n if (res.data && res.data.success) {\n toggleNotification({\n type: 'success',\n message: `Rule \"${payload.name}\" saved successfully!`,\n });\n setModalOpen(false);\n fetchRules();\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to save rule: ${err.message}`,\n });\n } finally {\n setSaving(false);\n }\n };\n\n const handleToggle = async (rule: ValidationRule) => {\n try {\n const res = await post(`/bulk-updater/validation-rules/${rule.id}/toggle`, {\n enabled: !rule.enabled,\n });\n if (res.data && res.data.success) {\n setRules((prev) =>\n prev.map((r) => (r.id === rule.id ? { ...r, enabled: !rule.enabled } : r))\n );\n toggleNotification({\n type: 'info',\n message: `Rule \"${rule.name}\" is now ${!rule.enabled ? 'ACTIVE' : 'DISABLED'}.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to update rule status: ${err.message}`,\n });\n }\n };\n\n const handleDelete = async (ruleId: string, ruleName: string) => {\n if (!window.confirm(`Are you sure you want to delete the rule \"${ruleName}\"?`)) return;\n\n try {\n const res = await del(`/bulk-updater/validation-rules/${ruleId}`);\n if (res.data && res.data.success) {\n setRules((prev) => prev.filter((r) => r.id !== ruleId));\n toggleNotification({\n type: 'success',\n message: `Rule \"${ruleName}\" deleted.`,\n });\n }\n } catch (err: any) {\n toggleNotification({\n type: 'danger',\n message: `Failed to delete rule: ${err.message}`,\n });\n }\n };\n\n return (\n <Box>\n {/* Header Panel */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius marginBottom={6}>\n <Flex justifyContent=\"space-between\" alignItems=\"center\" wrap=\"wrap\" gap={3}>\n <Box>\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\">\n Cross-Component Validation & Quota Rules\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ marginTop: 4 }}>\n Define and enforce limits across Dynamic Zone components without writing code. Changes take effect immediately in both Admin edit view and Document Service APIs.\n </Typography>\n </Box>\n <Flex gap={2}>\n <Button\n variant=\"tertiary\"\n startIcon={<ArrowClockwise />}\n onClick={fetchRules}\n loading={loading}\n >\n Refresh\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Plus />}\n onClick={openCreateModal}\n >\n Create New Rule\n </Button>\n </Flex>\n </Flex>\n </Box>\n\n {/* Rules Table */}\n <Box padding={6} background=\"neutral0\" shadow=\"filterShadow\" hasRadius>\n <Typography variant=\"sigma\" textColor=\"neutral600\" marginBottom={3} style={{ display: 'block' }}>\n CONFIGURED RULES ({rules.length})\n </Typography>\n\n {loading ? (\n <Typography variant=\"omega\" textColor=\"neutral500\">Loading validation rules...</Typography>\n ) : rules.length === 0 ? (\n <Alert variant=\"info\" title=\"No Rules Defined\">\n Click \"Create New Rule\" above to add your first cross-component quota rule.\n </Alert>\n ) : (\n <Table colCount={6} rowCount={rules.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">RULE NAME & TARGET FIELD</Typography></Th>\n <Th><Typography variant=\"sigma\">DESCRIPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">QUOTA CONSTRAINTS</Typography></Th>\n <Th><Typography variant=\"sigma\">EXCEEDED ACTION</Typography></Th>\n <Th><Typography variant=\"sigma\">STATUS</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTIONS</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {rules.map((rule) => {\n const quotaKeys = Object.entries(rule.quotas || {});\n return (\n <Tr key={rule.id}>\n <Td style={{ minWidth: 200 }}>\n <Typography variant=\"omega\" fontWeight=\"bold\" textColor=\"neutral800\" display=\"block\">\n {rule.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n Target Field: <code>{rule.targetField}</code>\n </Typography>\n </Td>\n <Td style={{ maxWidth: 300 }}>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n {rule.description || '—'}\n </Typography>\n </Td>\n <Td style={{ minWidth: 220 }}>\n <Flex gap={1} wrap=\"wrap\">\n {quotaKeys.map(([optVal, maxVal]) => (\n <Badge key={optVal} backgroundColor=\"neutral100\" textColor=\"primary700\">\n <strong>{optVal.toUpperCase()}</strong>: max {maxVal}\n </Badge>\n ))}\n </Flex>\n </Td>\n <Td style={{ minWidth: 120 }}>\n <Badge\n backgroundColor={rule.exceededAction === 'hide' ? 'secondary100' : 'warning100'}\n textColor={rule.exceededAction === 'hide' ? 'secondary700' : 'warning700'}\n >\n {rule.exceededAction.toUpperCase()}\n </Badge>\n </Td>\n <Td style={{ minWidth: 100 }}>\n <Button\n variant={rule.enabled ? 'success-light' : 'tertiary'}\n size=\"S\"\n onClick={() => handleToggle(rule)}\n >\n {rule.enabled ? '● ACTIVE' : '○ DISABLED'}\n </Button>\n </Td>\n <Td style={{ textAlign: 'right', minWidth: 260 }}>\n <Flex gap={2} justifyContent=\"flex-end\">\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Search />}\n onClick={() => handleScanRule(rule)}\n loading={scanningRuleId === rule.id}\n >\n Scan Violations\n </Button>\n <Button\n variant=\"tertiary\"\n size=\"S\"\n onClick={() => openEditModal(rule)}\n >\n Edit\n </Button>\n <Button\n variant=\"danger-light\"\n size=\"S\"\n startIcon={<Trash />}\n onClick={() => handleDelete(rule.id, rule.name)}\n >\n Delete\n </Button>\n </Flex>\n </Td>\n </Tr>\n );\n })}\n </Tbody>\n </Table>\n )}\n </Box>\n\n {/* Create / Edit Rule Modal */}\n {modalOpen && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 620, maxHeight: '90vh', overflowY: 'auto' }}\n >\n <Typography variant=\"delta\" tag=\"h2\" fontWeight=\"bold\" marginBottom={1}>\n {editingRule ? 'Edit Validation Rule' : 'Create New Validation Rule'}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" marginBottom={4} style={{ display: 'block' }}>\n Configure cross-component limits. The rule will automatically apply to any Dynamic Zone or Component using this attribute.\n </Typography>\n\n <Flex direction=\"column\" gap={4} alignItems=\"stretch\">\n <TextInput\n label=\"Rule Name\"\n placeholder=\"e.g. SEO Single H1 Rule\"\n value={formName}\n onChange={(e: any) => setFormName(e.target.value)}\n required\n />\n\n <TextInput\n label=\"Target Field Name\"\n placeholder=\"e.g. headingLevel, titleStyle, or color\"\n value={formField}\n onChange={(e: any) => setFormField(e.target.value)}\n hint=\"Attribute name on the component/customField to monitor across the entry.\"\n required\n />\n\n <Textarea\n label=\"Rule Description\"\n placeholder=\"Briefly explain what this constraint accomplishes...\"\n value={formDesc}\n onChange={(e: any) => setFormDesc(e.target.value)}\n />\n\n <SingleSelect\n label=\"When Quota Is Exceeded in Another Component\"\n value={formAction}\n onChange={(val: any) => setFormAction(val as 'disable' | 'hide')}\n >\n <SingleSelectOption value=\"disable\">\n Disable Option with Usage Badge [(1/1 used)]\n </SingleSelectOption>\n <SingleSelectOption value=\"hide\">\n Hide Option completely from dropdown menu\n </SingleSelectOption>\n </SingleSelect>\n\n {/* Quotas Editor */}\n <Box\n padding={4}\n background=\"neutral100\"\n hasRadius\n style={{ border: '1px solid #e0e0e0' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={3}>\n <Box>\n <Typography variant=\"pi\" fontWeight=\"bold\" textColor=\"neutral800\">\n Option Quotas (Max Allowed per Entry)\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\" style={{ display: 'block' }}>\n Options left unlisted will have unlimited usage.\n </Typography>\n </Box>\n <Button\n variant=\"secondary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={handleAddQuotaRow}\n >\n Add Option\n </Button>\n </Flex>\n\n <Flex direction=\"column\" gap={2}>\n {formQuotas.map((q, idx) => (\n <Flex key={idx} gap={2} alignItems=\"center\">\n <Box style={{ flex: 2 }}>\n <TextInput\n placeholder=\"Option key (e.g. h1)\"\n value={q.key}\n onChange={(e: any) => handleQuotaChange(idx, 'key', e.target.value)}\n />\n </Box>\n <Box style={{ flex: 1 }}>\n <TextInput\n type=\"number\"\n placeholder=\"Max\"\n value={String(q.maxAllowed)}\n onChange={(e: any) => handleQuotaChange(idx, 'maxAllowed', e.target.value)}\n />\n </Box>\n <Button\n variant=\"ghost\"\n size=\"S\"\n onClick={() => handleRemoveQuotaRow(idx)}\n disabled={formQuotas.length <= 1}\n >\n ✕\n </Button>\n </Flex>\n ))}\n </Flex>\n </Box>\n </Flex>\n\n {/* Modal Actions */}\n <Flex justifyContent=\"flex-end\" gap={2} marginTop={6}>\n <Button\n variant=\"tertiary\"\n onClick={() => setModalOpen(false)}\n disabled={saving}\n >\n Cancel\n </Button>\n <Button\n variant=\"default\"\n startIcon={<Check />}\n onClick={handleSave}\n loading={saving}\n >\n Save Rule\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n\n {/* Scan Results Modal */}\n {scanModalOpen && scanReport && (\n <Box\n style={{\n position: 'fixed',\n inset: 0,\n backgroundColor: 'rgba(33, 33, 52, 0.65)',\n zIndex: 9999,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Box\n background=\"neutral0\"\n hasRadius\n shadow=\"popupShadow\"\n padding={6}\n style={{ width: '90%', maxWidth: 780, maxHeight: '85vh', overflowY: 'auto' }}\n >\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginBottom={4}>\n <Box>\n <Typography variant=\"beta\" tag=\"h2\" fontWeight=\"bold\">\n Rule Violation Audit: {scanReport.rule?.name}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral600\">\n Target Field: <code>{scanReport.rule?.targetField}</code> • Total Entries Scanned: {scanReport.totalScanned}\n </Typography>\n </Box>\n <Badge\n backgroundColor={scanReport.totalViolations > 0 ? 'danger100' : 'success100'}\n textColor={scanReport.totalViolations > 0 ? 'danger700' : 'success700'}\n size=\"M\"\n >\n {scanReport.totalViolations > 0\n ? `${scanReport.totalViolations} VIOLATION(S) FOUND`\n : '100% COMPLIANT'}\n </Badge>\n </Flex>\n\n {scanReport.totalViolations === 0 ? (\n <Alert variant=\"success\" title=\"No Pre-Existing Violations Detected\" marginBottom={4}>\n All existing documents across your collections adhere strictly to the configured quota limits.\n </Alert>\n ) : (\n <Box>\n <Alert variant=\"danger\" title=\"Legacy Records Found Exceeding Quota\" marginBottom={4}>\n The following {scanReport.totalViolations} record(s) contain more instances of restricted options than currently permitted by this rule.\n </Alert>\n\n <Table colCount={4} rowCount={scanReport.violations.length + 1}>\n <Thead>\n <Tr>\n <Th><Typography variant=\"sigma\">CONTENT TYPE & ENTRY</Typography></Th>\n <Th><Typography variant=\"sigma\">RESTRICTED OPTION</Typography></Th>\n <Th><Typography variant=\"sigma\">COUNT VS LIMIT</Typography></Th>\n <Th style={{ textAlign: 'right' }}><Typography variant=\"sigma\">ACTION</Typography></Th>\n </Tr>\n </Thead>\n <Tbody>\n {scanReport.violations.map((v: any, idx: number) => (\n <Tr key={idx}>\n <Td>\n <Typography variant=\"omega\" fontWeight=\"bold\">\n {v.entryLabel}\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\" display=\"block\">\n Collection: {v.collectionDisplayName}\n </Typography>\n </Td>\n <Td>\n <Badge backgroundColor=\"warning100\" textColor=\"warning700\">\n {v.violatingOption}\n </Badge>\n </Td>\n <Td>\n <Typography variant=\"omega\" textColor=\"danger600\" fontWeight=\"bold\">\n {v.foundCount} used\n </Typography>\n <Typography variant=\"pi\" textColor=\"neutral500\">\n {' '}(Allowed max: {v.maxAllowed})\n </Typography>\n </Td>\n <Td style={{ textAlign: 'right' }}>\n <Button\n variant=\"secondary\"\n size=\"S\"\n onClick={() => window.open(v.editUrl, '_blank')}\n >\n Open in Editor ↗\n </Button>\n </Td>\n </Tr>\n ))}\n </Tbody>\n </Table>\n </Box>\n )}\n\n <Flex justifyContent=\"space-between\" alignItems=\"center\" marginTop={6}>\n {scanReport.totalViolations > 0 ? (\n <Button\n variant=\"secondary\"\n startIcon={<Download />}\n onClick={async () => {\n try {\n const res = await get(`/bulk-updater/csv/export-violations/${scanReport.rule.id}`);\n const csvStr = res.data?.csvContent || (typeof res.data === 'string' ? res.data : '');\n if (!csvStr) {\n toggleNotification({\n type: 'warning',\n message: 'No violation data to export',\n });\n return;\n }\n const safeContent = csvStr.startsWith('\\uFEFF') ? csvStr : '\\uFEFF' + csvStr;\n const blob = new Blob([safeContent], { type: 'text/csv;charset=utf-8;' });\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.setAttribute('download', `violations_${scanReport.rule.id}.csv`);\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n toggleNotification({\n type: 'success',\n message: 'Violations exported to CSV successfully',\n });\n } catch (e: any) {\n toggleNotification({\n type: 'danger',\n message: e.message || 'Failed exporting violations CSV',\n });\n }\n }}\n >\n Export Violations CSV\n </Button>\n ) : (\n <Box />\n )}\n <Button variant=\"default\" onClick={() => setScanModalOpen(false)}>\n Close Report\n </Button>\n </Flex>\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n"],"names":[],"mappings":"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"}
|
package/dist/admin/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const index = {
|
|
|
10
10
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
11
11
|
defaultMessage: "Bulk Attribute Updater"
|
|
12
12
|
},
|
|
13
|
-
Component: () => Promise.resolve().then(() => require("../_chunks/BulkUpdater-
|
|
13
|
+
Component: () => Promise.resolve().then(() => require("../_chunks/BulkUpdater-CWJYmuGU.js")),
|
|
14
14
|
permissions: [],
|
|
15
15
|
position: 3
|
|
16
16
|
});
|
|
@@ -21,7 +21,7 @@ const index = {
|
|
|
21
21
|
defaultMessage: "Bulk Updater Settings"
|
|
22
22
|
},
|
|
23
23
|
to: `${PLUGIN_ID}`,
|
|
24
|
-
Component: () => Promise.resolve().then(() => require("../_chunks/SettingsPage-
|
|
24
|
+
Component: () => Promise.resolve().then(() => require("../_chunks/SettingsPage-BAvuOb7V.js")),
|
|
25
25
|
permissions: []
|
|
26
26
|
});
|
|
27
27
|
app.registerPlugin({
|
package/dist/admin/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ const index = {
|
|
|
9
9
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
10
10
|
defaultMessage: "Bulk Attribute Updater"
|
|
11
11
|
},
|
|
12
|
-
Component: () => import("../_chunks/BulkUpdater-
|
|
12
|
+
Component: () => import("../_chunks/BulkUpdater-Cfig2f7d.mjs"),
|
|
13
13
|
permissions: [],
|
|
14
14
|
position: 3
|
|
15
15
|
});
|
|
@@ -20,7 +20,7 @@ const index = {
|
|
|
20
20
|
defaultMessage: "Bulk Updater Settings"
|
|
21
21
|
},
|
|
22
22
|
to: `${PLUGIN_ID}`,
|
|
23
|
-
Component: () => import("../_chunks/SettingsPage-
|
|
23
|
+
Component: () => import("../_chunks/SettingsPage-BWo4l6Gd.mjs"),
|
|
24
24
|
permissions: []
|
|
25
25
|
});
|
|
26
26
|
app.registerPlugin({
|