@nocios/crudify-ui 1.0.36 → 1.0.37

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.
@@ -3,11 +3,12 @@ import type { PolicyAction } from "./constants";
3
3
  type Policy = {
4
4
  id: string;
5
5
  action: PolicyAction;
6
- fields: {
6
+ fields?: {
7
7
  allow: string[];
8
8
  owner_allow: string[];
9
9
  deny: string[];
10
10
  };
11
+ permission?: string;
11
12
  };
12
13
  type FieldErrorMap = string | ({
13
14
  _error?: string;
@@ -22,12 +22,17 @@ const Policies = ({ policies, onChange, availableFields, errors, isSubmitting =
22
22
  const newPolicy = {
23
23
  id: generateId(),
24
24
  action: defaultAction,
25
- fields: {
25
+ };
26
+ if (defaultAction === "delete") {
27
+ newPolicy.permission = "deny";
28
+ }
29
+ else {
30
+ newPolicy.fields = {
26
31
  allow: [],
27
32
  owner_allow: [],
28
33
  deny: availableFields,
29
- },
30
- };
34
+ };
35
+ }
31
36
  const next = [...(policies || []), newPolicy];
32
37
  onChange(next);
33
38
  setTimeout(() => {
@@ -2,11 +2,12 @@ import type { PolicyAction } from "../constants";
2
2
  type Policy = {
3
3
  id: string;
4
4
  action: PolicyAction;
5
- fields: {
5
+ fields?: {
6
6
  allow: string[];
7
7
  owner_allow: string[];
8
8
  deny: string[];
9
9
  };
10
+ permission?: string;
10
11
  };
11
12
  interface PolicyItemProps {
12
13
  policy: Policy;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
3
  import { useTranslation } from "react-i18next";
4
- import { Box, FormControl, InputLabel, Select, MenuItem, IconButton, Typography, FormHelperText, Stack, Paper, Divider, } from "@mui/material";
5
- import { Delete } from "@mui/icons-material";
4
+ import { Box, FormControl, InputLabel, Select, MenuItem, IconButton, Typography, FormHelperText, Stack, Paper, Divider, Button, } from "@mui/material";
5
+ import { Delete, SelectAll, ClearAll } from "@mui/icons-material";
6
6
  import FieldSelector from "../FieldSelector";
7
7
  import { POLICY_ACTIONS } from "../constants";
8
8
  const PolicyItem = forwardRef(({ policy, onChange, onRemove, availableFields, isSubmitting = false, usedActions, error, }, ref) => {
@@ -30,7 +30,17 @@ const PolicyItem = forwardRef(({ policy, onChange, onRemove, availableFields, is
30
30
  backgroundColor: 'rgba(207, 34, 46, 0.1)'
31
31
  }
32
32
  }, children: _jsx(Delete, {}) })] }), _jsxs(Stack, { spacing: 3, children: [_jsx(Stack, { direction: { xs: "column", md: "row" }, spacing: 2, children: _jsx(Box, { sx: { flex: 1, minWidth: 200 }, children: _jsxs(FormControl, { fullWidth: true, children: [_jsx(InputLabel, { children: t("modules.form.publicPolicies.fields.action.label") }), _jsx(Select, { value: policy.action, label: t("modules.form.publicPolicies.fields.action.label"), disabled: isSubmitting, onChange: (e) => {
33
- const next = { ...policy, action: e.target.value };
33
+ const newAction = e.target.value;
34
+ const next = { ...policy, action: newAction };
35
+ // Reset fields/permission based on action type
36
+ if (newAction === "delete") {
37
+ next.permission = "deny";
38
+ delete next.fields;
39
+ }
40
+ else {
41
+ next.fields = { allow: [], owner_allow: [], deny: availableFields };
42
+ delete next.permission;
43
+ }
34
44
  onChange(next);
35
45
  }, sx: {
36
46
  backgroundColor: '#ffffff',
@@ -44,6 +54,29 @@ const PolicyItem = forwardRef(({ policy, onChange, onRemove, availableFields, is
44
54
  }, children: actionOptions.map((option) => {
45
55
  const disabledOption = takenActions.has(option.value);
46
56
  return (_jsx(MenuItem, { value: option.value, disabled: disabledOption, children: option.label }, option.value));
47
- }) }), error && (_jsx(FormHelperText, { error: true, children: error }))] }) }) }), _jsx(FieldSelector, { value: policy.fields, onChange: (nextFields) => onChange({ ...policy, fields: nextFields }), availableFields: availableFields, disabled: isSubmitting }), _jsx(Paper, { variant: "outlined", sx: { p: 2, backgroundColor: '#f9fafb' }, children: _jsxs(Stack, { spacing: 0.5, divider: _jsx(Divider, { sx: { borderColor: '#e5e7eb' } }), children: [_jsxs(Typography, { variant: "body2", sx: { fontFamily: 'monospace', color: 'text.secondary' }, children: [_jsxs(Box, { component: "span", sx: { color: '#16a34a' }, children: [t('modules.form.publicPolicies.fields.conditions.states.allow'), ":"] }), " ", (policy?.fields?.allow || []).join(', ') || '-'] }), _jsxs(Typography, { variant: "body2", sx: { fontFamily: 'monospace', color: 'text.secondary' }, children: [_jsxs(Box, { component: "span", sx: { color: '#0ea5e9' }, children: [t('modules.form.publicPolicies.fields.conditions.states.ownerAllow'), ":"] }), " ", (policy?.fields?.owner_allow || []).join(', ') || '-'] }), _jsxs(Typography, { variant: "body2", sx: { fontFamily: 'monospace', color: 'text.secondary' }, children: [_jsxs(Box, { component: "span", sx: { color: '#dc2626' }, children: [t('modules.form.publicPolicies.fields.conditions.states.deny'), ":"] }), " ", (policy?.fields?.deny || []).join(', ') || '-'] })] }) })] })] }));
57
+ }) }), error && (_jsx(FormHelperText, { error: true, children: error }))] }) }) }), policy.action === "delete" ? (_jsxs(Box, { children: [_jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: t("modules.form.publicPolicies.fields.conditions.label") }), _jsxs(Stack, { direction: "row", spacing: 1, sx: { mb: 3 }, children: [_jsx(Button, { variant: policy.permission === "*" ? 'contained' : 'outlined', startIcon: _jsx(SelectAll, {}), onClick: () => onChange({ ...policy, permission: "*" }), disabled: isSubmitting, size: "small", sx: {
58
+ minWidth: 140,
59
+ whiteSpace: 'nowrap',
60
+ ...(policy.permission === "*" && {
61
+ backgroundColor: '#16a34a',
62
+ '&:hover': { backgroundColor: '#15803d' }
63
+ })
64
+ }, children: t("modules.form.publicPolicies.fields.conditions.allFields") }), _jsx(Button, { variant: policy.permission === "owner" ? 'contained' : 'outlined', onClick: () => onChange({ ...policy, permission: "owner" }), disabled: isSubmitting, size: "small", sx: {
65
+ minWidth: 140,
66
+ whiteSpace: 'nowrap',
67
+ ...(policy.permission === "owner" && {
68
+ backgroundColor: '#0ea5e9',
69
+ '&:hover': { backgroundColor: '#0284c7' }
70
+ })
71
+ }, children: t("modules.form.publicPolicies.fields.conditions.states.ownerAllow") }), _jsx(Button, { variant: policy.permission === "deny" ? 'contained' : 'outlined', startIcon: _jsx(ClearAll, {}), onClick: () => onChange({ ...policy, permission: "deny" }), disabled: isSubmitting, size: "small", sx: {
72
+ minWidth: 140,
73
+ whiteSpace: 'nowrap',
74
+ ...(policy.permission === "deny" && {
75
+ backgroundColor: '#cf222e',
76
+ '&:hover': { backgroundColor: '#bc1f2c' }
77
+ })
78
+ }, children: t("modules.form.publicPolicies.fields.conditions.noFields") })] })] })) : (_jsx(FieldSelector, { value: policy.fields || { allow: [], owner_allow: [], deny: [] }, onChange: (nextFields) => onChange({ ...policy, fields: nextFields }), availableFields: availableFields, disabled: isSubmitting })), _jsx(Paper, { variant: "outlined", sx: { p: 2, backgroundColor: '#f9fafb' }, children: policy.action === "delete" ? (_jsxs(Typography, { variant: "body2", sx: { fontFamily: 'monospace', color: 'text.secondary' }, children: [_jsxs(Box, { component: "span", sx: {
79
+ color: policy.permission === "*" ? '#16a34a' : policy.permission === "owner" ? '#0ea5e9' : '#dc2626'
80
+ }, children: [t('modules.form.publicPolicies.fields.conditions.states.allow'), ":"] }), " ", policy.permission || '-'] })) : (_jsxs(Stack, { spacing: 0.5, divider: _jsx(Divider, { sx: { borderColor: '#e5e7eb' } }), children: [_jsxs(Typography, { variant: "body2", sx: { fontFamily: 'monospace', color: 'text.secondary' }, children: [_jsxs(Box, { component: "span", sx: { color: '#16a34a' }, children: [t('modules.form.publicPolicies.fields.conditions.states.allow'), ":"] }), " ", (policy?.fields?.allow || []).join(', ') || '-'] }), _jsxs(Typography, { variant: "body2", sx: { fontFamily: 'monospace', color: 'text.secondary' }, children: [_jsxs(Box, { component: "span", sx: { color: '#0ea5e9' }, children: [t('modules.form.publicPolicies.fields.conditions.states.ownerAllow'), ":"] }), " ", (policy?.fields?.owner_allow || []).join(', ') || '-'] }), _jsxs(Typography, { variant: "body2", sx: { fontFamily: 'monospace', color: 'text.secondary' }, children: [_jsxs(Box, { component: "span", sx: { color: '#dc2626' }, children: [t('modules.form.publicPolicies.fields.conditions.states.deny'), ":"] }), " ", (policy?.fields?.deny || []).join(', ') || '-'] })] })) })] })] }));
48
81
  });
49
82
  export default PolicyItem;
@@ -1,3 +1,5 @@
1
1
  export declare const POLICY_ACTIONS: readonly ["create", "read", "update", "delete"];
2
2
  export type PolicyAction = typeof POLICY_ACTIONS[number];
3
3
  export declare const PREFERRED_POLICY_ORDER: PolicyAction[];
4
+ export declare const DELETE_PERMISSIONS: readonly ["*", "deny", "owner"];
5
+ export type DeletePermission = typeof DELETE_PERMISSIONS[number];
@@ -5,3 +5,4 @@ export const PREFERRED_POLICY_ORDER = [
5
5
  "update",
6
6
  "delete",
7
7
  ];
8
+ export const DELETE_PERMISSIONS = ["*", "deny", "owner"];
@@ -0,0 +1 @@
1
+ export { default } from "./Policies";
@@ -0,0 +1 @@
1
+ export { default } from "./Policies";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocios/crudify-ui",
3
- "version": "1.0.36",
3
+ "version": "1.0.37",
4
4
  "description": "Biblioteca de componentes UI para Crudify",
5
5
  "author": "Nocios",
6
6
  "type": "module",