1551 lines
54 KiB
JavaScript
1551 lines
54 KiB
JavaScript
import {
|
||
DRAG_DROP_TYPES,
|
||
DragLayerRendered,
|
||
Header,
|
||
Root,
|
||
useReviewWorkflows
|
||
} from "./chunk-HDN4UDJS.js";
|
||
import {
|
||
AVAILABLE_COLORS,
|
||
getStageColorByHex,
|
||
isBaseQueryError
|
||
} from "./chunk-KGPWUC7Q.js";
|
||
import {
|
||
CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME,
|
||
CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME,
|
||
LimitsModal,
|
||
reviewWorkflowsApi,
|
||
useGetContentTypesQuery
|
||
} from "./chunk-E3IW2VDN.js";
|
||
import {
|
||
useTypedSelector
|
||
} from "./chunk-MN3D3XJI.js";
|
||
import "./chunk-C7H2BX76.js";
|
||
import "./chunk-QF6GPHA4.js";
|
||
import {
|
||
getEmptyImage
|
||
} from "./chunk-SYWYLB7I.js";
|
||
import {
|
||
useDrag,
|
||
useDrop
|
||
} from "./chunk-S3HPKOXW.js";
|
||
import "./chunk-JRLAXHTE.js";
|
||
import "./chunk-E4IFZ6ZT.js";
|
||
import "./chunk-QLEKUQKW.js";
|
||
import "./chunk-4J3VOWQV.js";
|
||
import "./chunk-PFI4R5WA.js";
|
||
import {
|
||
useLicenseLimits
|
||
} from "./chunk-G2UWKDMB.js";
|
||
import "./chunk-B3BGMYGX.js";
|
||
import "./chunk-W6ICJ5TB.js";
|
||
import "./chunk-IHYIPMY2.js";
|
||
import "./chunk-UWHSN2C7.js";
|
||
import "./chunk-ERK7O2GM.js";
|
||
import "./chunk-FCIM6RNO.js";
|
||
import "./chunk-J33IXKN4.js";
|
||
import {
|
||
ConfirmDialog
|
||
} from "./chunk-NP53ZCXD.js";
|
||
import "./chunk-MBK4V2X7.js";
|
||
import "./chunk-5ESYXDTN.js";
|
||
import "./chunk-K65KIEAL.js";
|
||
import "./chunk-B7ZLODDO.js";
|
||
import "./chunk-PW7XKCYO.js";
|
||
import "./chunk-RMBEU7DO.js";
|
||
import "./chunk-RI2W2UZ6.js";
|
||
import {
|
||
BackButton
|
||
} from "./chunk-IY256CNP.js";
|
||
import "./chunk-IFOFBKTA.js";
|
||
import {
|
||
create4 as create,
|
||
create5 as create2,
|
||
create6 as create3,
|
||
create7 as create4
|
||
} from "./chunk-XLSIZGJF.js";
|
||
import "./chunk-EGNP2T5O.js";
|
||
import {
|
||
useTracking
|
||
} from "./chunk-GSN7U3BK.js";
|
||
import "./chunk-T3B5F2LV.js";
|
||
import "./chunk-YXDCVYVT.js";
|
||
import "./chunk-QIJGNK42.js";
|
||
import "./chunk-7PUJSL55.js";
|
||
import "./chunk-C2ZJTFO7.js";
|
||
import "./chunk-C75BZXCZ.js";
|
||
import "./chunk-APGTER6B.js";
|
||
import "./chunk-ZM6TT53G.js";
|
||
import {
|
||
MemoizedInputRenderer
|
||
} from "./chunk-6AXVGFVQ.js";
|
||
import {
|
||
Form,
|
||
generateNKeysBetween,
|
||
useField,
|
||
useForm
|
||
} from "./chunk-BFLP6DBI.js";
|
||
import {
|
||
useRBAC
|
||
} from "./chunk-CMLQV3Z2.js";
|
||
import "./chunk-IGCTEXRF.js";
|
||
import "./chunk-TIVRAWTC.js";
|
||
import "./chunk-PQINNV4N.js";
|
||
import "./chunk-VYSYYPOB.js";
|
||
import {
|
||
Page,
|
||
useAPIErrorHandler
|
||
} from "./chunk-5CAWUBTQ.js";
|
||
import "./chunk-W2TBR6J3.js";
|
||
import "./chunk-QEGMJR7H.js";
|
||
import "./chunk-LCL5TIBZ.js";
|
||
import "./chunk-WOQNBAGN.js";
|
||
import "./chunk-BHLYCXQ7.js";
|
||
import "./chunk-76QM3EFM.js";
|
||
import "./chunk-CE4VABH2.js";
|
||
import "./chunk-5VODLFKF.js";
|
||
import {
|
||
useNotification
|
||
} from "./chunk-N55RVBRV.js";
|
||
import {
|
||
Accordion,
|
||
Box,
|
||
Button,
|
||
Dialog,
|
||
Field,
|
||
Flex,
|
||
Grid,
|
||
IconButton,
|
||
Menu,
|
||
MenuItem,
|
||
MultiSelect,
|
||
MultiSelectGroup,
|
||
MultiSelectOption,
|
||
SingleSelect,
|
||
SingleSelectOption,
|
||
TextInput,
|
||
Typography,
|
||
VisuallyHidden,
|
||
useCollator,
|
||
useComposedRefs,
|
||
useIntl
|
||
} from "./chunk-7XB6XSWQ.js";
|
||
import "./chunk-5ZC4PE57.js";
|
||
import {
|
||
useNavigate,
|
||
useParams
|
||
} from "./chunk-TUXTO2Z5.js";
|
||
import "./chunk-FOD4ENRR.js";
|
||
import {
|
||
ForwardRef$1V,
|
||
ForwardRef$1f,
|
||
ForwardRef$3B,
|
||
ForwardRef$3R,
|
||
ForwardRef$3T,
|
||
ForwardRef$4F
|
||
} from "./chunk-WRD5KPDH.js";
|
||
import {
|
||
require_jsx_runtime
|
||
} from "./chunk-NIAJZ5MX.js";
|
||
import {
|
||
dt
|
||
} from "./chunk-ACIMPXWY.js";
|
||
import {
|
||
require_react
|
||
} from "./chunk-MADUDGYZ.js";
|
||
import {
|
||
__toESM
|
||
} from "./chunk-PLDDJCW6.js";
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/id.mjs
|
||
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
||
var React4 = __toESM(require_react(), 1);
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/components/Stages.mjs
|
||
var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
|
||
var React3 = __toESM(require_react(), 1);
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/services/admin.mjs
|
||
var adminApi = reviewWorkflowsApi.injectEndpoints({
|
||
endpoints(builder) {
|
||
return {
|
||
getAdminRoles: builder.query({
|
||
query: () => ({
|
||
url: `/admin/roles`,
|
||
method: "GET"
|
||
}),
|
||
transformResponse: (res) => {
|
||
return res.data;
|
||
}
|
||
})
|
||
};
|
||
}
|
||
});
|
||
var { useGetAdminRolesQuery } = adminApi;
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/hooks/useDragAndDrop.mjs
|
||
var React2 = __toESM(require_react(), 1);
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/hooks/useKeyboardDragAndDrop.mjs
|
||
var React = __toESM(require_react(), 1);
|
||
var useKeyboardDragAndDrop = (active, index, { onCancel, onDropItem, onGrabItem, onMoveItem }) => {
|
||
const [isSelected, setIsSelected] = React.useState(false);
|
||
const handleMove = (movement) => {
|
||
if (!isSelected) {
|
||
return;
|
||
}
|
||
if (typeof index === "number" && onMoveItem) {
|
||
if (movement === "UP") {
|
||
onMoveItem(index - 1, index);
|
||
} else if (movement === "DOWN") {
|
||
onMoveItem(index + 1, index);
|
||
}
|
||
}
|
||
};
|
||
const handleDragClick = () => {
|
||
if (isSelected) {
|
||
if (onDropItem) {
|
||
onDropItem(index);
|
||
}
|
||
setIsSelected(false);
|
||
} else {
|
||
if (onGrabItem) {
|
||
onGrabItem(index);
|
||
}
|
||
setIsSelected(true);
|
||
}
|
||
};
|
||
const handleCancel = () => {
|
||
if (isSelected) {
|
||
setIsSelected(false);
|
||
if (onCancel) {
|
||
onCancel(index);
|
||
}
|
||
}
|
||
};
|
||
const handleKeyDown = (e) => {
|
||
if (!active) {
|
||
return;
|
||
}
|
||
if (e.key === "Tab" && !isSelected) {
|
||
return;
|
||
}
|
||
e.preventDefault();
|
||
switch (e.key) {
|
||
case " ":
|
||
case "Enter":
|
||
handleDragClick();
|
||
break;
|
||
case "Escape":
|
||
handleCancel();
|
||
break;
|
||
case "ArrowDown":
|
||
case "ArrowRight":
|
||
handleMove("DOWN");
|
||
break;
|
||
case "ArrowUp":
|
||
case "ArrowLeft":
|
||
handleMove("UP");
|
||
break;
|
||
}
|
||
};
|
||
return handleKeyDown;
|
||
};
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/hooks/useDragAndDrop.mjs
|
||
var DIRECTIONS = {
|
||
UPWARD: "upward",
|
||
DOWNWARD: "downward"
|
||
};
|
||
var DROP_SENSITIVITY = {
|
||
REGULAR: "regular",
|
||
IMMEDIATE: "immediate"
|
||
};
|
||
var useDragAndDrop = (active, { type = "STRAPI_DND", index, item, onStart, onEnd, onGrabItem, onDropItem, onCancel, onMoveItem, dropSensitivity = DROP_SENSITIVITY.REGULAR }) => {
|
||
const objectRef = React2.useRef(null);
|
||
const [{ handlerId, isOver }, dropRef] = useDrop({
|
||
accept: type,
|
||
collect(monitor) {
|
||
return {
|
||
handlerId: monitor.getHandlerId(),
|
||
isOver: monitor.isOver({
|
||
shallow: true
|
||
})
|
||
};
|
||
},
|
||
drop(item2) {
|
||
const draggedIndex = item2.index;
|
||
const newIndex = index;
|
||
if (isOver && onDropItem) {
|
||
onDropItem(draggedIndex, newIndex);
|
||
}
|
||
},
|
||
hover(item2, monitor) {
|
||
var _a;
|
||
if (!objectRef.current || !onMoveItem) {
|
||
return;
|
||
}
|
||
const dragIndex = item2.index;
|
||
const newIndex = index;
|
||
const hoverBoundingRect = (_a = objectRef.current) == null ? void 0 : _a.getBoundingClientRect();
|
||
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
|
||
const clientOffset = monitor.getClientOffset();
|
||
if (!clientOffset) return;
|
||
const hoverClientY = clientOffset && clientOffset.y - hoverBoundingRect.top;
|
||
if (typeof dragIndex === "number" && typeof newIndex === "number") {
|
||
if (dragIndex === newIndex) {
|
||
return;
|
||
}
|
||
if (dropSensitivity === DROP_SENSITIVITY.REGULAR) {
|
||
if (dragIndex < newIndex && hoverClientY < hoverMiddleY) {
|
||
return;
|
||
}
|
||
if (dragIndex > newIndex && hoverClientY > hoverMiddleY) {
|
||
return;
|
||
}
|
||
}
|
||
onMoveItem(newIndex, dragIndex);
|
||
item2.index = newIndex;
|
||
} else {
|
||
if (Array.isArray(dragIndex) && Array.isArray(newIndex)) {
|
||
const minLength = Math.min(dragIndex.length, newIndex.length);
|
||
let areEqual = true;
|
||
let isLessThan = false;
|
||
let isGreaterThan = false;
|
||
for (let i = 0; i < minLength; i++) {
|
||
if (dragIndex[i] < newIndex[i]) {
|
||
isLessThan = true;
|
||
areEqual = false;
|
||
break;
|
||
} else if (dragIndex[i] > newIndex[i]) {
|
||
isGreaterThan = true;
|
||
areEqual = false;
|
||
break;
|
||
}
|
||
}
|
||
if (areEqual && dragIndex.length === newIndex.length) {
|
||
return;
|
||
}
|
||
if (dropSensitivity === DROP_SENSITIVITY.REGULAR) {
|
||
if (isLessThan && !isGreaterThan && hoverClientY < hoverMiddleY) {
|
||
return;
|
||
}
|
||
if (isGreaterThan && !isLessThan && hoverClientY > hoverMiddleY) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
onMoveItem(newIndex, dragIndex);
|
||
item2.index = newIndex;
|
||
}
|
||
}
|
||
});
|
||
const getDragDirection = (monitor) => {
|
||
if (monitor && monitor.isDragging() && !monitor.didDrop() && monitor.getInitialClientOffset() && monitor.getClientOffset()) {
|
||
const deltaY = monitor.getInitialClientOffset().y - monitor.getClientOffset().y;
|
||
if (deltaY > 0) return DIRECTIONS.UPWARD;
|
||
if (deltaY < 0) return DIRECTIONS.DOWNWARD;
|
||
return null;
|
||
}
|
||
return null;
|
||
};
|
||
const [{ isDragging, direction }, dragRef, dragPreviewRef] = useDrag({
|
||
type,
|
||
item() {
|
||
var _a;
|
||
if (onStart) {
|
||
onStart();
|
||
}
|
||
const { width } = ((_a = objectRef.current) == null ? void 0 : _a.getBoundingClientRect()) ?? {};
|
||
return {
|
||
index,
|
||
width,
|
||
...item
|
||
};
|
||
},
|
||
end() {
|
||
if (onEnd) {
|
||
onEnd();
|
||
}
|
||
},
|
||
canDrag: active,
|
||
/**
|
||
* This is useful when the item is in a virtualized list.
|
||
* However, if we don't have an ID then we want the libraries
|
||
* defaults to take care of this.
|
||
*/
|
||
isDragging: (item == null ? void 0 : item.id) ? (monitor) => {
|
||
return item.id === monitor.getItem().id;
|
||
} : void 0,
|
||
collect: (monitor) => ({
|
||
isDragging: monitor.isDragging(),
|
||
initialOffset: monitor.getInitialClientOffset(),
|
||
currentOffset: monitor.getClientOffset(),
|
||
direction: getDragDirection(monitor)
|
||
})
|
||
});
|
||
const handleKeyDown = useKeyboardDragAndDrop(active, index, {
|
||
onGrabItem,
|
||
onDropItem,
|
||
onCancel,
|
||
onMoveItem
|
||
});
|
||
return [
|
||
{
|
||
handlerId,
|
||
isDragging,
|
||
handleKeyDown,
|
||
isOverDropTarget: isOver,
|
||
direction
|
||
},
|
||
objectRef,
|
||
dropRef,
|
||
dragRef,
|
||
dragPreviewRef
|
||
];
|
||
};
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/components/AddStage.mjs
|
||
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
||
var AddStage = ({ children, ...props }) => {
|
||
return (0, import_jsx_runtime.jsx)(StyledButton, {
|
||
tag: "button",
|
||
background: "neutral0",
|
||
borderColor: "neutral150",
|
||
paddingBottom: 3,
|
||
paddingLeft: 4,
|
||
paddingRight: 4,
|
||
paddingTop: 3,
|
||
shadow: "filterShadow",
|
||
...props,
|
||
children: (0, import_jsx_runtime.jsx)(Typography, {
|
||
variant: "pi",
|
||
fontWeight: "bold",
|
||
children: (0, import_jsx_runtime.jsxs)(Flex, {
|
||
tag: "span",
|
||
gap: 2,
|
||
children: [
|
||
(0, import_jsx_runtime.jsx)(ForwardRef$1f, {
|
||
width: "2.4rem",
|
||
height: "2.4rem",
|
||
"aria-hidden": true
|
||
}),
|
||
children
|
||
]
|
||
})
|
||
})
|
||
});
|
||
};
|
||
var StyledButton = dt(Box)`
|
||
border-radius: 26px;
|
||
color: ${({ theme }) => theme.colors.neutral500};
|
||
|
||
&:hover {
|
||
color: ${({ theme }) => theme.colors.primary600};
|
||
}
|
||
|
||
&:active {
|
||
color: ${({ theme }) => theme.colors.primary600};
|
||
}
|
||
`;
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/components/Stages.mjs
|
||
var Stages = ({ canDelete = true, canUpdate = true, isCreating }) => {
|
||
const { formatMessage } = useIntl();
|
||
const { trackUsage } = useTracking();
|
||
const addFieldRow = useForm("Stages", (state) => state.addFieldRow);
|
||
const { value: stages = [] } = useField("stages");
|
||
return (0, import_jsx_runtime2.jsxs)(Flex, {
|
||
direction: "column",
|
||
gap: 6,
|
||
width: "100%",
|
||
children: [
|
||
(0, import_jsx_runtime2.jsxs)(Box, {
|
||
position: "relative",
|
||
width: "100%",
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(Background, {
|
||
background: "neutral200",
|
||
height: "100%",
|
||
left: "50%",
|
||
position: "absolute",
|
||
top: "0",
|
||
width: 2
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(Flex, {
|
||
direction: "column",
|
||
alignItems: "stretch",
|
||
gap: 6,
|
||
position: "relative",
|
||
tag: "ol",
|
||
children: stages.map((stage, index) => {
|
||
return (0, import_jsx_runtime2.jsx)(Box, {
|
||
tag: "li",
|
||
children: (0, import_jsx_runtime2.jsx)(Stage, {
|
||
index,
|
||
canDelete: stages.length > 1 && canDelete,
|
||
canReorder: stages.length > 1,
|
||
canUpdate,
|
||
stagesCount: stages.length,
|
||
defaultOpen: !stage.id,
|
||
...stage
|
||
})
|
||
}, stage.__temp_key__);
|
||
})
|
||
})
|
||
]
|
||
}),
|
||
canUpdate && (0, import_jsx_runtime2.jsx)(AddStage, {
|
||
type: "button",
|
||
onClick: () => {
|
||
addFieldRow("stages", {
|
||
name: ""
|
||
});
|
||
trackUsage("willCreateStage");
|
||
},
|
||
children: formatMessage({
|
||
id: "Settings.review-workflows.stage.add",
|
||
defaultMessage: "Add new stage"
|
||
})
|
||
})
|
||
]
|
||
});
|
||
};
|
||
var Background = dt(Box)`
|
||
transform: translateX(-50%);
|
||
`;
|
||
var Stage = ({ index, canDelete = false, canReorder = false, canUpdate = false, stagesCount, name, permissions, color, defaultOpen }) => {
|
||
const [liveText, setLiveText] = React3.useState();
|
||
const { formatMessage } = useIntl();
|
||
const { trackUsage } = useTracking();
|
||
const stageErrors = useForm("Stages", (state) => state.errors.stages);
|
||
const error = stageErrors == null ? void 0 : stageErrors[index];
|
||
const addFieldRow = useForm("Stage", (state) => state.addFieldRow);
|
||
const moveFieldRow = useForm("Stage", (state) => state.moveFieldRow);
|
||
const removeFieldRow = useForm("Stage", (state) => state.removeFieldRow);
|
||
const getItemPos = (index2) => `${index2 + 1} of ${stagesCount}`;
|
||
const handleGrabStage = (index2) => {
|
||
setLiveText(formatMessage({
|
||
id: "dnd.grab-item",
|
||
defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
|
||
}, {
|
||
item: name,
|
||
position: getItemPos(index2)
|
||
}));
|
||
};
|
||
const handleDropStage = (index2) => {
|
||
setLiveText(formatMessage({
|
||
id: "dnd.drop-item",
|
||
defaultMessage: `{item}, dropped. Final position in list: {position}.`
|
||
}, {
|
||
item: name,
|
||
position: getItemPos(index2)
|
||
}));
|
||
};
|
||
const handleCancelDragStage = () => {
|
||
setLiveText(formatMessage({
|
||
id: "dnd.cancel-item",
|
||
defaultMessage: "{item}, dropped. Re-order cancelled."
|
||
}, {
|
||
item: name
|
||
}));
|
||
};
|
||
const handleMoveStage = (newIndex, oldIndex) => {
|
||
setLiveText(formatMessage({
|
||
id: "dnd.reorder",
|
||
defaultMessage: "{item}, moved. New position in list: {position}."
|
||
}, {
|
||
item: name,
|
||
position: getItemPos(newIndex)
|
||
}));
|
||
moveFieldRow("stages", oldIndex, newIndex);
|
||
};
|
||
const [{ handlerId, isDragging, handleKeyDown }, stageRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(canReorder, {
|
||
index,
|
||
item: {
|
||
index,
|
||
name
|
||
},
|
||
onGrabItem: handleGrabStage,
|
||
onDropItem: handleDropStage,
|
||
onMoveItem: handleMoveStage,
|
||
onCancel: handleCancelDragStage,
|
||
type: DRAG_DROP_TYPES.STAGE
|
||
});
|
||
const composedRef = useComposedRefs(stageRef, dropRef);
|
||
React3.useEffect(() => {
|
||
dragPreviewRef(getEmptyImage(), {
|
||
captureDraggingState: false
|
||
});
|
||
}, [
|
||
dragPreviewRef,
|
||
index
|
||
]);
|
||
const handleCloneClick = () => {
|
||
addFieldRow("stages", {
|
||
name,
|
||
color,
|
||
permissions
|
||
});
|
||
};
|
||
const id = React3.useId();
|
||
return (0, import_jsx_runtime2.jsxs)(Box, {
|
||
ref: composedRef,
|
||
shadow: "tableShadow",
|
||
children: [
|
||
liveText && (0, import_jsx_runtime2.jsx)(VisuallyHidden, {
|
||
"aria-live": "assertive",
|
||
children: liveText
|
||
}),
|
||
isDragging ? (0, import_jsx_runtime2.jsx)(Box, {
|
||
background: "primary100",
|
||
borderStyle: "dashed",
|
||
borderColor: "primary600",
|
||
borderWidth: "1px",
|
||
display: "block",
|
||
hasRadius: true,
|
||
padding: 6
|
||
}) : (0, import_jsx_runtime2.jsx)(AccordionRoot, {
|
||
onValueChange: (value) => {
|
||
if (value) {
|
||
trackUsage("willEditStage");
|
||
}
|
||
},
|
||
defaultValue: defaultOpen ? id : void 0,
|
||
$error: Object.values(error ?? {}).length > 0,
|
||
children: (0, import_jsx_runtime2.jsxs)(Accordion.Item, {
|
||
value: id,
|
||
children: [
|
||
(0, import_jsx_runtime2.jsxs)(Accordion.Header, {
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(Accordion.Trigger, {
|
||
children: name
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(Accordion.Actions, {
|
||
children: canDelete || canUpdate ? (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, {
|
||
children: [
|
||
(0, import_jsx_runtime2.jsxs)(Menu.Root, {
|
||
children: [
|
||
(0, import_jsx_runtime2.jsxs)(ContextMenuTrigger, {
|
||
size: "S",
|
||
endIcon: null,
|
||
paddingLeft: 2,
|
||
paddingRight: 2,
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(ForwardRef$1V, {
|
||
"aria-hidden": true,
|
||
focusable: false
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(VisuallyHidden, {
|
||
tag: "span",
|
||
children: formatMessage({
|
||
id: "[tbdb].components.DynamicZone.more-actions",
|
||
defaultMessage: "More actions"
|
||
})
|
||
})
|
||
]
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(Menu.Content, {
|
||
popoverPlacement: "bottom-end",
|
||
zIndex: 2,
|
||
children: (0, import_jsx_runtime2.jsxs)(Menu.SubRoot, {
|
||
children: [
|
||
canUpdate && (0, import_jsx_runtime2.jsx)(MenuItem, {
|
||
onClick: handleCloneClick,
|
||
children: formatMessage({
|
||
id: "Settings.review-workflows.stage.delete",
|
||
defaultMessage: "Duplicate stage"
|
||
})
|
||
}),
|
||
canDelete && (0, import_jsx_runtime2.jsx)(DeleteMenuItem, {
|
||
onClick: () => removeFieldRow("stages", index),
|
||
children: formatMessage({
|
||
id: "Settings.review-workflows.stage.delete",
|
||
defaultMessage: "Delete"
|
||
})
|
||
})
|
||
]
|
||
})
|
||
})
|
||
]
|
||
}),
|
||
canUpdate && (0, import_jsx_runtime2.jsx)(IconButton, {
|
||
background: "transparent",
|
||
hasRadius: true,
|
||
variant: "ghost",
|
||
"data-handler-id": handlerId,
|
||
ref: dragRef,
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.stage.drag",
|
||
defaultMessage: "Drag"
|
||
}),
|
||
onClick: (e) => e.stopPropagation(),
|
||
onKeyDown: handleKeyDown,
|
||
children: (0, import_jsx_runtime2.jsx)(ForwardRef$3T, {})
|
||
})
|
||
]
|
||
}) : null
|
||
})
|
||
]
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(Accordion.Content, {
|
||
children: (0, import_jsx_runtime2.jsx)(Grid.Root, {
|
||
gap: 4,
|
||
padding: 6,
|
||
children: [
|
||
{
|
||
disabled: !canUpdate,
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.stage.name.label",
|
||
defaultMessage: "Stage name"
|
||
}),
|
||
name: `stages.${index}.name`,
|
||
required: true,
|
||
size: 6,
|
||
type: "string"
|
||
},
|
||
{
|
||
disabled: !canUpdate,
|
||
label: formatMessage({
|
||
id: "content-manager.reviewWorkflows.stage.color",
|
||
defaultMessage: "Color"
|
||
}),
|
||
name: `stages.${index}.color`,
|
||
required: true,
|
||
size: 6,
|
||
type: "color"
|
||
},
|
||
{
|
||
disabled: !canUpdate,
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.stage.permissions.label",
|
||
defaultMessage: "Roles that can change this stage"
|
||
}),
|
||
name: `stages.${index}.permissions`,
|
||
placeholder: formatMessage({
|
||
id: "Settings.review-workflows.stage.permissions.placeholder",
|
||
defaultMessage: "Select a role"
|
||
}),
|
||
required: true,
|
||
size: 6,
|
||
type: "permissions"
|
||
}
|
||
].map(({ size, ...field }) => (0, import_jsx_runtime2.jsx)(Grid.Item, {
|
||
col: size,
|
||
direction: "column",
|
||
alignItems: "stretch",
|
||
children: (0, import_jsx_runtime2.jsx)(InputRenderer, {
|
||
...field
|
||
})
|
||
}, field.name))
|
||
})
|
||
})
|
||
]
|
||
})
|
||
})
|
||
]
|
||
});
|
||
};
|
||
var AccordionRoot = dt(Accordion.Root)`
|
||
border: 1px solid
|
||
${({ theme, $error }) => $error ? theme.colors.danger600 : theme.colors.neutral200};
|
||
`;
|
||
var DeleteMenuItem = dt(MenuItem)`
|
||
color: ${({ theme }) => theme.colors.danger600};
|
||
`;
|
||
var ContextMenuTrigger = dt(Menu.Trigger)`
|
||
:hover,
|
||
:focus {
|
||
background-color: ${({ theme }) => theme.colors.neutral100};
|
||
}
|
||
|
||
> span {
|
||
font-size: 0;
|
||
}
|
||
`;
|
||
var InputRenderer = (props) => {
|
||
switch (props.type) {
|
||
case "color":
|
||
return (0, import_jsx_runtime2.jsx)(ColorSelector, {
|
||
...props
|
||
});
|
||
case "permissions":
|
||
return (0, import_jsx_runtime2.jsx)(PermissionsField, {
|
||
...props
|
||
});
|
||
default:
|
||
return (0, import_jsx_runtime2.jsx)(MemoizedInputRenderer, {
|
||
...props
|
||
});
|
||
}
|
||
};
|
||
var ColorSelector = ({ disabled, label, name, required }) => {
|
||
const { formatMessage } = useIntl();
|
||
const { value, error, onChange } = useField(name);
|
||
const colorOptions = AVAILABLE_COLORS.map(({ hex, name: name2 }) => ({
|
||
value: hex,
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.stage.color.name",
|
||
defaultMessage: "{name}"
|
||
}, {
|
||
name: name2
|
||
}),
|
||
color: hex
|
||
}));
|
||
const { themeColorName } = getStageColorByHex(value) ?? {};
|
||
return (0, import_jsx_runtime2.jsxs)(Field.Root, {
|
||
error,
|
||
name,
|
||
required,
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(Field.Label, {
|
||
children: label
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(SingleSelect, {
|
||
disabled,
|
||
onChange: (v) => {
|
||
onChange(name, v.toString());
|
||
},
|
||
value: value == null ? void 0 : value.toUpperCase(),
|
||
startIcon: (0, import_jsx_runtime2.jsx)(Flex, {
|
||
tag: "span",
|
||
height: 2,
|
||
background: value,
|
||
borderColor: themeColorName === "neutral0" ? "neutral150" : "transparent",
|
||
hasRadius: true,
|
||
shrink: 0,
|
||
width: 2
|
||
}),
|
||
children: colorOptions.map(({ value: value2, label: label2, color }) => {
|
||
const { themeColorName: themeColorName2 } = getStageColorByHex(color) || {};
|
||
return (0, import_jsx_runtime2.jsx)(SingleSelectOption, {
|
||
value: value2,
|
||
startIcon: (0, import_jsx_runtime2.jsx)(Flex, {
|
||
tag: "span",
|
||
height: 2,
|
||
background: color,
|
||
borderColor: themeColorName2 === "neutral0" ? "neutral150" : "transparent",
|
||
hasRadius: true,
|
||
shrink: 0,
|
||
width: 2
|
||
}),
|
||
children: label2
|
||
}, value2);
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(Field.Error, {})
|
||
]
|
||
});
|
||
};
|
||
var PermissionsField = ({ disabled, name, placeholder, required }) => {
|
||
const { formatMessage } = useIntl();
|
||
const { toggleNotification } = useNotification();
|
||
const [isApplyAllConfirmationOpen, setIsApplyAllConfirmationOpen] = React3.useState(false);
|
||
const { value = [], error, onChange } = useField(name);
|
||
const allStages = useForm("PermissionsField", (state) => state.values.stages);
|
||
const onFormValueChange = useForm("PermissionsField", (state) => state.onChange);
|
||
const rolesErrorCount = React3.useRef(0);
|
||
const { data: roles = [], isLoading, error: getRolesError } = useGetAdminRolesQuery();
|
||
const filteredRoles = (roles == null ? void 0 : roles.filter((role) => role.code !== "strapi-super-admin")) ?? [];
|
||
React3.useEffect(() => {
|
||
if (!isLoading && getRolesError && "status" in getRolesError && getRolesError.status == 403 && rolesErrorCount.current === 0) {
|
||
rolesErrorCount.current = 1;
|
||
toggleNotification({
|
||
blockTransition: true,
|
||
type: "danger",
|
||
message: formatMessage({
|
||
id: "review-workflows.stage.permissions.noPermissions.description",
|
||
defaultMessage: "You don’t have the permission to see roles. Contact your administrator."
|
||
})
|
||
});
|
||
}
|
||
}, [
|
||
formatMessage,
|
||
isLoading,
|
||
roles,
|
||
toggleNotification,
|
||
getRolesError
|
||
]);
|
||
if (!isLoading && filteredRoles.length === 0) {
|
||
return (0, import_jsx_runtime2.jsxs)(Field.Root, {
|
||
name,
|
||
hint: formatMessage({
|
||
id: "Settings.review-workflows.stage.permissions.noPermissions.description",
|
||
defaultMessage: "You don’t have the permission to see roles"
|
||
}),
|
||
required,
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(Field.Label, {
|
||
children: formatMessage({
|
||
id: "Settings.review-workflows.stage.permissions.label",
|
||
defaultMessage: "Roles that can change this stage"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(TextInput, {
|
||
disabled: true,
|
||
placeholder: formatMessage({
|
||
id: "components.NotAllowedInput.text",
|
||
defaultMessage: "No permissions to see this field"
|
||
}),
|
||
startAction: (0, import_jsx_runtime2.jsx)(ForwardRef$3B, {
|
||
fill: "neutral600"
|
||
}),
|
||
type: "text",
|
||
value: ""
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(Field.Hint, {})
|
||
]
|
||
});
|
||
}
|
||
return (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, {
|
||
children: (0, import_jsx_runtime2.jsxs)(Flex, {
|
||
alignItems: "flex-end",
|
||
gap: 3,
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(PermissionWrapper, {
|
||
grow: 1,
|
||
children: (0, import_jsx_runtime2.jsxs)(Field.Root, {
|
||
error,
|
||
name,
|
||
required: true,
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(Field.Label, {
|
||
children: formatMessage({
|
||
id: "Settings.review-workflows.stage.permissions.label",
|
||
defaultMessage: "Roles that can change this stage"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(MultiSelect, {
|
||
disabled,
|
||
onChange: (values) => {
|
||
const permissions = values.map((value2) => ({
|
||
role: parseInt(value2, 10),
|
||
action: "admin::review-workflows.stage.transition"
|
||
}));
|
||
onChange(name, permissions);
|
||
},
|
||
placeholder,
|
||
// The Select component expects strings for values
|
||
value: value.map((permission) => `${permission.role}`),
|
||
withTags: true,
|
||
children: (0, import_jsx_runtime2.jsx)(MultiSelectGroup, {
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.stage.permissions.allRoles.label",
|
||
defaultMessage: "All roles"
|
||
}),
|
||
values: filteredRoles.map((r) => `${r.id}`),
|
||
children: filteredRoles.map((role) => {
|
||
return (0, import_jsx_runtime2.jsx)(NestedOption, {
|
||
value: `${role.id}`,
|
||
children: role.name
|
||
}, role.id);
|
||
})
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(Field.Error, {})
|
||
]
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime2.jsxs)(Dialog.Root, {
|
||
open: isApplyAllConfirmationOpen,
|
||
onOpenChange: setIsApplyAllConfirmationOpen,
|
||
children: [
|
||
(0, import_jsx_runtime2.jsx)(Dialog.Trigger, {
|
||
children: (0, import_jsx_runtime2.jsx)(IconButton, {
|
||
disabled,
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.stage.permissions.apply.label",
|
||
defaultMessage: "Apply to all stages"
|
||
}),
|
||
size: "L",
|
||
children: (0, import_jsx_runtime2.jsx)(ForwardRef$3R, {})
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime2.jsx)(ConfirmDialog, {
|
||
onConfirm: () => {
|
||
onFormValueChange("stages", allStages.map((stage) => ({
|
||
...stage,
|
||
permissions: value
|
||
})));
|
||
setIsApplyAllConfirmationOpen(false);
|
||
toggleNotification({
|
||
type: "success",
|
||
message: formatMessage({
|
||
id: "Settings.review-workflows.page.edit.confirm.stages.permissions.copy.success",
|
||
defaultMessage: "Applied roles to all other stages of the workflow"
|
||
})
|
||
});
|
||
},
|
||
variant: "default",
|
||
children: formatMessage({
|
||
id: "Settings.review-workflows.page.edit.confirm.stages.permissions.copy",
|
||
defaultMessage: "Roles that can change that stage will be applied to all the other stages."
|
||
})
|
||
})
|
||
]
|
||
})
|
||
]
|
||
})
|
||
});
|
||
};
|
||
var NestedOption = dt(MultiSelectOption)`
|
||
padding-left: ${({ theme }) => theme.spaces[7]};
|
||
`;
|
||
var PermissionWrapper = dt(Flex)`
|
||
> * {
|
||
flex-grow: 1;
|
||
}
|
||
`;
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/components/WorkflowAttributes.mjs
|
||
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
||
var WorkflowAttributes = ({ canUpdate = true }) => {
|
||
const { formatMessage } = useIntl();
|
||
return (0, import_jsx_runtime3.jsxs)(Grid.Root, {
|
||
background: "neutral0",
|
||
hasRadius: true,
|
||
gap: 4,
|
||
padding: 6,
|
||
shadow: "tableShadow",
|
||
children: [
|
||
(0, import_jsx_runtime3.jsx)(Grid.Item, {
|
||
col: 6,
|
||
direction: "column",
|
||
alignItems: "stretch",
|
||
children: (0, import_jsx_runtime3.jsx)(MemoizedInputRenderer, {
|
||
disabled: !canUpdate,
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.workflow.name.label",
|
||
defaultMessage: "Workflow Name"
|
||
}),
|
||
name: "name",
|
||
required: true,
|
||
type: "string"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime3.jsx)(Grid.Item, {
|
||
col: 6,
|
||
direction: "column",
|
||
alignItems: "stretch",
|
||
children: (0, import_jsx_runtime3.jsx)(ContentTypesSelector, {
|
||
disabled: !canUpdate
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime3.jsx)(Grid.Item, {
|
||
col: 6,
|
||
direction: "column",
|
||
alignItems: "stretch",
|
||
children: (0, import_jsx_runtime3.jsx)(StageSelector, {
|
||
disabled: !canUpdate
|
||
})
|
||
})
|
||
]
|
||
});
|
||
};
|
||
var ContentTypesSelector = ({ disabled }) => {
|
||
const { formatMessage, locale } = useIntl();
|
||
const { data: contentTypes, isLoading } = useGetContentTypesQuery();
|
||
const { workflows } = useReviewWorkflows();
|
||
const currentWorkflow = useForm("ContentTypesSelector", (state) => state.values);
|
||
const { error, value, onChange } = useField("contentTypes");
|
||
const formatter = useCollator(locale, {
|
||
sensitivity: "base"
|
||
});
|
||
const isDisabled = disabled || isLoading || !contentTypes || contentTypes.collectionType.length === 0 && contentTypes.singleType.length === 0;
|
||
const collectionTypes = ((contentTypes == null ? void 0 : contentTypes.collectionType) ?? []).toSorted((a, b) => formatter.compare(a.info.displayName, b.info.displayName)).map((contentType) => ({
|
||
label: contentType.info.displayName,
|
||
value: contentType.uid
|
||
}));
|
||
const singleTypes = ((contentTypes == null ? void 0 : contentTypes.singleType) ?? []).map((contentType) => ({
|
||
label: contentType.info.displayName,
|
||
value: contentType.uid
|
||
}));
|
||
return (0, import_jsx_runtime3.jsxs)(Field.Root, {
|
||
error,
|
||
name: "contentTypes",
|
||
children: [
|
||
(0, import_jsx_runtime3.jsx)(Field.Label, {
|
||
children: formatMessage({
|
||
id: "Settings.review-workflows.workflow.contentTypes.label",
|
||
defaultMessage: "Associated to"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime3.jsx)(MultiSelect, {
|
||
customizeContent: (value2) => formatMessage({
|
||
id: "Settings.review-workflows.workflow.contentTypes.displayValue",
|
||
defaultMessage: "{count} {count, plural, one {content type} other {content types}} selected"
|
||
}, {
|
||
count: value2 == null ? void 0 : value2.length
|
||
}),
|
||
disabled: isDisabled,
|
||
onChange: (values) => {
|
||
onChange("contentTypes", values);
|
||
},
|
||
value,
|
||
placeholder: formatMessage({
|
||
id: "Settings.review-workflows.workflow.contentTypes.placeholder",
|
||
defaultMessage: "Select"
|
||
}),
|
||
children: [
|
||
...collectionTypes.length > 0 ? [
|
||
{
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.workflow.contentTypes.collectionTypes.label",
|
||
defaultMessage: "Collection Types"
|
||
}),
|
||
children: collectionTypes
|
||
}
|
||
] : [],
|
||
...singleTypes.length > 0 ? [
|
||
{
|
||
label: formatMessage({
|
||
id: "Settings.review-workflows.workflow.contentTypes.singleTypes.label",
|
||
defaultMessage: "Single Types"
|
||
}),
|
||
children: singleTypes
|
||
}
|
||
] : []
|
||
].map((opt) => {
|
||
return (0, import_jsx_runtime3.jsx)(MultiSelectGroup, {
|
||
label: opt.label,
|
||
values: opt.children.map((child) => child.value.toString()),
|
||
children: opt.children.map((child) => {
|
||
const { name: assignedWorkflowName } = (workflows == null ? void 0 : workflows.find((workflow) => (currentWorkflow && workflow.id !== currentWorkflow.id || !currentWorkflow) && workflow.contentTypes.includes(child.value))) ?? {};
|
||
return (0, import_jsx_runtime3.jsx)(NestedOption2, {
|
||
value: child.value,
|
||
children: (0, import_jsx_runtime3.jsx)(Typography, {
|
||
children: (
|
||
// @ts-expect-error - formatMessage options doesn't expect to be a React component but that's what we need actually for the <i> and <em> components
|
||
formatMessage({
|
||
id: "Settings.review-workflows.workflow.contentTypes.assigned.notice",
|
||
defaultMessage: "{label} {name, select, undefined {} other {<i>(assigned to <em>{name}</em> workflow)</i>}}"
|
||
}, {
|
||
label: child.label,
|
||
name: assignedWorkflowName,
|
||
em: (...children) => (0, import_jsx_runtime3.jsx)(Typography, {
|
||
tag: "em",
|
||
fontWeight: "bold",
|
||
children
|
||
}),
|
||
i: (...children) => (0, import_jsx_runtime3.jsx)(ContentTypeTakeNotice, {
|
||
children
|
||
})
|
||
})
|
||
)
|
||
})
|
||
}, child.value);
|
||
})
|
||
}, opt.label);
|
||
})
|
||
})
|
||
]
|
||
});
|
||
};
|
||
var NestedOption2 = dt(MultiSelectOption)`
|
||
padding-left: ${({ theme }) => theme.spaces[7]};
|
||
`;
|
||
var ContentTypeTakeNotice = dt(Typography)`
|
||
font-style: italic;
|
||
`;
|
||
var StageSelector = ({ disabled }) => {
|
||
const { value: stages = [] } = useField("stages");
|
||
const { formatMessage } = useIntl();
|
||
const { error, value, onChange } = useField("stageRequiredToPublish");
|
||
const validStages = stages.filter((stage) => stage.name);
|
||
return (0, import_jsx_runtime3.jsxs)(Field.Root, {
|
||
error,
|
||
name: "stageRequiredToPublish",
|
||
hint: formatMessage({
|
||
id: "settings.review-workflows.workflow.stageRequiredToPublish.hint",
|
||
defaultMessage: "Prevents entries from being published if they are not at the required stage."
|
||
}),
|
||
children: [
|
||
(0, import_jsx_runtime3.jsx)(Field.Label, {
|
||
children: formatMessage({
|
||
id: "settings.review-workflows.workflow.stageRequiredToPublish.label",
|
||
defaultMessage: "Required stage for publishing"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime3.jsxs)(SingleSelect, {
|
||
disabled,
|
||
onChange: (value2) => {
|
||
onChange("stageRequiredToPublish", value2);
|
||
},
|
||
value,
|
||
children: [
|
||
(0, import_jsx_runtime3.jsx)(SingleSelectOption, {
|
||
value: "",
|
||
children: formatMessage({
|
||
id: "settings.review-workflows.workflow.stageRequiredToPublish.any",
|
||
defaultMessage: "Any stage"
|
||
})
|
||
}),
|
||
validStages.map((stage, i) => {
|
||
var _a;
|
||
return (0, import_jsx_runtime3.jsx)(SingleSelectOption, {
|
||
value: ((_a = stage.id) == null ? void 0 : _a.toString()) || stage.__temp_key__,
|
||
children: stage.name
|
||
}, `requiredToPublishStage-${stage.id || stage.__temp_key__}`);
|
||
})
|
||
]
|
||
}),
|
||
(0, import_jsx_runtime3.jsx)(Field.Hint, {})
|
||
]
|
||
});
|
||
};
|
||
|
||
// node_modules/@strapi/review-workflows/dist/admin/routes/settings/id.mjs
|
||
var WORKFLOW_SCHEMA = create3({
|
||
contentTypes: create4().of(create()),
|
||
name: create().max(255, {
|
||
id: "review-workflows.validation.name.max-length",
|
||
defaultMessage: "Name can not be longer than 255 characters"
|
||
}).required().nullable(),
|
||
stages: create4().of(create3().shape({
|
||
name: create().nullable().required({
|
||
id: "review-workflows.validation.stage.name",
|
||
defaultMessage: "Name is required"
|
||
}).max(255, {
|
||
id: "review-workflows.validation.stage.max-length",
|
||
defaultMessage: "Name can not be longer than 255 characters"
|
||
}).test("unique-name", {
|
||
id: "review-workflows.validation.stage.duplicate",
|
||
defaultMessage: "Stage name must be unique"
|
||
}, (stageName, context) => {
|
||
const { stages } = context.from[1].value;
|
||
return stages.filter((stage) => stage.name === stageName).length === 1;
|
||
}),
|
||
color: create().nullable().required({
|
||
id: "review-workflows.validation.stage.color",
|
||
defaultMessage: "Color is required"
|
||
}).matches(/^#(?:[0-9a-fA-F]{3}){1,2}$/i),
|
||
permissions: create4(create3({
|
||
role: create2().strict().typeError({
|
||
id: "review-workflows.validation.stage.permissions.role.number",
|
||
defaultMessage: "Role must be of type number"
|
||
}).required(),
|
||
action: create().required({
|
||
id: "review-workflows.validation.stage.permissions.action.required",
|
||
defaultMessage: "Action is a required argument"
|
||
})
|
||
})).strict()
|
||
})).min(1),
|
||
stageRequiredToPublish: create().nullable()
|
||
});
|
||
var EditPage = () => {
|
||
const { id = "" } = useParams();
|
||
const isCreatingWorkflow = id === "create";
|
||
const { formatMessage } = useIntl();
|
||
const { _unstableFormatValidationErrors: formatValidationErrors } = useAPIErrorHandler();
|
||
const navigate = useNavigate();
|
||
const { toggleNotification } = useNotification();
|
||
const { isLoading: isLoadingWorkflow, meta, workflows, error, update, create: create5 } = useReviewWorkflows();
|
||
const permissions = useTypedSelector((state) => {
|
||
var _a;
|
||
return (_a = state.admin_app.permissions["settings"]) == null ? void 0 : _a["review-workflows"];
|
||
});
|
||
const { allowedActions: { canDelete, canUpdate, canCreate } } = useRBAC(permissions);
|
||
const [savePrompts, setSavePrompts] = React4.useState({});
|
||
const { getFeature, isLoading: isLicenseLoading } = useLicenseLimits();
|
||
const [showLimitModal, setShowLimitModal] = React4.useState(null);
|
||
const currentWorkflow = workflows == null ? void 0 : workflows.find((workflow) => workflow.id === parseInt(id, 10));
|
||
const contentTypesFromOtherWorkflows = workflows == null ? void 0 : workflows.filter((workflow) => workflow.id !== parseInt(id, 10)).flatMap((workflow) => workflow.contentTypes);
|
||
const limits = getFeature("review-workflows");
|
||
const numberOfWorkflows = limits == null ? void 0 : limits[CHARGEBEE_WORKFLOW_ENTITLEMENT_NAME];
|
||
const stagesPerWorkflow = limits == null ? void 0 : limits[CHARGEBEE_STAGES_PER_WORKFLOW_ENTITLEMENT_NAME];
|
||
const submitForm = async (data, helpers) => {
|
||
var _a;
|
||
try {
|
||
const { stageRequiredToPublish, ...rest } = data;
|
||
const stageRequiredToPublishName = stageRequiredToPublish === "" ? null : (_a = rest.stages.find((stage) => stage.id === Number(stageRequiredToPublish) || stage.__temp_key__ === stageRequiredToPublish)) == null ? void 0 : _a.name;
|
||
if (!isCreatingWorkflow) {
|
||
const res = await update(id, {
|
||
...rest,
|
||
// compare permissions of stages and only submit them if at least one has
|
||
// changed; this enables partial updates e.g. for users who don't have
|
||
// permissions to see roles
|
||
stages: rest.stages.map((stage) => {
|
||
var _a2, _b, _c, _d;
|
||
let hasUpdatedPermissions = true;
|
||
const serverStage = (_a2 = currentWorkflow == null ? void 0 : currentWorkflow.stages) == null ? void 0 : _a2.find((serverStage2) => serverStage2.id === (stage == null ? void 0 : stage.id));
|
||
if (serverStage) {
|
||
hasUpdatedPermissions = ((_b = serverStage.permissions) == null ? void 0 : _b.length) !== ((_c = stage.permissions) == null ? void 0 : _c.length) || !((_d = serverStage.permissions) == null ? void 0 : _d.every((serverPermission) => {
|
||
var _a3;
|
||
return !!((_a3 = stage.permissions) == null ? void 0 : _a3.find((permission) => permission.role === serverPermission.role));
|
||
}));
|
||
}
|
||
return {
|
||
...stage,
|
||
permissions: hasUpdatedPermissions ? stage.permissions : void 0
|
||
};
|
||
}),
|
||
stageRequiredToPublishName
|
||
});
|
||
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
||
helpers.setErrors(formatValidationErrors(res.error));
|
||
}
|
||
} else {
|
||
const res = await create5({
|
||
...rest,
|
||
stageRequiredToPublishName
|
||
});
|
||
if ("error" in res && isBaseQueryError(res.error) && res.error.name === "ValidationError") {
|
||
helpers.setErrors(formatValidationErrors(res.error));
|
||
} else if ("data" in res) {
|
||
navigate(`../${res.data.id}`, {
|
||
replace: true
|
||
});
|
||
}
|
||
}
|
||
} catch (error2) {
|
||
toggleNotification({
|
||
type: "danger",
|
||
message: formatMessage({
|
||
id: "notification.error",
|
||
defaultMessage: "An error occurred"
|
||
})
|
||
});
|
||
}
|
||
setSavePrompts({});
|
||
};
|
||
const handleConfirmDeleteDialog = (data, helpers) => async () => {
|
||
await submitForm(data, helpers);
|
||
};
|
||
const handleConfirmClose = () => {
|
||
setSavePrompts({});
|
||
};
|
||
const handleSubmit = async (data, helpers) => {
|
||
const isContentTypeReassignment = data.contentTypes.some((contentType) => contentTypesFromOtherWorkflows == null ? void 0 : contentTypesFromOtherWorkflows.includes(contentType));
|
||
const hasDeletedServerStages = !isCreatingWorkflow && !(currentWorkflow == null ? void 0 : currentWorkflow.stages.every((stage) => data.stages.some((newStage) => newStage.id === stage.id)));
|
||
if (meta && numberOfWorkflows && (meta == null ? void 0 : meta.workflowCount) > parseInt(numberOfWorkflows, 10)) {
|
||
setShowLimitModal("workflow");
|
||
} else if (data.stages && stagesPerWorkflow && data.stages.length > parseInt(stagesPerWorkflow, 10)) {
|
||
setShowLimitModal("stage");
|
||
} else if (hasDeletedServerStages || isContentTypeReassignment) {
|
||
if (hasDeletedServerStages) {
|
||
setSavePrompts((prev) => ({
|
||
...prev,
|
||
hasDeletedServerStages: true
|
||
}));
|
||
}
|
||
if (isContentTypeReassignment) {
|
||
setSavePrompts((prev) => ({
|
||
...prev,
|
||
hasReassignedContentTypes: true
|
||
}));
|
||
}
|
||
} else {
|
||
await submitForm(data, helpers);
|
||
}
|
||
};
|
||
React4.useEffect(() => {
|
||
if (!isLoadingWorkflow && !isLicenseLoading) {
|
||
if (meta && numberOfWorkflows && (meta == null ? void 0 : meta.workflowCount) > parseInt(numberOfWorkflows, 10)) {
|
||
setShowLimitModal("workflow");
|
||
} else if (currentWorkflow && currentWorkflow.stages && stagesPerWorkflow && currentWorkflow.stages.length > parseInt(stagesPerWorkflow, 10)) {
|
||
setShowLimitModal("stage");
|
||
}
|
||
}
|
||
}, [
|
||
currentWorkflow,
|
||
isLicenseLoading,
|
||
isLoadingWorkflow,
|
||
limits,
|
||
meta,
|
||
numberOfWorkflows,
|
||
stagesPerWorkflow
|
||
]);
|
||
const initialValues = React4.useMemo(() => {
|
||
var _a;
|
||
if (isCreatingWorkflow || !currentWorkflow) {
|
||
return {
|
||
name: "",
|
||
stages: [],
|
||
contentTypes: [],
|
||
stageRequiredToPublish: ""
|
||
};
|
||
} else {
|
||
return {
|
||
name: currentWorkflow.name,
|
||
stages: addTmpKeysToStages(currentWorkflow.stages),
|
||
contentTypes: currentWorkflow.contentTypes,
|
||
stageRequiredToPublish: ((_a = currentWorkflow.stageRequiredToPublish) == null ? void 0 : _a.id.toString()) ?? ""
|
||
};
|
||
}
|
||
}, [
|
||
currentWorkflow,
|
||
isCreatingWorkflow
|
||
]);
|
||
if (isLoadingWorkflow) {
|
||
return (0, import_jsx_runtime4.jsx)(Page.Loading, {});
|
||
}
|
||
if (error) {
|
||
return (0, import_jsx_runtime4.jsx)(Page.Error, {});
|
||
}
|
||
return (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, {
|
||
children: [
|
||
(0, import_jsx_runtime4.jsx)(DragLayerRendered, {}),
|
||
(0, import_jsx_runtime4.jsx)(Form, {
|
||
method: isCreatingWorkflow ? "POST" : "PUT",
|
||
initialValues,
|
||
validationSchema: WORKFLOW_SCHEMA,
|
||
onSubmit: handleSubmit,
|
||
children: ({ modified, isSubmitting, values, setErrors }) => {
|
||
var _a;
|
||
return (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, {
|
||
children: [
|
||
(0, import_jsx_runtime4.jsx)(Header, {
|
||
navigationAction: (0, import_jsx_runtime4.jsx)(BackButton, {
|
||
fallback: ".."
|
||
}),
|
||
primaryAction: canUpdate || canCreate ? (0, import_jsx_runtime4.jsx)(Button, {
|
||
startIcon: (0, import_jsx_runtime4.jsx)(ForwardRef$4F, {}),
|
||
type: "submit",
|
||
disabled: !modified || isSubmitting || values.stages.length === 0,
|
||
// if the confirm dialog is open the loading state is on
|
||
// the confirm button already
|
||
loading: !Boolean(Object.keys(savePrompts).length > 0) && isSubmitting,
|
||
children: formatMessage({
|
||
id: "global.save",
|
||
defaultMessage: "Save"
|
||
})
|
||
}) : null,
|
||
subtitle: formatMessage({
|
||
id: "review-workflows.page.subtitle",
|
||
defaultMessage: "{count, plural, one {# stage} other {# stages}}"
|
||
}, {
|
||
count: ((_a = currentWorkflow == null ? void 0 : currentWorkflow.stages) == null ? void 0 : _a.length) ?? 0
|
||
}),
|
||
title: (currentWorkflow == null ? void 0 : currentWorkflow.name) || formatMessage({
|
||
id: "Settings.review-workflows.create.page.title",
|
||
defaultMessage: "Create Review Workflow"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime4.jsx)(Root, {
|
||
children: (0, import_jsx_runtime4.jsxs)(Flex, {
|
||
alignItems: "stretch",
|
||
direction: "column",
|
||
gap: 7,
|
||
children: [
|
||
(0, import_jsx_runtime4.jsx)(WorkflowAttributes, {
|
||
canUpdate: canUpdate || canCreate
|
||
}),
|
||
(0, import_jsx_runtime4.jsx)(Stages, {
|
||
canDelete,
|
||
canUpdate: canUpdate || canCreate,
|
||
isCreating: isCreatingWorkflow
|
||
})
|
||
]
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime4.jsx)(Dialog.Root, {
|
||
open: Object.keys(savePrompts).length > 0,
|
||
onOpenChange: handleConfirmClose,
|
||
children: (0, import_jsx_runtime4.jsx)(ConfirmDialog, {
|
||
onConfirm: handleConfirmDeleteDialog(values, {
|
||
setErrors
|
||
}),
|
||
children: (0, import_jsx_runtime4.jsxs)(Flex, {
|
||
direction: "column",
|
||
gap: 5,
|
||
children: [
|
||
savePrompts.hasDeletedServerStages && (0, import_jsx_runtime4.jsx)(Typography, {
|
||
textAlign: "center",
|
||
variant: "omega",
|
||
children: formatMessage({
|
||
id: "review-workflows.page.delete.confirm.stages.body",
|
||
defaultMessage: "All entries assigned to deleted stages will be moved to the previous stage."
|
||
})
|
||
}),
|
||
savePrompts.hasReassignedContentTypes && (0, import_jsx_runtime4.jsx)(Typography, {
|
||
textAlign: "center",
|
||
variant: "omega",
|
||
children: formatMessage({
|
||
id: "review-workflows.page.delete.confirm.contentType.body",
|
||
defaultMessage: "{count} {count, plural, one {content-type} other {content-types}} {count, plural, one {is} other {are}} already mapped to {count, plural, one {another workflow} other {other workflows}}. If you save changes, {count, plural, one {this} other {these}} {count, plural, one {content-type} other {{count} content-types}} will no more be mapped to the {count, plural, one {another workflow} other {other workflows}} and all corresponding information will be removed."
|
||
}, {
|
||
count: (contentTypesFromOtherWorkflows == null ? void 0 : contentTypesFromOtherWorkflows.filter((contentType) => values.contentTypes.includes(contentType)).length) ?? 0
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime4.jsx)(Typography, {
|
||
textAlign: "center",
|
||
variant: "omega",
|
||
children: formatMessage({
|
||
id: "review-workflows.page.delete.confirm.confirm",
|
||
defaultMessage: "Are you sure you want to save?"
|
||
})
|
||
})
|
||
]
|
||
})
|
||
})
|
||
})
|
||
]
|
||
});
|
||
}
|
||
}),
|
||
(0, import_jsx_runtime4.jsxs)(LimitsModal.Root, {
|
||
open: showLimitModal === "workflow",
|
||
onOpenChange: () => setShowLimitModal(null),
|
||
children: [
|
||
(0, import_jsx_runtime4.jsx)(LimitsModal.Title, {
|
||
children: formatMessage({
|
||
id: "review-workflows.edit.page.workflows.limit.title",
|
||
defaultMessage: "You’ve reached the limit of workflows in your plan"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime4.jsx)(LimitsModal.Body, {
|
||
children: formatMessage({
|
||
id: "review-workflows.edit.page.workflows.limit.body",
|
||
defaultMessage: "Delete a workflow or contact Sales to enable more workflows."
|
||
})
|
||
})
|
||
]
|
||
}),
|
||
(0, import_jsx_runtime4.jsxs)(LimitsModal.Root, {
|
||
open: showLimitModal === "stage",
|
||
onOpenChange: () => setShowLimitModal(null),
|
||
children: [
|
||
(0, import_jsx_runtime4.jsx)(LimitsModal.Title, {
|
||
children: formatMessage({
|
||
id: "review-workflows.edit.page.stages.limit.title",
|
||
defaultMessage: "You have reached the limit of stages for this workflow in your plan"
|
||
})
|
||
}),
|
||
(0, import_jsx_runtime4.jsx)(LimitsModal.Body, {
|
||
children: formatMessage({
|
||
id: "review-workflows.edit.page.stages.limit.body",
|
||
defaultMessage: "Try deleting some stages or contact Sales to enable more stages."
|
||
})
|
||
})
|
||
]
|
||
})
|
||
]
|
||
});
|
||
};
|
||
var addTmpKeysToStages = (data) => {
|
||
const keys = generateNKeysBetween(void 0, void 0, data.length);
|
||
return data.map((datum, index) => ({
|
||
...datum,
|
||
__temp_key__: keys[index]
|
||
}));
|
||
};
|
||
var ProtectedEditPage = () => {
|
||
const permissions = useTypedSelector((state) => {
|
||
var _a;
|
||
const { create: create5 = [], update = [], read = [] } = ((_a = state.admin_app.permissions.settings) == null ? void 0 : _a["review-workflows"]) ?? {};
|
||
return [
|
||
...create5,
|
||
...update,
|
||
...read
|
||
];
|
||
});
|
||
return (0, import_jsx_runtime4.jsx)(Page.Protect, {
|
||
permissions,
|
||
children: (0, import_jsx_runtime4.jsx)(EditPage, {})
|
||
});
|
||
};
|
||
export {
|
||
ProtectedEditPage
|
||
};
|
||
//# sourceMappingURL=id-JP5DTOKM.js.map
|