import {
useTypedSelector
} from "./chunk-VE2D6HMA.js";
import {
DocumentRBAC,
DynamicZone,
MemoizedBlocksInput,
MemoizedComponentInput,
MemoizedUIDInput,
MemoizedWysiwyg,
NotAllowedInput,
PERMISSIONS,
getDisplayName,
getRelationLabel,
useDocumentRBAC,
useDynamicZone,
useFieldHint,
useLazyComponents
} from "./chunk-GXKJFURG.js";
import {
DocumentStatus,
RelativeTime
} from "./chunk-7FUKGPNR.js";
import "./chunk-NAZM6EA4.js";
import {
COLLECTION_TYPES,
buildValidParams,
prepareTempKeys,
removeFieldsThatDontExistOnSchema,
useDoc,
useDocLayout,
useDocument,
useDocumentLayout,
useGetContentTypeConfigurationQuery
} from "./chunk-UATNJIHQ.js";
import {
contentManagerApi
} from "./chunk-P4VL3IHZ.js";
import "./chunk-HIZVCZYI.js";
import "./chunk-6LY4MOO2.js";
import "./chunk-QF6GPHA4.js";
import "./chunk-SYWYLB7I.js";
import "./chunk-S3HPKOXW.js";
import "./chunk-JRLAXHTE.js";
import "./chunk-E4IFZ6ZT.js";
import "./chunk-QLEKUQKW.js";
import "./chunk-4J3VOWQV.js";
import "./chunk-PFI4R5WA.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-KFLQQE5L.js";
import "./chunk-ED4XR3VQ.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 "./chunk-IY256CNP.js";
import "./chunk-IFOFBKTA.js";
import "./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,
useField,
useForm
} from "./chunk-BFLP6DBI.js";
import {
useRBAC
} from "./chunk-CMLQV3Z2.js";
import "./chunk-D4WYVNVM.js";
import "./chunk-MMOBCIZG.js";
import "./chunk-IGCTEXRF.js";
import {
Layouts
} from "./chunk-TIVRAWTC.js";
import "./chunk-PQINNV4N.js";
import "./chunk-VYSYYPOB.js";
import {
Page
} from "./chunk-5CAWUBTQ.js";
import {
useQueryParams,
useStrapiApp
} from "./chunk-W2TBR6J3.js";
import "./chunk-QEGMJR7H.js";
import {
require_lib,
require_pipe
} from "./chunk-LCL5TIBZ.js";
import "./chunk-WOQNBAGN.js";
import "./chunk-BHLYCXQ7.js";
import {
createContext
} from "./chunk-76QM3EFM.js";
import "./chunk-CE4VABH2.js";
import "./chunk-5VODLFKF.js";
import {
useNotification
} from "./chunk-N55RVBRV.js";
import {
Alert,
Box,
Button,
Dialog,
Divider,
Field,
Flex,
FocusTrap,
Grid,
Link as Link2,
Main,
Portal$1,
TooltipImpl,
Typography,
useIntl
} from "./chunk-7XB6XSWQ.js";
import "./chunk-5ZC4PE57.js";
import {
Link,
NavLink,
Navigate,
useNavigate,
useParams
} from "./chunk-TUXTO2Z5.js";
import "./chunk-FOD4ENRR.js";
import {
ForwardRef$3,
ForwardRef$5j
} 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/content-manager/dist/admin/history/pages/History.mjs
var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
var React4 = __toESM(require_react(), 1);
var import_qs3 = __toESM(require_lib(), 1);
// node_modules/@strapi/content-manager/dist/admin/history/components/VersionContent.mjs
var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
var React2 = __toESM(require_react(), 1);
var import_pipe = __toESM(require_pipe(), 1);
// node_modules/@strapi/content-manager/dist/admin/history/components/VersionInputRenderer.mjs
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
var React = __toESM(require_react(), 1);
var StyledAlert = dt(Alert).attrs({
closeLabel: "Close",
onClose: () => {
},
shadow: "none"
})`
button {
display: none;
}
`;
var LinkEllipsis = dt(Link2)`
display: block;
& > span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
`;
var CustomRelationInput = (props) => {
const { formatMessage } = useIntl();
const field = useField(props.name);
let formattedFieldValue;
if (field) {
formattedFieldValue = Array.isArray(field.value) ? {
results: field.value,
meta: {
missingCount: 0
}
} : field.value;
}
if (!formattedFieldValue || formattedFieldValue.results.length === 0 && formattedFieldValue.meta.missingCount === 0) {
return (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
children: [
(0, import_jsx_runtime.jsx)(Field.Label, {
action: props.labelAction,
children: props.label
}),
(0, import_jsx_runtime.jsx)(Box, {
marginTop: 1,
children: (0, import_jsx_runtime.jsx)(StyledAlert, {
variant: "default",
children: formatMessage({
id: "content-manager.history.content.no-relations",
defaultMessage: "No relations."
})
})
})
]
});
}
const { results, meta } = formattedFieldValue;
return (0, import_jsx_runtime.jsxs)(Box, {
children: [
(0, import_jsx_runtime.jsx)(Field.Label, {
children: props.label
}),
results.length > 0 && (0, import_jsx_runtime.jsx)(Flex, {
direction: "column",
gap: 2,
marginTop: 1,
alignItems: "stretch",
children: results.map((relationData) => {
const { targetModel } = props.attribute;
const href = `../${COLLECTION_TYPES}/${targetModel}/${relationData.documentId}`;
const label = getRelationLabel(relationData, props.mainField);
const isAdminUserRelation = targetModel === "admin::user";
return (0, import_jsx_runtime.jsxs)(Flex, {
paddingTop: 2,
paddingBottom: 2,
paddingLeft: 4,
paddingRight: 4,
hasRadius: true,
borderColor: "neutral200",
background: "neutral150",
justifyContent: "space-between",
children: [
(0, import_jsx_runtime.jsx)(Box, {
minWidth: 0,
paddingTop: 1,
paddingBottom: 1,
paddingRight: 4,
children: (0, import_jsx_runtime.jsx)(TooltipImpl, {
label,
children: isAdminUserRelation ? (0, import_jsx_runtime.jsx)(Typography, {
children: label
}) : (0, import_jsx_runtime.jsx)(LinkEllipsis, {
tag: NavLink,
to: href,
children: label
})
})
}),
(0, import_jsx_runtime.jsx)(DocumentStatus, {
status: relationData.status
})
]
}, relationData.documentId ?? relationData.id);
})
}),
meta.missingCount > 0 && /* @ts-expect-error – we dont need closeLabel */
(0, import_jsx_runtime.jsx)(StyledAlert, {
marginTop: 1,
variant: "warning",
title: formatMessage({
id: "content-manager.history.content.missing-relations.title",
defaultMessage: "{number, plural, =1 {Missing relation} other {{number} missing relations}}"
}, {
number: meta.missingCount
}),
children: formatMessage({
id: "content-manager.history.content.missing-relations.message",
defaultMessage: "{number, plural, =1 {It has} other {They have}} been deleted and can't be restored."
}, {
number: meta.missingCount
})
})
]
});
};
var createInitialValuesForPath = (keyPath, value) => {
const keys = keyPath.split(".");
const root = {};
let node = root;
keys.forEach((key, index) => {
if (key === "__proto__" || key === "constructor") return;
if (index === keys.length - 1) {
node[key] = value;
} else {
node[key] = node[key] || {};
}
node = node[key];
});
return root;
};
var CustomMediaInput = (props) => {
const { value } = useField(props.name);
const results = (value == null ? void 0 : value.results) ?? [];
const meta = (value == null ? void 0 : value.meta) ?? {
missingCount: 0
};
const { formatMessage } = useIntl();
const fields = useStrapiApp("CustomMediaInput", (state) => state.fields);
const MediaLibrary = fields.media;
return (0, import_jsx_runtime.jsxs)(Flex, {
direction: "column",
gap: 2,
alignItems: "stretch",
children: [
(0, import_jsx_runtime.jsx)(Form, {
method: "PUT",
disabled: true,
initialValues: createInitialValuesForPath(props.name, results),
children: (0, import_jsx_runtime.jsx)(MediaLibrary, {
...props,
disabled: true,
multiple: results.length > 1
})
}),
meta.missingCount > 0 && (0, import_jsx_runtime.jsx)(StyledAlert, {
variant: "warning",
closeLabel: "Close",
onClose: () => {
},
title: formatMessage({
id: "content-manager.history.content.missing-assets.title",
defaultMessage: "{number, plural, =1 {Missing asset} other {{number} missing assets}}"
}, {
number: meta.missingCount
}),
children: formatMessage({
id: "content-manager.history.content.missing-assets.message",
defaultMessage: "{number, plural, =1 {It has} other {They have}} been deleted in the Media Library and can't be restored."
}, {
number: meta.missingCount
})
})
]
});
};
var getLabelAction = (labelAction) => {
if (!React.isValidElement(labelAction)) {
return labelAction;
}
const labelActionTitleId = labelAction.props.title.id;
if (labelActionTitleId === "i18n.Field.localized") {
return React.cloneElement(labelAction, {
...labelAction.props,
title: {
id: "history.content.localized",
defaultMessage: "This value is specific to this locale. If you restore this version, the content will not be replaced for other locales."
}
});
}
if (labelActionTitleId === "i18n.Field.not-localized") {
return React.cloneElement(labelAction, {
...labelAction.props,
title: {
id: "history.content.not-localized",
defaultMessage: "This value is common to all locales. If you restore this version and save the changes, the content will be replaced for all locales."
}
});
}
return labelAction;
};
var VersionInputRenderer = ({ visible, hint: providedHint, shouldIgnoreRBAC = false, labelAction, ...props }) => {
const customLabelAction = getLabelAction(labelAction);
const { formatMessage } = useIntl();
const version = useHistoryContext("VersionContent", (state) => state.selectedVersion);
const configuration = useHistoryContext("VersionContent", (state) => state.configuration);
const fieldSizes = useTypedSelector((state) => state["content-manager"].app.fieldSizes);
const { id, components } = useDoc();
const isFormDisabled = useForm("InputRenderer", (state) => state.disabled);
const isInDynamicZone = useDynamicZone("isInDynamicZone", (state) => state.isInDynamicZone);
const canCreateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canCreateFields);
const canReadFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canReadFields);
const canUpdateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUpdateFields);
const canUserAction = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUserAction);
const editableFields = id ? canUpdateFields : canCreateFields;
const readableFields = id ? canReadFields : canCreateFields;
const canUserReadField = canUserAction(props.name, readableFields, props.type);
const canUserEditField = canUserAction(props.name, editableFields, props.type);
const fields = useStrapiApp("InputRenderer", (app) => app.fields);
const { lazyComponentStore } = useLazyComponents(attributeHasCustomFieldProperty(props.attribute) ? [
props.attribute.customField
] : void 0);
const hint = useFieldHint(providedHint, props.attribute);
const { edit: { components: componentsLayout } } = useDocLayout();
if (!visible) {
return null;
}
if (!shouldIgnoreRBAC && !canUserReadField && !isInDynamicZone) {
return (0, import_jsx_runtime.jsx)(NotAllowedInput, {
hint,
...props
});
}
const fieldIsDisabled = !canUserEditField && !isInDynamicZone || props.disabled || isFormDisabled;
const addedAttributes = version.meta.unknownAttributes.added;
if (Object.keys(addedAttributes).includes(props.name)) {
return (0, import_jsx_runtime.jsxs)(Flex, {
direction: "column",
alignItems: "flex-start",
gap: 1,
children: [
(0, import_jsx_runtime.jsx)(Field.Label, {
children: props.label
}),
(0, import_jsx_runtime.jsx)(StyledAlert, {
width: "100%",
closeLabel: "Close",
onClose: () => {
},
variant: "warning",
title: formatMessage({
id: "content-manager.history.content.new-field.title",
defaultMessage: "New field"
}),
children: formatMessage({
id: "content-manager.history.content.new-field.message",
defaultMessage: "This field didn't exist when this version was saved. If you restore this version, it will be empty."
})
})
]
});
}
if (attributeHasCustomFieldProperty(props.attribute)) {
const CustomInput = lazyComponentStore[props.attribute.customField];
if (CustomInput) {
return (0, import_jsx_runtime.jsx)(CustomInput, {
...props,
// @ts-expect-error – TODO: fix this type error in the useLazyComponents hook.
hint,
labelAction: customLabelAction,
disabled: fieldIsDisabled
});
}
return (0, import_jsx_runtime.jsx)(MemoizedInputRenderer, {
...props,
hint,
labelAction: customLabelAction,
// @ts-expect-error – this workaround lets us display that the custom field is missing.
type: props.attribute.customField,
disabled: fieldIsDisabled
});
}
if (props.type === "media") {
return (0, import_jsx_runtime.jsx)(CustomMediaInput, {
...props,
labelAction: customLabelAction,
disabled: fieldIsDisabled
});
}
const addedInputTypes = Object.keys(fields);
if (!attributeHasCustomFieldProperty(props.attribute) && addedInputTypes.includes(props.type)) {
const CustomInput = fields[props.type];
return (0, import_jsx_runtime.jsx)(CustomInput, {
...props,
// @ts-expect-error – TODO: fix this type error in the useLibrary hook.
hint,
labelAction: customLabelAction,
disabled: fieldIsDisabled
});
}
switch (props.type) {
case "blocks":
return (0, import_jsx_runtime.jsx)(MemoizedBlocksInput, {
...props,
hint,
type: props.type,
disabled: fieldIsDisabled
});
case "component":
const { layout } = componentsLayout[props.attribute.component];
const [remainingFieldsLayout] = getRemaingFieldsLayout({
layout: [
layout
],
metadatas: configuration.components[props.attribute.component].metadatas,
fieldSizes,
schemaAttributes: components[props.attribute.component].attributes
});
return (0, import_jsx_runtime.jsx)(MemoizedComponentInput, {
...props,
layout: [
...layout,
...remainingFieldsLayout || []
],
hint,
labelAction: customLabelAction,
disabled: fieldIsDisabled,
children: (inputProps) => (0, import_jsx_runtime.jsx)(VersionInputRenderer, {
...inputProps,
shouldIgnoreRBAC: true
})
});
case "dynamiczone":
return (0, import_jsx_runtime.jsx)(DynamicZone, {
...props,
hint,
labelAction: customLabelAction,
disabled: fieldIsDisabled,
children: (inputProps) => (0, import_jsx_runtime.jsx)(VersionInputRenderer, {
...inputProps,
shouldIgnoreRBAC: true
})
});
case "relation":
return (0, import_jsx_runtime.jsx)(CustomRelationInput, {
...props,
hint,
labelAction: customLabelAction,
disabled: fieldIsDisabled
});
case "richtext":
return (0, import_jsx_runtime.jsx)(MemoizedWysiwyg, {
...props,
hint,
type: props.type,
labelAction: customLabelAction,
disabled: fieldIsDisabled
});
case "uid":
return (0, import_jsx_runtime.jsx)(MemoizedUIDInput, {
...props,
hint,
type: props.type,
labelAction: customLabelAction,
disabled: fieldIsDisabled
});
case "enumeration":
return (0, import_jsx_runtime.jsx)(MemoizedInputRenderer, {
...props,
hint,
labelAction: customLabelAction,
options: props.attribute.enum.map((value) => ({
value
})),
// @ts-expect-error – Temp workaround so we don't forget custom-fields don't work!
type: props.customField ? "custom-field" : props.type,
disabled: fieldIsDisabled
});
default:
const { unique: _unique, mainField: _mainField, ...restProps } = props;
return (0, import_jsx_runtime.jsx)(MemoizedInputRenderer, {
...restProps,
hint,
labelAction: customLabelAction,
// @ts-expect-error – Temp workaround so we don't forget custom-fields don't work!
type: props.customField ? "custom-field" : props.type,
disabled: fieldIsDisabled
});
}
};
var attributeHasCustomFieldProperty = (attribute) => "customField" in attribute && typeof attribute.customField === "string";
// node_modules/@strapi/content-manager/dist/admin/history/components/VersionContent.mjs
var createLayoutFromFields = (fields) => {
return fields.reduce((rows, field) => {
if (field.type === "dynamiczone") {
rows.push([
field
]);
return rows;
}
if (!rows[rows.length - 1]) {
rows.push([]);
}
rows[rows.length - 1].push(field);
return rows;
}, []).map((row) => [
row
]);
};
function getRemaingFieldsLayout({ layout, metadatas, schemaAttributes, fieldSizes }) {
const fieldsInLayout = layout.flatMap((panel) => panel.flatMap((row) => row.flatMap((field) => field.name)));
const remainingFields = Object.entries(metadatas).reduce((currentRemainingFields, [name, field]) => {
if (!fieldsInLayout.includes(name) && field.edit.visible === true) {
const attribute = schemaAttributes[name];
currentRemainingFields.push({
attribute,
type: attribute.type,
visible: true,
disabled: true,
label: field.edit.label || name,
name,
size: fieldSizes[attribute.type].default ?? 12
});
}
return currentRemainingFields;
}, []);
return createLayoutFromFields(remainingFields);
}
var FormPanel = ({ panel }) => {
if (panel.some((row) => row.some((field) => field.type === "dynamiczone"))) {
const [row] = panel;
const [field] = row;
return (0, import_jsx_runtime2.jsx)(Grid.Root, {
gap: 4,
children: (0, import_jsx_runtime2.jsx)(Grid.Item, {
col: 12,
s: 12,
xs: 12,
direction: "column",
alignItems: "stretch",
children: (0, import_jsx_runtime2.jsx)(VersionInputRenderer, {
...field
})
})
}, field.name);
}
return (0, import_jsx_runtime2.jsx)(Box, {
hasRadius: true,
background: "neutral0",
shadow: "tableShadow",
paddingLeft: 6,
paddingRight: 6,
paddingTop: 6,
paddingBottom: 6,
borderColor: "neutral150",
children: (0, import_jsx_runtime2.jsx)(Flex, {
direction: "column",
alignItems: "stretch",
gap: 6,
children: panel.map((row, gridRowIndex) => (0, import_jsx_runtime2.jsx)(Grid.Root, {
gap: 4,
children: row.map(({ size, ...field }) => {
return (0, import_jsx_runtime2.jsx)(Grid.Item, {
col: size,
s: 12,
xs: 12,
direction: "column",
alignItems: "stretch",
children: (0, import_jsx_runtime2.jsx)(VersionInputRenderer, {
...field
})
}, field.name);
})
}, gridRowIndex))
})
});
};
var VersionContent = () => {
const { formatMessage } = useIntl();
const { fieldSizes } = useTypedSelector((state) => state["content-manager"].app);
const version = useHistoryContext("VersionContent", (state) => state.selectedVersion);
const layout = useHistoryContext("VersionContent", (state) => state.layout);
const configuration = useHistoryContext("VersionContent", (state) => state.configuration);
const schema = useHistoryContext("VersionContent", (state) => state.schema);
const removedAttributes = version.meta.unknownAttributes.removed;
const removedAttributesAsFields = Object.entries(removedAttributes).map(([attributeName, attribute]) => {
const field = {
attribute,
shouldIgnoreRBAC: true,
type: attribute.type,
visible: true,
disabled: true,
label: attributeName,
name: attributeName,
size: fieldSizes[attribute.type].default ?? 12
};
return field;
});
const unknownFieldsLayout = createLayoutFromFields(removedAttributesAsFields);
const remainingFieldsLayout = getRemaingFieldsLayout({
metadatas: configuration.contentType.metadatas,
layout,
schemaAttributes: schema.attributes,
fieldSizes
});
const { components } = useDoc();
const transformedData = React2.useMemo(() => {
const transform = (schemaAttributes, components2 = {}) => (document) => {
const schema2 = {
attributes: schemaAttributes
};
const transformations = (0, import_pipe.default)(removeFieldsThatDontExistOnSchema(schema2), prepareTempKeys(schema2, components2));
return transformations(document);
};
return transform(version.schema, components)(version.data);
}, [
components,
version.data,
version.schema
]);
return (0, import_jsx_runtime2.jsxs)(Layouts.Content, {
children: [
(0, import_jsx_runtime2.jsx)(Box, {
paddingBottom: 8,
children: (0, import_jsx_runtime2.jsx)(Form, {
disabled: true,
method: "PUT",
initialValues: transformedData,
children: (0, import_jsx_runtime2.jsx)(Flex, {
direction: "column",
alignItems: "stretch",
gap: 6,
position: "relative",
children: [
...layout,
...remainingFieldsLayout
].map((panel, index) => {
return (0, import_jsx_runtime2.jsx)(FormPanel, {
panel
}, index);
})
})
})
}),
removedAttributesAsFields.length > 0 && (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, {
children: [
(0, import_jsx_runtime2.jsx)(Divider, {}),
(0, import_jsx_runtime2.jsxs)(Box, {
paddingTop: 8,
children: [
(0, import_jsx_runtime2.jsxs)(Flex, {
direction: "column",
alignItems: "flex-start",
paddingBottom: 6,
gap: 1,
children: [
(0, import_jsx_runtime2.jsx)(Typography, {
variant: "delta",
children: formatMessage({
id: "content-manager.history.content.unknown-fields.title",
defaultMessage: "Unknown fields"
})
}),
(0, import_jsx_runtime2.jsx)(Typography, {
variant: "pi",
children: formatMessage({
id: "content-manager.history.content.unknown-fields.message",
defaultMessage: "These fields have been deleted or renamed in the Content-Type Builder. These fields will not be restored."
}, {
b: (chunks) => (0, import_jsx_runtime2.jsx)(Typography, {
variant: "pi",
fontWeight: "bold",
children: chunks
})
})
})
]
}),
(0, import_jsx_runtime2.jsx)(Form, {
disabled: true,
method: "PUT",
initialValues: version.data,
children: (0, import_jsx_runtime2.jsx)(Flex, {
direction: "column",
alignItems: "stretch",
gap: 6,
position: "relative",
children: unknownFieldsLayout.map((panel, index) => {
return (0, import_jsx_runtime2.jsx)(FormPanel, {
panel
}, index);
})
})
})
]
})
]
})
]
});
};
// node_modules/@strapi/content-manager/dist/admin/history/components/VersionHeader.mjs
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
var React3 = __toESM(require_react(), 1);
var import_qs = __toESM(require_lib(), 1);
// node_modules/@strapi/content-manager/dist/admin/history/services/historyVersion.mjs
var historyVersionsApi = contentManagerApi.injectEndpoints({
endpoints: (builder) => ({
getHistoryVersions: builder.query({
query(params) {
return {
url: `/content-manager/history-versions`,
method: "GET",
config: {
params
}
};
},
providesTags: [
"HistoryVersion"
]
}),
restoreVersion: builder.mutation({
query({ params, body }) {
return {
url: `/content-manager/history-versions/${params.versionId}/restore`,
method: "PUT",
data: body
};
},
invalidatesTags: (_res, _error, { documentId, collectionType, params }) => {
return [
"HistoryVersion",
{
type: "Document",
id: collectionType === COLLECTION_TYPES ? `${params.contentType}_${documentId}` : params.contentType
}
];
}
})
})
});
var { useGetHistoryVersionsQuery, useRestoreVersionMutation } = historyVersionsApi;
// node_modules/@strapi/content-manager/dist/admin/history/components/VersionHeader.mjs
var VersionHeader = ({ headerId }) => {
var _a;
const [isConfirmDialogOpen, setIsConfirmDialogOpen] = React3.useState(false);
const navigate = useNavigate();
const { formatMessage, formatDate } = useIntl();
const { trackUsage } = useTracking();
const { toggleNotification } = useNotification();
const [{ query }] = useQueryParams();
const { collectionType, slug } = useParams();
const [restoreVersion, { isLoading }] = useRestoreVersionMutation();
const { allowedActions } = useRBAC(PERMISSIONS.map((action) => ({
action,
subject: slug
})));
const version = useHistoryContext("VersionHeader", (state) => state.selectedVersion);
const mainField = useHistoryContext("VersionHeader", (state) => state.mainField);
const schema = useHistoryContext("VersionHeader", (state) => state.schema);
const isCurrentVersion = useHistoryContext("VersionHeader", (state) => state.page === 1 && state.versions.data[0].id === state.selectedVersion.id);
const mainFieldValue = version.data[mainField];
const getNextNavigation = () => {
const pluginsQueryParams = (0, import_qs.stringify)({
plugins: query.plugins
}, {
encode: false
});
return {
pathname: "..",
search: pluginsQueryParams
};
};
const handleRestore = async () => {
try {
const response = await restoreVersion({
documentId: version.relatedDocumentId,
collectionType,
params: {
versionId: version.id,
contentType: version.contentType
},
body: {
contentType: version.contentType
}
});
if ("data" in response) {
navigate(getNextNavigation(), {
relative: "path"
});
toggleNotification({
type: "success",
title: formatMessage({
id: "content-manager.restore.success.title",
defaultMessage: "Version restored."
}),
message: formatMessage({
id: "content-manager.restore.success.message",
defaultMessage: "A past version of the content was restored."
})
});
trackUsage("didRestoreHistoryVersion");
}
if ("error" in response) {
toggleNotification({
type: "danger",
message: formatMessage({
id: "content-manager.history.restore.error.message",
defaultMessage: "Could not restore version."
})
});
}
} catch (error) {
toggleNotification({
type: "danger",
message: formatMessage({
id: "notification.error",
defaultMessage: "An error occurred"
})
});
}
};
return (0, import_jsx_runtime3.jsxs)(Dialog.Root, {
open: isConfirmDialogOpen,
onOpenChange: setIsConfirmDialogOpen,
children: [
(0, import_jsx_runtime3.jsx)(Layouts.BaseHeader, {
id: headerId,
title: formatDate(new Date(version.createdAt), {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric"
}),
subtitle: (0, import_jsx_runtime3.jsx)(Typography, {
variant: "epsilon",
textColor: "neutral600",
children: formatMessage({
id: "content-manager.history.version.subtitle",
defaultMessage: "{hasLocale, select, true {{subtitle}, in {locale}} other {{subtitle}}}"
}, {
hasLocale: Boolean(version.locale),
subtitle: `${mainFieldValue || ""} (${schema.info.singularName})`.trim(),
locale: (_a = version.locale) == null ? void 0 : _a.name
})
}),
navigationAction: (0, import_jsx_runtime3.jsx)(Link2, {
startIcon: (0, import_jsx_runtime3.jsx)(ForwardRef$5j, {}),
tag: NavLink,
to: getNextNavigation(),
relative: "path",
isExternal: false,
children: formatMessage({
id: "global.back",
defaultMessage: "Back"
})
}),
sticky: false,
primaryAction: (0, import_jsx_runtime3.jsx)(Dialog.Trigger, {
children: (0, import_jsx_runtime3.jsx)(Button, {
disabled: !allowedActions.canUpdate || isCurrentVersion,
onClick: () => {
setIsConfirmDialogOpen(true);
},
children: formatMessage({
id: "content-manager.history.restore.confirm.button",
defaultMessage: "Restore"
})
})
})
}),
(0, import_jsx_runtime3.jsx)(ConfirmDialog, {
onConfirm: handleRestore,
endAction: (0, import_jsx_runtime3.jsx)(Button, {
variant: "secondary",
onClick: handleRestore,
loading: isLoading,
children: formatMessage({
id: "content-manager.history.restore.confirm.button",
defaultMessage: "Restore"
})
}),
children: (0, import_jsx_runtime3.jsxs)(Flex, {
direction: "column",
alignItems: "center",
justifyContent: "center",
gap: 2,
textAlign: "center",
children: [
(0, import_jsx_runtime3.jsx)(Flex, {
justifyContent: "center",
children: (0, import_jsx_runtime3.jsx)(ForwardRef$3, {
width: "24px",
height: "24px",
fill: "danger600"
})
}),
(0, import_jsx_runtime3.jsx)(Typography, {
children: formatMessage({
id: "content-manager.history.restore.confirm.title",
defaultMessage: "Are you sure you want to restore this version?"
})
}),
(0, import_jsx_runtime3.jsx)(Typography, {
children: formatMessage({
id: "content-manager.history.restore.confirm.message",
defaultMessage: "{isDraft, select, true {The restored content will override your draft.} other {The restored content won't be published, it will override the draft and be saved as pending changes. You'll be able to publish the changes at anytime.}}"
}, {
isDraft: version.status === "draft"
})
})
]
})
})
]
});
};
// node_modules/@strapi/content-manager/dist/admin/history/components/VersionsList.mjs
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
var import_react = __toESM(require_react(), 1);
var import_qs2 = __toESM(require_lib(), 1);
var BlueText = (children) => (0, import_jsx_runtime4.jsx)(Typography, {
textColor: "primary600",
variant: "pi",
children
});
var VersionCard = ({ version, isCurrent }) => {
const { formatDate, formatMessage } = useIntl();
const [{ query }] = useQueryParams();
const isActive = query.id === version.id.toString();
const author = version.createdBy && getDisplayName(version.createdBy);
return (0, import_jsx_runtime4.jsxs)(Flex, {
direction: "column",
alignItems: "flex-start",
gap: 3,
hasRadius: true,
borderWidth: "1px",
borderStyle: "solid",
borderColor: isActive ? "primary600" : "neutral200",
color: "neutral800",
padding: 5,
tag: Link,
to: `?${(0, import_qs2.stringify)({
...query,
id: version.id
})}`,
style: {
textDecoration: "none"
},
children: [
(0, import_jsx_runtime4.jsxs)(Flex, {
direction: "column",
gap: 1,
alignItems: "flex-start",
children: [
(0, import_jsx_runtime4.jsx)(Typography, {
tag: "h3",
fontWeight: "semiBold",
children: formatDate(version.createdAt, {
day: "numeric",
month: "numeric",
year: "numeric",
hour: "2-digit",
minute: "2-digit"
})
}),
(0, import_jsx_runtime4.jsx)(Typography, {
tag: "p",
variant: "pi",
textColor: "neutral600",
children: formatMessage({
id: "content-manager.history.sidebar.versionDescription",
defaultMessage: "{distanceToNow}{isAnonymous, select, true {} other { by {author}}}{isCurrent, select, true { (current)} other {}}"
}, {
distanceToNow: (0, import_jsx_runtime4.jsx)(RelativeTime, {
timestamp: new Date(version.createdAt)
}),
author,
isAnonymous: !Boolean(version.createdBy),
isCurrent,
b: BlueText
})
})
]
}),
version.status && (0, import_jsx_runtime4.jsx)(DocumentStatus, {
status: version.status,
size: "XS"
})
]
});
};
var PaginationButton = ({ page, children }) => {
const [{ query }] = useQueryParams();
const { id: _id, ...queryRest } = query;
return (0, import_jsx_runtime4.jsx)(Link, {
to: {
search: (0, import_qs2.stringify)({
...queryRest,
page
})
},
style: {
textDecoration: "none"
},
children: (0, import_jsx_runtime4.jsx)(Typography, {
variant: "omega",
textColor: "primary600",
children
})
});
};
var VersionsList = () => {
const { formatMessage } = useIntl();
const { versions, page } = useHistoryContext("VersionsList", (state) => ({
versions: state.versions,
page: state.page
}));
return (0, import_jsx_runtime4.jsxs)(Flex, {
shrink: 0,
direction: "column",
alignItems: "stretch",
width: "320px",
height: "100vh",
background: "neutral0",
borderColor: "neutral200",
borderWidth: "0 0 0 1px",
borderStyle: "solid",
tag: "aside",
children: [
(0, import_jsx_runtime4.jsxs)(Flex, {
direction: "row",
justifyContent: "space-between",
padding: 4,
borderColor: "neutral200",
borderWidth: "0 0 1px",
borderStyle: "solid",
tag: "header",
children: [
(0, import_jsx_runtime4.jsx)(Typography, {
tag: "h2",
variant: "omega",
fontWeight: "semiBold",
children: formatMessage({
id: "content-manager.history.sidebar.title",
defaultMessage: "Versions"
})
}),
(0, import_jsx_runtime4.jsx)(Box, {
background: "neutral150",
hasRadius: true,
padding: 1,
children: (0, import_jsx_runtime4.jsx)(Typography, {
variant: "sigma",
textColor: "neutral600",
children: versions.meta.pagination.total
})
})
]
}),
(0, import_jsx_runtime4.jsxs)(Box, {
flex: 1,
overflow: "auto",
children: [
versions.meta.pagination.page > 1 && (0, import_jsx_runtime4.jsx)(Box, {
paddingTop: 4,
textAlign: "center",
children: (0, import_jsx_runtime4.jsx)(PaginationButton, {
page: page - 1,
children: formatMessage({
id: "content-manager.history.sidebar.show-newer",
defaultMessage: "Show newer versions"
})
})
}),
(0, import_jsx_runtime4.jsx)(Flex, {
direction: "column",
gap: 3,
padding: 4,
tag: "ul",
alignItems: "stretch",
children: versions.data.map((version, index) => (0, import_jsx_runtime4.jsx)("li", {
"aria-label": formatMessage({
id: "content-manager.history.sidebar.title.version-card.aria-label",
defaultMessage: "Version card"
}),
children: (0, import_jsx_runtime4.jsx)(VersionCard, {
version,
isCurrent: page === 1 && index === 0
})
}, version.id))
}),
versions.meta.pagination.page < versions.meta.pagination.pageCount && (0, import_jsx_runtime4.jsx)(Box, {
paddingBottom: 4,
textAlign: "center",
children: (0, import_jsx_runtime4.jsx)(PaginationButton, {
page: page + 1,
children: formatMessage({
id: "content-manager.history.sidebar.show-older",
defaultMessage: "Show older versions"
})
})
})
]
})
]
});
};
// node_modules/@strapi/content-manager/dist/admin/history/pages/History.mjs
var [HistoryProvider, useHistoryContext] = createContext("HistoryPage");
var HistoryPage = () => {
var _a, _b, _c, _d, _e, _f;
const headerId = React4.useId();
const { formatMessage } = useIntl();
const { slug, id: documentId, collectionType } = useParams();
const { isLoading: isLoadingDocument, schema } = useDocument({
collectionType,
model: slug
});
const { isLoading: isLoadingLayout, edit: { layout, settings: { displayName, mainField } } } = useDocumentLayout(slug);
const { data: configuration, isLoading: isLoadingConfiguration } = useGetContentTypeConfigurationQuery(slug);
const [{ query }] = useQueryParams();
const { id: selectedVersionId, ...queryWithoutId } = query;
const validQueryParamsWithoutId = buildValidParams(queryWithoutId);
const page = validQueryParamsWithoutId.page ? Number(validQueryParamsWithoutId.page) : 1;
const versionsResponse = useGetHistoryVersionsQuery({
contentType: slug,
...documentId ? {
documentId
} : {},
// Omit id since it's not needed by the endpoint and caused extra refetches
...validQueryParamsWithoutId
}, {
refetchOnMountOrArgChange: true
});
const initialRequestId = React4.useRef(versionsResponse.requestId);
const isStaleRequest = versionsResponse.requestId === initialRequestId.current;
if (!slug || collectionType === COLLECTION_TYPES && !documentId) {
return (0, import_jsx_runtime5.jsx)(Navigate, {
to: "/content-manager"
});
}
if (isLoadingDocument || isLoadingLayout || versionsResponse.isFetching || isStaleRequest || isLoadingConfiguration) {
return (0, import_jsx_runtime5.jsx)(Page.Loading, {});
}
if (!versionsResponse.isError && !((_b = (_a = versionsResponse.data) == null ? void 0 : _a.data) == null ? void 0 : _b.length)) {
return (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, {
children: (0, import_jsx_runtime5.jsx)(Page.NoData, {
action: (0, import_jsx_runtime5.jsx)(Link2, {
tag: NavLink,
to: `/content-manager/${collectionType}/${slug}${documentId ? `/${documentId}` : ""}`,
children: formatMessage({
id: "global.back",
defaultMessage: "Back"
})
})
})
});
}
if (((_d = (_c = versionsResponse.data) == null ? void 0 : _c.data) == null ? void 0 : _d.length) && !selectedVersionId) {
return (0, import_jsx_runtime5.jsx)(Navigate, {
to: {
search: (0, import_qs3.stringify)({
...query,
id: versionsResponse.data.data[0].id
})
},
replace: true
});
}
const selectedVersion = (_f = (_e = versionsResponse.data) == null ? void 0 : _e.data) == null ? void 0 : _f.find((version) => version.id.toString() === selectedVersionId);
if (versionsResponse.isError || !layout || !schema || !selectedVersion || !configuration || // This should not happen as it's covered by versionsResponse.isError, but we need it for TS
versionsResponse.data.error) {
return (0, import_jsx_runtime5.jsx)(Page.Error, {});
}
return (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, {
children: [
(0, import_jsx_runtime5.jsx)(Page.Title, {
children: formatMessage({
id: "content-manager.history.page-title",
defaultMessage: "{contentType} history"
}, {
contentType: displayName
})
}),
(0, import_jsx_runtime5.jsx)(HistoryProvider, {
contentType: slug,
id: documentId,
schema,
layout,
configuration,
selectedVersion,
versions: versionsResponse.data,
page,
mainField,
children: (0, import_jsx_runtime5.jsxs)(Flex, {
direction: "row",
alignItems: "flex-start",
children: [
(0, import_jsx_runtime5.jsxs)(Main, {
grow: 1,
height: "100vh",
background: "neutral100",
paddingBottom: 6,
overflow: "auto",
labelledBy: headerId,
children: [
(0, import_jsx_runtime5.jsx)(VersionHeader, {
headerId
}),
(0, import_jsx_runtime5.jsx)(VersionContent, {})
]
}),
(0, import_jsx_runtime5.jsx)(VersionsList, {})
]
})
})
]
});
};
var ProtectedHistoryPageImpl = () => {
const { slug } = useParams();
const { permissions = [], isLoading, error } = useRBAC(PERMISSIONS.map((action) => ({
action,
subject: slug
})));
if (isLoading) {
return (0, import_jsx_runtime5.jsx)(Page.Loading, {});
}
if (error || !slug) {
return (0, import_jsx_runtime5.jsx)(Box, {
height: "100vh",
width: "100vw",
position: "fixed",
top: 0,
left: 0,
zIndex: 2,
background: "neutral0",
children: (0, import_jsx_runtime5.jsx)(Page.Error, {})
});
}
return (0, import_jsx_runtime5.jsx)(Box, {
height: "100vh",
width: "100vw",
position: "fixed",
top: 0,
left: 0,
zIndex: 2,
background: "neutral0",
children: (0, import_jsx_runtime5.jsx)(Page.Protect, {
permissions,
children: ({ permissions: permissions2 }) => (0, import_jsx_runtime5.jsx)(DocumentRBAC, {
permissions: permissions2,
children: (0, import_jsx_runtime5.jsx)(HistoryPage, {})
})
})
});
};
var ProtectedHistoryPage = () => {
return (0, import_jsx_runtime5.jsx)(Portal$1, {
children: (0, import_jsx_runtime5.jsx)(FocusTrap, {
children: (0, import_jsx_runtime5.jsx)(ProtectedHistoryPageImpl, {})
})
});
};
export {
HistoryProvider,
ProtectedHistoryPage,
useHistoryContext
};
//# sourceMappingURL=History-UKPXPR4M.js.map