@webiny/app-headless-cms 6.0.0 → 6.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/components/ContentEntries/SidebarFooter/SidebarFooter.js +1 -3
- package/admin/components/ContentEntries/SidebarFooter/SidebarFooter.js.map +1 -1
- package/admin/components/ContentEntryForm/ContentEntryForm.d.ts +1 -1
- package/admin/components/ContentEntryForm/ContentEntryForm.js.map +1 -1
- package/admin/components/ContentEntryForm/ContentEntryFormPreview.js +8 -2
- package/admin/components/ContentEntryForm/ContentEntryFormPreview.js.map +1 -1
- package/admin/components/ContentEntryForm/ContentEntryFormProvider.d.ts +2 -2
- package/admin/components/ContentEntryForm/ContentEntryFormProvider.js +31 -7
- package/admin/components/ContentEntryForm/ContentEntryFormProvider.js.map +1 -1
- package/admin/components/ContentEntryForm/Header/SaveContent/SaveContent.js +7 -4
- package/admin/components/ContentEntryForm/Header/SaveContent/SaveContent.js.map +1 -1
- package/admin/components/ContentEntryForm/ParentValue.js +1 -1
- package/admin/components/ContentEntryForm/ParentValue.js.map +1 -1
- package/admin/components/ContentModelEditor/ContentModelEditor.js +22 -5
- package/admin/components/ContentModelEditor/ContentModelEditor.js.map +1 -1
- package/admin/components/ContentModelEditor/FieldsSidebar.js +6 -2
- package/admin/components/ContentModelEditor/FieldsSidebar.js.map +1 -1
- package/admin/components/DragPreview.js +4 -2
- package/admin/components/DragPreview.js.map +1 -1
- package/admin/components/DropZone/Center.js +4 -2
- package/admin/components/DropZone/Center.js.map +1 -1
- package/admin/components/DropZone/Horizontal.js +3 -1
- package/admin/components/DropZone/Horizontal.js.map +1 -1
- package/admin/components/DropZone/Vertical.js +3 -1
- package/admin/components/DropZone/Vertical.js.map +1 -1
- package/admin/components/FieldEditor/FieldEditor.js +9 -3
- package/admin/components/FieldEditor/FieldEditor.js.map +1 -1
- package/admin/components/IsModelPublishable.js +3 -6
- package/admin/components/IsModelPublishable.js.map +1 -1
- package/admin/hooks/useIsModelPublishable.d.ts +1 -0
- package/admin/hooks/useIsModelPublishable.js +10 -0
- package/admin/hooks/useIsModelPublishable.js.map +1 -0
- package/admin/menus/HasContentEntryPermissions.d.ts +2 -2
- package/admin/menus/HasContentEntryPermissions.js.map +1 -1
- package/admin/plugins/editor/defaultBar/Name/Name.js +1 -5
- package/admin/plugins/editor/defaultBar/Name/Name.js.map +1 -1
- package/admin/plugins/fieldRenderers/DynamicSection.d.ts +1 -1
- package/admin/plugins/fieldRenderers/DynamicSection.js +1 -1
- package/admin/plugins/fieldRenderers/DynamicSection.js.map +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/MultiValueDynamicZone.d.ts +2 -2
- package/admin/plugins/fieldRenderers/dynamicZone/MultiValueDynamicZone.js.map +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/SingleValueDynamicZone.d.ts +2 -2
- package/admin/plugins/fieldRenderers/dynamicZone/SingleValueDynamicZone.js +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/SingleValueDynamicZone.js.map +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/TemplateIcon.d.ts +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/TemplateIcon.js.map +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/dynamicZoneRenderer.d.ts +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/dynamicZoneRenderer.js +1 -1
- package/admin/plugins/fieldRenderers/dynamicZone/dynamicZoneRenderer.js.map +1 -1
- package/admin/plugins/fieldRenderers/ref/advanced/components/entry/elements/ButtonLink.js +2 -2
- package/admin/plugins/fieldRenderers/ref/advanced/components/entry/elements/ButtonLink.js.map +1 -1
- package/admin/plugins/fieldRenderers/ref/components/NewReferencedEntryDialog.js +8 -2
- package/admin/plugins/fieldRenderers/ref/components/NewReferencedEntryDialog.js.map +1 -1
- package/admin/plugins/icons.js +13 -12
- package/admin/plugins/icons.js.map +1 -1
- package/admin/views/contentEntries/ContentEntriesModule.js +1 -5
- package/admin/views/contentEntries/ContentEntriesModule.js.map +1 -1
- package/admin/views/contentEntries/ContentEntry/FullScreenContentEntry/FullScreenContentEntry.js +2 -9
- package/admin/views/contentEntries/ContentEntry/FullScreenContentEntry/FullScreenContentEntry.js.map +1 -1
- package/admin/views/contentEntries/ContentEntry/FullScreenContentEntry/RevisionListDrawer/RevisionListDrawer.js +1 -2
- package/admin/views/contentEntries/ContentEntry/FullScreenContentEntry/RevisionListDrawer/RevisionListDrawer.js.map +1 -1
- package/admin/views/contentModels/ContentModelsDataList.js +4 -5
- package/admin/views/contentModels/ContentModelsDataList.js.map +1 -1
- package/admin/views/contentModels/fullDelete/FullyDeleteModelDialog.d.ts +1 -1
- package/admin/views/contentModels/fullDelete/FullyDeleteModelDialog.js +2 -2
- package/admin/views/contentModels/fullDelete/FullyDeleteModelDialog.js.map +1 -1
- package/admin/views/contentModels/fullDelete/dialog/state.d.ts +3 -3
- package/admin/views/contentModels/fullDelete/dialog/state.js +13 -9
- package/admin/views/contentModels/fullDelete/dialog/state.js.map +1 -1
- package/admin/views/contentModels/fullDelete/types.d.ts +1 -1
- package/admin/views/contentModels/fullDelete/types.js.map +1 -1
- package/admin/views/contentModels/importing/components/Model/DataListModelItem.js +10 -10
- package/admin/views/contentModels/importing/components/Model/DataListModelItem.js.map +1 -1
- package/package.json +38 -40
- package/admin/components/ContentEntries/Scheduler/actions/ScheduleEntryAction.d.ts +0 -2
- package/admin/components/ContentEntries/Scheduler/actions/ScheduleEntryAction.js +0 -82
- package/admin/components/ContentEntries/Scheduler/actions/ScheduleEntryAction.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/actions/hooks/useGetSchedulerItem.d.ts +0 -11
- package/admin/components/ContentEntries/Scheduler/actions/hooks/useGetSchedulerItem.js +0 -35
- package/admin/components/ContentEntries/Scheduler/actions/hooks/useGetSchedulerItem.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerCancelGraphQLGateway.d.ts +0 -7
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerCancelGraphQLGateway.js +0 -46
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerCancelGraphQLGateway.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerGetGraphQLGateway.d.ts +0 -20
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerGetGraphQLGateway.js +0 -69
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerGetGraphQLGateway.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerListGraphQLGateway.d.ts +0 -7
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerListGraphQLGateway.js +0 -86
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerListGraphQLGateway.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerPublishGraphQLGateway.d.ts +0 -7
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerPublishGraphQLGateway.js +0 -65
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerPublishGraphQLGateway.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerUnpublishGraphQLGateway.d.ts +0 -23
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerUnpublishGraphQLGateway.js +0 -67
- package/admin/components/ContentEntries/Scheduler/adapters/SchedulerUnpublishGraphQLGateway.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/graphql/fields.d.ts +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/graphql/fields.js +0 -20
- package/admin/components/ContentEntries/Scheduler/adapters/graphql/fields.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/index.d.ts +0 -5
- package/admin/components/ContentEntries/Scheduler/adapters/index.js +0 -7
- package/admin/components/ContentEntries/Scheduler/adapters/index.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/adapters/schema/schedulerEntry.d.ts +0 -61
- package/admin/components/ContentEntries/Scheduler/adapters/schema/schedulerEntry.js +0 -26
- package/admin/components/ContentEntries/Scheduler/adapters/schema/schedulerEntry.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/components/ScheduleSidebarButton.d.ts +0 -5
- package/admin/components/ContentEntries/Scheduler/components/ScheduleSidebarButton.js +0 -17
- package/admin/components/ContentEntries/Scheduler/components/ScheduleSidebarButton.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/components/Scheduler.d.ts +0 -2
- package/admin/components/ContentEntries/Scheduler/components/Scheduler.js +0 -54
- package/admin/components/ContentEntries/Scheduler/components/Scheduler.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/components/index.d.ts +0 -1
- package/admin/components/ContentEntries/Scheduler/components/index.js +0 -3
- package/admin/components/ContentEntries/Scheduler/components/index.js.map +0 -1
- package/admin/components/ContentEntries/Scheduler/index.d.ts +0 -1
- package/admin/components/ContentEntries/Scheduler/index.js +0 -3
- package/admin/components/ContentEntries/Scheduler/index.js.map +0 -1
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { TrashBin } from "../TrashBin/index.js";
|
|
3
|
-
import { Scheduler } from "../Scheduler/index.js";
|
|
4
3
|
import { makeDecoratable } from "@webiny/react-composition";
|
|
5
|
-
import { IsModelPublishable } from "../../../../exports/admin/cms.js";
|
|
6
4
|
export const SidebarFooter = makeDecoratable(({
|
|
7
5
|
children
|
|
8
6
|
}) => {
|
|
9
7
|
return /*#__PURE__*/React.createElement("div", {
|
|
10
8
|
className: "px-xs py-sm bg-neutral-base"
|
|
11
|
-
}, /*#__PURE__*/React.createElement(
|
|
9
|
+
}, /*#__PURE__*/React.createElement(TrashBin, null), children);
|
|
12
10
|
});
|
|
13
11
|
|
|
14
12
|
//# sourceMappingURL=SidebarFooter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","TrashBin","
|
|
1
|
+
{"version":3,"names":["React","TrashBin","makeDecoratable","SidebarFooter","children","createElement","className"],"sources":["SidebarFooter.tsx"],"sourcesContent":["import React from \"react\";\nimport { TrashBin } from \"~/admin/components/ContentEntries/TrashBin/index.js\";\nimport { makeDecoratable } from \"@webiny/react-composition\";\n\nexport interface ISidebarFooterProps {\n children?: React.ReactNode;\n}\n\nexport const SidebarFooter = makeDecoratable(({ children }: ISidebarFooterProps) => {\n return (\n <div className={\"px-xs py-sm bg-neutral-base\"}>\n <TrashBin />\n {children}\n </div>\n );\n});\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,QAAQ;AACjB,SAASC,eAAe,QAAQ,2BAA2B;AAM3D,OAAO,MAAMC,aAAa,GAAGD,eAAe,CAAC,CAAC;EAAEE;AAA8B,CAAC,KAAK;EAChF,oBACIJ,KAAA,CAAAK,aAAA;IAAKC,SAAS,EAAE;EAA8B,gBAC1CN,KAAA,CAAAK,aAAA,CAACJ,QAAQ,MAAE,CAAC,EACXG,QACA,CAAC;AAEd,CAAC,CAAC","ignoreList":[]}
|
|
@@ -3,7 +3,7 @@ import type { FormOnSubmit, FormValidation } from "@webiny/form";
|
|
|
3
3
|
import type { CmsContentEntry } from "../../../types.js";
|
|
4
4
|
import type { ContentEntryFormContext, PersistEntry } from "./ContentEntryFormProvider.js";
|
|
5
5
|
export interface ContentEntryFormProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onChange"> {
|
|
6
|
-
entry: Partial<CmsContentEntry>;
|
|
6
|
+
entry: Partial<Omit<CmsContentEntry, "values">> & Pick<CmsContentEntry, "values">;
|
|
7
7
|
/**
|
|
8
8
|
* This callback is executed when an entry, or a revision, are created.
|
|
9
9
|
* @param entry
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","useRef","makeDecoratable","ModelProvider","useModel","useFormRenderer","ContentEntryFormProvider","CustomLayout","DefaultLayout","useGoToRevision","ContentEntryForm","entry","persistEntry","onChange","onInvalidFields","onAfterCreate","setSaveEntry","header","props","formElementRef","model","goToRevision","formRenderer","defaultOnAfterCreate","id","current","setTimeout","scrollTo","isBeingDeleted","createElement","Fragment","confirmNavigationIfDirty","Object","assign","ref"],"sources":["ContentEntryForm.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport type { FormOnSubmit, FormValidation } from \"@webiny/form\";\nimport { makeDecoratable } from \"@webiny/app-admin\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { ModelProvider, useModel } from \"~/admin/components/ModelProvider/index.js\";\nimport { useFormRenderer } from \"~/admin/components/ContentEntryForm/useFormRenderer.js\";\nimport type { ContentEntryFormContext, PersistEntry } from \"./ContentEntryFormProvider.js\";\nimport { ContentEntryFormProvider } from \"./ContentEntryFormProvider.js\";\nimport { CustomLayout } from \"./CustomLayout.js\";\nimport { DefaultLayout } from \"./DefaultLayout.js\";\nimport { useGoToRevision } from \"~/admin/components/ContentEntryForm/useGoToRevision.js\";\n\nexport interface ContentEntryFormProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n entry: Partial<CmsContentEntry>;\n /**\n * This callback is executed when an entry, or a revision, are created.\n * @param entry\n */\n onAfterCreate?: (entry: CmsContentEntry) => void;\n /**\n * This callback is executed when the form is valid, and it needs to persist the content entry.\n */\n persistEntry: PersistEntry;\n onChange?: FormOnSubmit<Partial<CmsContentEntry>>;\n onInvalidFields?: (invalidFields: FormValidation) => void;\n header?: React.ReactNode;\n /**\n * This prop is used to get a reference to `saveEntry` callback, so it can be triggered by components\n * outside the ContentEntryForm context.\n * TODO: introduce a `layout` prop to be able to mount arbitrary components around the entry form, within the context.\n */\n setSaveEntry?: (cb: ContentEntryFormContext[\"saveEntry\"]) => void;\n}\n\nexport const ContentEntryForm = makeDecoratable(\n \"ContentEntryForm\",\n ({\n entry,\n persistEntry,\n onChange,\n onInvalidFields,\n onAfterCreate,\n setSaveEntry,\n header = true,\n ...props\n }: ContentEntryFormProps) => {\n const formElementRef = useRef<HTMLDivElement>(null);\n const { model } = useModel();\n const { goToRevision } = useGoToRevision();\n const formRenderer = useFormRenderer(model);\n\n const defaultOnAfterCreate = (entry: CmsContentEntry) => {\n goToRevision(entry.id);\n };\n\n // When entry changes, scroll to the top of the form.\n useEffect(() => {\n if (!formElementRef.current) {\n return;\n }\n\n setTimeout(() => {\n formElementRef.current?.scrollTo(0, 0);\n }, 20);\n }, [entry.id, formElementRef.current]);\n\n if (model.isBeingDeleted) {\n return <>Model is being deleted.</>;\n }\n\n return (\n <ContentEntryFormProvider\n model={model}\n entry={entry}\n onChange={onChange}\n onInvalidFields={onInvalidFields}\n onAfterCreate={onAfterCreate || defaultOnAfterCreate}\n setSaveEntry={setSaveEntry}\n confirmNavigationIfDirty={true}\n persistEntry={persistEntry}\n >\n <ModelProvider model={model}>\n {header ? header : null}\n <div\n {...props}\n id={\"cms-content-form\"}\n data-element={\"cms-content-form\"}\n data-testid={\"cms-content-form\"}\n ref={formElementRef}\n >\n {formRenderer ? (\n <CustomLayout model={model} formRenderer={formRenderer} />\n ) : (\n <DefaultLayout model={model} />\n )}\n </div>\n </ModelProvider>\n </ContentEntryFormProvider>\n );\n }\n);\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAEhD,SAASC,eAAe,QAAQ,mBAAmB;AAEnD,SAASC,aAAa,EAAEC,QAAQ;AAChC,SAASC,eAAe;AAExB,SAASC,wBAAwB;AACjC,SAASC,YAAY;AACrB,SAASC,aAAa;AACtB,SAASC,eAAe;AAyBxB,OAAO,MAAMC,gBAAgB,GAAGR,eAAe,CAC3C,kBAAkB,EAClB,CAAC;EACGS,KAAK;EACLC,YAAY;EACZC,QAAQ;EACRC,eAAe;EACfC,aAAa;EACbC,YAAY;EACZC,MAAM,GAAG,IAAI;EACb,GAAGC;AACgB,CAAC,KAAK;EACzB,MAAMC,cAAc,GAAGlB,MAAM,CAAiB,IAAI,CAAC;EACnD,MAAM;IAAEmB;EAAM,CAAC,GAAGhB,QAAQ,CAAC,CAAC;EAC5B,MAAM;IAAEiB;EAAa,CAAC,GAAGZ,eAAe,CAAC,CAAC;EAC1C,MAAMa,YAAY,GAAGjB,eAAe,CAACe,KAAK,CAAC;EAE3C,MAAMG,oBAAoB,GAAIZ,KAAsB,IAAK;IACrDU,YAAY,CAACV,KAAK,CAACa,EAAE,CAAC;EAC1B,CAAC;;EAED;EACAxB,SAAS,CAAC,MAAM;IACZ,IAAI,CAACmB,cAAc,CAACM,OAAO,EAAE;MACzB;IACJ;IAEAC,UAAU,CAAC,MAAM;MACbP,cAAc,CAACM,OAAO,EAAEE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,EAAE,EAAE,CAAC;EACV,CAAC,EAAE,CAAChB,KAAK,CAACa,EAAE,EAAEL,cAAc,CAACM,OAAO,CAAC,CAAC;EAEtC,IAAIL,KAAK,CAACQ,cAAc,EAAE;IACtB,oBAAO7B,KAAA,CAAA8B,aAAA,CAAA9B,KAAA,CAAA+B,QAAA,QAAE,yBAAyB,CAAC;EACvC;EAEA,oBACI/B,KAAA,CAAA8B,aAAA,CAACvB,wBAAwB;IACrBc,KAAK,EAAEA,KAAM;IACbT,KAAK,EAAEA,KAAM;IACbE,QAAQ,EAAEA,QAAS;IACnBC,eAAe,EAAEA,eAAgB;IACjCC,aAAa,EAAEA,aAAa,IAAIQ,oBAAqB;IACrDP,YAAY,EAAEA,YAAa;IAC3Be,wBAAwB,EAAE,IAAK;IAC/BnB,YAAY,EAAEA;EAAa,gBAE3Bb,KAAA,CAAA8B,aAAA,CAAC1B,aAAa;IAACiB,KAAK,EAAEA;EAAM,GACvBH,MAAM,GAAGA,MAAM,GAAG,IAAI,eACvBlB,KAAA,CAAA8B,aAAA,QAAAG,MAAA,CAAAC,MAAA,KACQf,KAAK;IACTM,EAAE,EAAE,kBAAmB;IACvB,gBAAc,kBAAmB;IACjC,eAAa,kBAAmB;IAChCU,GAAG,EAAEf;EAAe,IAEnBG,YAAY,gBACTvB,KAAA,CAAA8B,aAAA,CAACtB,YAAY;IAACa,KAAK,EAAEA,KAAM;IAACE,YAAY,EAAEA;EAAa,CAAE,CAAC,gBAE1DvB,KAAA,CAAA8B,aAAA,CAACrB,aAAa;IAACY,KAAK,EAAEA;EAAM,CAAE,CAEjC,CACM,CACO,CAAC;AAEnC,CACJ,CAAC","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["React","useEffect","useRef","makeDecoratable","ModelProvider","useModel","useFormRenderer","ContentEntryFormProvider","CustomLayout","DefaultLayout","useGoToRevision","ContentEntryForm","entry","persistEntry","onChange","onInvalidFields","onAfterCreate","setSaveEntry","header","props","formElementRef","model","goToRevision","formRenderer","defaultOnAfterCreate","id","current","setTimeout","scrollTo","isBeingDeleted","createElement","Fragment","confirmNavigationIfDirty","Object","assign","ref"],"sources":["ContentEntryForm.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport type { FormOnSubmit, FormValidation } from \"@webiny/form\";\nimport { makeDecoratable } from \"@webiny/app-admin\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { ModelProvider, useModel } from \"~/admin/components/ModelProvider/index.js\";\nimport { useFormRenderer } from \"~/admin/components/ContentEntryForm/useFormRenderer.js\";\nimport type { ContentEntryFormContext, PersistEntry } from \"./ContentEntryFormProvider.js\";\nimport { ContentEntryFormProvider } from \"./ContentEntryFormProvider.js\";\nimport { CustomLayout } from \"./CustomLayout.js\";\nimport { DefaultLayout } from \"./DefaultLayout.js\";\nimport { useGoToRevision } from \"~/admin/components/ContentEntryForm/useGoToRevision.js\";\n\nexport interface ContentEntryFormProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, \"onChange\"> {\n entry: Partial<Omit<CmsContentEntry, \"values\">> & Pick<CmsContentEntry, \"values\">;\n /**\n * This callback is executed when an entry, or a revision, are created.\n * @param entry\n */\n onAfterCreate?: (entry: CmsContentEntry) => void;\n /**\n * This callback is executed when the form is valid, and it needs to persist the content entry.\n */\n persistEntry: PersistEntry;\n onChange?: FormOnSubmit<Partial<CmsContentEntry>>;\n onInvalidFields?: (invalidFields: FormValidation) => void;\n header?: React.ReactNode;\n /**\n * This prop is used to get a reference to `saveEntry` callback, so it can be triggered by components\n * outside the ContentEntryForm context.\n * TODO: introduce a `layout` prop to be able to mount arbitrary components around the entry form, within the context.\n */\n setSaveEntry?: (cb: ContentEntryFormContext[\"saveEntry\"]) => void;\n}\n\nexport const ContentEntryForm = makeDecoratable(\n \"ContentEntryForm\",\n ({\n entry,\n persistEntry,\n onChange,\n onInvalidFields,\n onAfterCreate,\n setSaveEntry,\n header = true,\n ...props\n }: ContentEntryFormProps) => {\n const formElementRef = useRef<HTMLDivElement>(null);\n const { model } = useModel();\n const { goToRevision } = useGoToRevision();\n const formRenderer = useFormRenderer(model);\n\n const defaultOnAfterCreate = (entry: CmsContentEntry) => {\n goToRevision(entry.id);\n };\n\n // When entry changes, scroll to the top of the form.\n useEffect(() => {\n if (!formElementRef.current) {\n return;\n }\n\n setTimeout(() => {\n formElementRef.current?.scrollTo(0, 0);\n }, 20);\n }, [entry.id, formElementRef.current]);\n\n if (model.isBeingDeleted) {\n return <>Model is being deleted.</>;\n }\n\n return (\n <ContentEntryFormProvider\n model={model}\n entry={entry}\n onChange={onChange}\n onInvalidFields={onInvalidFields}\n onAfterCreate={onAfterCreate || defaultOnAfterCreate}\n setSaveEntry={setSaveEntry}\n confirmNavigationIfDirty={true}\n persistEntry={persistEntry}\n >\n <ModelProvider model={model}>\n {header ? header : null}\n <div\n {...props}\n id={\"cms-content-form\"}\n data-element={\"cms-content-form\"}\n data-testid={\"cms-content-form\"}\n ref={formElementRef}\n >\n {formRenderer ? (\n <CustomLayout model={model} formRenderer={formRenderer} />\n ) : (\n <DefaultLayout model={model} />\n )}\n </div>\n </ModelProvider>\n </ContentEntryFormProvider>\n );\n }\n);\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAEhD,SAASC,eAAe,QAAQ,mBAAmB;AAEnD,SAASC,aAAa,EAAEC,QAAQ;AAChC,SAASC,eAAe;AAExB,SAASC,wBAAwB;AACjC,SAASC,YAAY;AACrB,SAASC,aAAa;AACtB,SAASC,eAAe;AAyBxB,OAAO,MAAMC,gBAAgB,GAAGR,eAAe,CAC3C,kBAAkB,EAClB,CAAC;EACGS,KAAK;EACLC,YAAY;EACZC,QAAQ;EACRC,eAAe;EACfC,aAAa;EACbC,YAAY;EACZC,MAAM,GAAG,IAAI;EACb,GAAGC;AACgB,CAAC,KAAK;EACzB,MAAMC,cAAc,GAAGlB,MAAM,CAAiB,IAAI,CAAC;EACnD,MAAM;IAAEmB;EAAM,CAAC,GAAGhB,QAAQ,CAAC,CAAC;EAC5B,MAAM;IAAEiB;EAAa,CAAC,GAAGZ,eAAe,CAAC,CAAC;EAC1C,MAAMa,YAAY,GAAGjB,eAAe,CAACe,KAAK,CAAC;EAE3C,MAAMG,oBAAoB,GAAIZ,KAAsB,IAAK;IACrDU,YAAY,CAACV,KAAK,CAACa,EAAE,CAAC;EAC1B,CAAC;;EAED;EACAxB,SAAS,CAAC,MAAM;IACZ,IAAI,CAACmB,cAAc,CAACM,OAAO,EAAE;MACzB;IACJ;IAEAC,UAAU,CAAC,MAAM;MACbP,cAAc,CAACM,OAAO,EAAEE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC,EAAE,EAAE,CAAC;EACV,CAAC,EAAE,CAAChB,KAAK,CAACa,EAAE,EAAEL,cAAc,CAACM,OAAO,CAAC,CAAC;EAEtC,IAAIL,KAAK,CAACQ,cAAc,EAAE;IACtB,oBAAO7B,KAAA,CAAA8B,aAAA,CAAA9B,KAAA,CAAA+B,QAAA,QAAE,yBAAyB,CAAC;EACvC;EAEA,oBACI/B,KAAA,CAAA8B,aAAA,CAACvB,wBAAwB;IACrBc,KAAK,EAAEA,KAAM;IACbT,KAAK,EAAEA,KAAM;IACbE,QAAQ,EAAEA,QAAS;IACnBC,eAAe,EAAEA,eAAgB;IACjCC,aAAa,EAAEA,aAAa,IAAIQ,oBAAqB;IACrDP,YAAY,EAAEA,YAAa;IAC3Be,wBAAwB,EAAE,IAAK;IAC/BnB,YAAY,EAAEA;EAAa,gBAE3Bb,KAAA,CAAA8B,aAAA,CAAC1B,aAAa;IAACiB,KAAK,EAAEA;EAAM,GACvBH,MAAM,GAAGA,MAAM,GAAG,IAAI,eACvBlB,KAAA,CAAA8B,aAAA,QAAAG,MAAA,CAAAC,MAAA,KACQf,KAAK;IACTM,EAAE,EAAE,kBAAmB;IACvB,gBAAc,kBAAmB;IACjC,eAAa,kBAAmB;IAChCU,GAAG,EAAEf;EAAe,IAEnBG,YAAY,gBACTvB,KAAA,CAAA8B,aAAA,CAACtB,YAAY;IAACa,KAAK,EAAEA,KAAM;IAACE,YAAY,EAAEA;EAAa,CAAE,CAAC,gBAE1DvB,KAAA,CAAA8B,aAAA,CAACrB,aAAa;IAACY,KAAK,EAAEA;EAAM,CAAE,CAEjC,CACM,CACO,CAAC;AAEnC,CACJ,CAAC","ignoreList":[]}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
2
|
import { makeDecoratable } from "@webiny/app-admin";
|
|
3
3
|
import { ModelProvider } from "../ModelProvider/index.js";
|
|
4
4
|
import { useFormRenderer } from "./useFormRenderer.js";
|
|
5
5
|
import { CustomLayout } from "./CustomLayout.js";
|
|
6
6
|
import { DefaultLayout } from "./DefaultLayout.js";
|
|
7
7
|
import { ContentEntryFormProvider } from "./ContentEntryFormProvider.js";
|
|
8
|
+
const baseEntry = {
|
|
9
|
+
values: {}
|
|
10
|
+
};
|
|
8
11
|
export const ContentEntryFormPreview = makeDecoratable("ContentEntryFormPreview", props => {
|
|
9
12
|
const {
|
|
10
13
|
contentModel
|
|
11
14
|
} = props;
|
|
12
15
|
const formRenderer = useFormRenderer(contentModel);
|
|
16
|
+
const initialEntry = useMemo(() => {
|
|
17
|
+
return baseEntry;
|
|
18
|
+
}, []);
|
|
13
19
|
return /*#__PURE__*/React.createElement(ContentEntryFormProvider, {
|
|
14
|
-
entry:
|
|
20
|
+
entry: initialEntry,
|
|
15
21
|
model: contentModel,
|
|
16
22
|
persistEntry: async entry => {
|
|
17
23
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","makeDecoratable","ModelProvider","useFormRenderer","CustomLayout","DefaultLayout","ContentEntryFormProvider","ContentEntryFormPreview","props","contentModel","formRenderer","createElement","entry","model","persistEntry","confirmNavigationIfDirty","className"],"sources":["ContentEntryFormPreview.tsx"],"sourcesContent":["import React from \"react\";\nimport { makeDecoratable } from \"@webiny/app-admin\";\nimport type { CmsContentEntry, CmsEditorContentModel } from \"~/types.js\";\nimport { ModelProvider } from \"~/admin/components/ModelProvider/index.js\";\nimport { useFormRenderer } from \"~/admin/components/ContentEntryForm/useFormRenderer.js\";\nimport { CustomLayout } from \"~/admin/components/ContentEntryForm/CustomLayout.js\";\nimport { DefaultLayout } from \"~/admin/components/ContentEntryForm/DefaultLayout.js\";\nimport { ContentEntryFormProvider } from \"./ContentEntryFormProvider.js\";\n\nexport interface ContentEntryFormPreviewProps {\n contentModel: CmsEditorContentModel;\n}\n\nexport const ContentEntryFormPreview = makeDecoratable(\n \"ContentEntryFormPreview\",\n (props: ContentEntryFormPreviewProps) => {\n const { contentModel } = props;\n\n const formRenderer = useFormRenderer(contentModel);\n\n return (\n <ContentEntryFormProvider\n entry={
|
|
1
|
+
{"version":3,"names":["React","useMemo","makeDecoratable","ModelProvider","useFormRenderer","CustomLayout","DefaultLayout","ContentEntryFormProvider","baseEntry","values","ContentEntryFormPreview","props","contentModel","formRenderer","initialEntry","createElement","entry","model","persistEntry","confirmNavigationIfDirty","className"],"sources":["ContentEntryFormPreview.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport { makeDecoratable } from \"@webiny/app-admin\";\nimport type { CmsContentEntry, CmsEditorContentModel } from \"~/types.js\";\nimport { ModelProvider } from \"~/admin/components/ModelProvider/index.js\";\nimport { useFormRenderer } from \"~/admin/components/ContentEntryForm/useFormRenderer.js\";\nimport { CustomLayout } from \"~/admin/components/ContentEntryForm/CustomLayout.js\";\nimport { DefaultLayout } from \"~/admin/components/ContentEntryForm/DefaultLayout.js\";\nimport { ContentEntryFormProvider } from \"./ContentEntryFormProvider.js\";\n\nexport interface ContentEntryFormPreviewProps {\n contentModel: CmsEditorContentModel;\n}\n\nconst baseEntry: Pick<CmsContentEntry, \"values\"> = {\n values: {}\n};\n\nexport const ContentEntryFormPreview = makeDecoratable(\n \"ContentEntryFormPreview\",\n (props: ContentEntryFormPreviewProps) => {\n const { contentModel } = props;\n\n const formRenderer = useFormRenderer(contentModel);\n\n const initialEntry = useMemo(() => {\n return baseEntry;\n }, []);\n\n return (\n <ContentEntryFormProvider\n entry={initialEntry}\n model={contentModel}\n persistEntry={async entry => {\n return {\n entry: entry as CmsContentEntry\n };\n }}\n confirmNavigationIfDirty={false}\n >\n <ModelProvider model={contentModel}>\n <div\n className={\"h-calc(100vh-260px) overflow-auto\"}\n data-testid={\"cms-content-form\"}\n >\n {formRenderer ? (\n <CustomLayout model={contentModel} formRenderer={formRenderer} />\n ) : (\n <DefaultLayout model={contentModel} />\n )}\n </div>\n </ModelProvider>\n </ContentEntryFormProvider>\n );\n }\n);\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,OAAO,QAAQ,OAAO;AACtC,SAASC,eAAe,QAAQ,mBAAmB;AAEnD,SAASC,aAAa;AACtB,SAASC,eAAe;AACxB,SAASC,YAAY;AACrB,SAASC,aAAa;AACtB,SAASC,wBAAwB;AAMjC,MAAMC,SAA0C,GAAG;EAC/CC,MAAM,EAAE,CAAC;AACb,CAAC;AAED,OAAO,MAAMC,uBAAuB,GAAGR,eAAe,CAClD,yBAAyB,EACxBS,KAAmC,IAAK;EACrC,MAAM;IAAEC;EAAa,CAAC,GAAGD,KAAK;EAE9B,MAAME,YAAY,GAAGT,eAAe,CAACQ,YAAY,CAAC;EAElD,MAAME,YAAY,GAAGb,OAAO,CAAC,MAAM;IAC/B,OAAOO,SAAS;EACpB,CAAC,EAAE,EAAE,CAAC;EAEN,oBACIR,KAAA,CAAAe,aAAA,CAACR,wBAAwB;IACrBS,KAAK,EAAEF,YAAa;IACpBG,KAAK,EAAEL,YAAa;IACpBM,YAAY,EAAE,MAAMF,KAAK,IAAI;MACzB,OAAO;QACHA,KAAK,EAAEA;MACX,CAAC;IACL,CAAE;IACFG,wBAAwB,EAAE;EAAM,gBAEhCnB,KAAA,CAAAe,aAAA,CAACZ,aAAa;IAACc,KAAK,EAAEL;EAAa,gBAC/BZ,KAAA,CAAAe,aAAA;IACIK,SAAS,EAAE,mCAAoC;IAC/C,eAAa;EAAmB,GAE/BP,YAAY,gBACTb,KAAA,CAAAe,aAAA,CAACV,YAAY;IAACY,KAAK,EAAEL,YAAa;IAACC,YAAY,EAAEA;EAAa,CAAE,CAAC,gBAEjEb,KAAA,CAAAe,aAAA,CAACT,aAAa;IAACW,KAAK,EAAEL;EAAa,CAAE,CAExC,CACM,CACO,CAAC;AAEnC,CACJ,CAAC","ignoreList":[]}
|
|
@@ -7,7 +7,7 @@ interface SaveEntryOptions {
|
|
|
7
7
|
createNewRevision?: boolean;
|
|
8
8
|
}
|
|
9
9
|
export interface ContentEntryFormContext {
|
|
10
|
-
entry: Partial<CmsContentEntry>;
|
|
10
|
+
entry: Partial<Omit<CmsContentEntry, "values">> & Pick<CmsContentEntry, "values">;
|
|
11
11
|
saveEntry: (options?: SaveEntryOptions) => Promise<CmsContentEntry | null>;
|
|
12
12
|
invalidFields: FormInvalidFields;
|
|
13
13
|
}
|
|
@@ -19,7 +19,7 @@ export interface PersistEntry {
|
|
|
19
19
|
(entry: Partial<CmsContentEntry>, options?: SaveEntryOptions): Promise<CreateEntryResponse | UpdateEntryRevisionResponse>;
|
|
20
20
|
}
|
|
21
21
|
interface ContentEntryFormProviderProps {
|
|
22
|
-
entry: Partial<CmsContentEntry>;
|
|
22
|
+
entry: Partial<Omit<CmsContentEntry, "values">> & Pick<CmsContentEntry, "values">;
|
|
23
23
|
model: CmsModel;
|
|
24
24
|
persistEntry: PersistEntry;
|
|
25
25
|
confirmNavigationIfDirty: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { DevToolsSection, useDialogs, useSnackbar } from "@webiny/app-admin";
|
|
3
|
+
import { useRouter } from "@webiny/app";
|
|
3
4
|
import { Form } from "@webiny/form";
|
|
4
5
|
import { prepareFormData } from "@webiny/app-headless-cms-common";
|
|
5
6
|
const promptMessage = "There are some unsaved changes! Are you sure you want to navigate away and discard all changes?";
|
|
@@ -30,6 +31,27 @@ export const ContentEntryFormProvider = ({
|
|
|
30
31
|
const saveOptionsRef = useRef({
|
|
31
32
|
skipValidators: undefined
|
|
32
33
|
});
|
|
34
|
+
const router = useRouter();
|
|
35
|
+
const dialogs = useDialogs();
|
|
36
|
+
const isPristineRef = useRef(true);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!confirmNavigationIfDirty) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
return router.addTransitionGuard({
|
|
42
|
+
guard: () => !isPristineRef.current,
|
|
43
|
+
onBlocked: () => {
|
|
44
|
+
dialogs.showDialog({
|
|
45
|
+
title: "Confirm Navigation",
|
|
46
|
+
content: promptMessage,
|
|
47
|
+
acceptLabel: "Yes!",
|
|
48
|
+
cancelLabel: "No, stay here.",
|
|
49
|
+
onAccept: () => router.confirmTransition(),
|
|
50
|
+
onClose: () => router.cancelTransition()
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}, [confirmNavigationIfDirty]);
|
|
33
55
|
const saveEntry = useCallback(async (options = {}) => {
|
|
34
56
|
saveOptionsRef.current.skipValidators = options.skipValidators;
|
|
35
57
|
return await ref.current.submit(undefined, {
|
|
@@ -66,6 +88,7 @@ export const ContentEntryFormProvider = ({
|
|
|
66
88
|
if ((isNewEntry || isNewRevision) && onAfterCreate) {
|
|
67
89
|
onAfterSubmitRef.current = onAfterCreate;
|
|
68
90
|
}
|
|
91
|
+
router.unblockTransition();
|
|
69
92
|
return entry;
|
|
70
93
|
};
|
|
71
94
|
useEffect(() => {
|
|
@@ -89,6 +112,7 @@ export const ContentEntryFormProvider = ({
|
|
|
89
112
|
showSnackbar("Some fields did not pass the validation. Please check the form.");
|
|
90
113
|
}
|
|
91
114
|
}, formProps => {
|
|
115
|
+
isPristineRef.current = formProps.form.isPristine;
|
|
92
116
|
const context = {
|
|
93
117
|
entry: {
|
|
94
118
|
...initialEntry,
|
|
@@ -99,12 +123,12 @@ export const ContentEntryFormProvider = ({
|
|
|
99
123
|
};
|
|
100
124
|
return /*#__PURE__*/React.createElement(ContentEntryFormContext.Provider, {
|
|
101
125
|
value: context
|
|
102
|
-
},
|
|
103
|
-
name: "
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
})
|
|
126
|
+
}, /*#__PURE__*/React.createElement(DevToolsSection, {
|
|
127
|
+
name: "Entry",
|
|
128
|
+
group: "CMS",
|
|
129
|
+
data: context.entry,
|
|
130
|
+
views: "raw"
|
|
131
|
+
}), children);
|
|
108
132
|
});
|
|
109
133
|
};
|
|
110
134
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useCallback","useEffect","useRef","useState","CompositionScope","NavigationPrompt","useSnackbar","Form","prepareFormData","promptMessage","ContentEntryFormContext","createContext","undefined","formValidationToMap","invalidFields","Object","keys","reduce","acc","key","message","ContentEntryFormProvider","model","entry","initialEntry","children","persistEntry","onChange","onInvalidFields","onAfterCreate","setSaveEntry","confirmNavigationIfDirty","ref","onAfterSubmitRef","setInvalidFields","showSnackbar","saveOptionsRef","skipValidators","saveEntry","options","current","submit","onFormSubmit","data","values","fields","isNewEntry","id","error","createNewRevision","meta","locked","code","errors","item","fieldId","isNewRevision","createElement","onSubmit","onAfterSubmit","validateOnFirstSubmit","onInvalid","formProps","context","Provider","value","name","when","form","isPristine"],"sources":["ContentEntryFormProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { CompositionScope, NavigationPrompt, useSnackbar } from \"@webiny/app-admin\";\nimport type { FormAPI, FormInvalidFields, FormOnSubmit, FormValidation } from \"@webiny/form\";\nimport { Form } from \"@webiny/form\";\nimport { prepareFormData } from \"@webiny/app-headless-cms-common\";\nimport type { CmsContentEntry, CmsModel } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport type {\n CreateEntryResponse,\n UpdateEntryRevisionResponse\n} from \"~/admin/contexts/Cms/index.js\";\nimport type { GenericRecord } from \"@webiny/app/types.js\";\n\nconst promptMessage =\n \"There are some unsaved changes! Are you sure you want to navigate away and discard all changes?\";\n\ninterface SaveEntryOptions {\n skipValidators?: string[];\n createNewRevision?: boolean;\n}\n\nexport interface ContentEntryFormContext {\n entry: Partial<CmsContentEntry>;\n saveEntry: (options?: SaveEntryOptions) => Promise<CmsContentEntry | null>;\n invalidFields: FormInvalidFields;\n}\n\nexport const ContentEntryFormContext = React.createContext<ContentEntryFormContext | undefined>(\n undefined\n);\n\nexport interface SetSaveEntry {\n (cb: ContentEntryFormContext[\"saveEntry\"]): void;\n}\n\nexport interface PersistEntry {\n (\n entry: Partial<CmsContentEntry>,\n options?: SaveEntryOptions\n ): Promise<CreateEntryResponse | UpdateEntryRevisionResponse>;\n}\n\ninterface ContentEntryFormProviderProps {\n entry: Partial<CmsContentEntry>;\n model: CmsModel;\n persistEntry: PersistEntry;\n confirmNavigationIfDirty: boolean;\n onChange?: FormOnSubmit<Partial<CmsContentEntry>>;\n onInvalidFields?: (invalidFields: FormValidation) => void;\n onAfterCreate?: (entry: CmsContentEntry) => void;\n setSaveEntry?: SetSaveEntry;\n children: React.ReactNode;\n}\n\ninterface InvalidFieldError {\n fieldId: string;\n error: string;\n}\n\nconst formValidationToMap = (invalidFields: FormValidation): FormInvalidFields => {\n return Object.keys(invalidFields).reduce(\n (acc, key) => ({ ...acc, [key]: invalidFields[key].message || \"Value is invalid.\" }),\n {} as FormInvalidFields\n );\n};\n\nexport const ContentEntryFormProvider = ({\n model,\n entry: initialEntry,\n children,\n persistEntry,\n onChange,\n onInvalidFields,\n onAfterCreate,\n setSaveEntry,\n confirmNavigationIfDirty\n}: ContentEntryFormProviderProps) => {\n const ref = useRef<FormAPI<CmsContentEntry> | null>(null);\n const onAfterSubmitRef = useRef<(entry: CmsContentEntry) => void>(() => void 0);\n const [invalidFields, setInvalidFields] = useState<FormInvalidFields>({});\n const { showSnackbar } = useSnackbar();\n const saveOptionsRef = useRef<SaveEntryOptions>({ skipValidators: undefined });\n\n const saveEntry = useCallback(async (options: SaveEntryOptions = {}) => {\n saveOptionsRef.current.skipValidators = options.skipValidators;\n\n return (await ref.current!.submit(undefined, {\n skipValidators: options.skipValidators\n })) as Promise<CmsContentEntry | null>;\n }, []);\n\n const onFormSubmit: FormOnSubmit<CmsContentEntry> = async data => {\n const values = prepareFormData<GenericRecord>(data, model.fields);\n const isNewEntry = initialEntry.id === undefined;\n\n const { entry, error } = await persistEntry(\n {\n id: initialEntry.id,\n values\n },\n {\n skipValidators: saveOptionsRef.current.skipValidators,\n createNewRevision: initialEntry.meta?.locked\n }\n );\n\n if (error) {\n if (error.code === \"VALIDATION_FAILED\") {\n const errors: InvalidFieldError[] = error.data || [];\n\n setInvalidFields(\n errors.reduce((acc, item) => ({ ...acc, [item.fieldId]: item.error }), {})\n );\n }\n showSnackbar(error.message);\n\n return;\n }\n\n showSnackbar(\"Entry saved successfully!\");\n setInvalidFields({});\n\n const isNewRevision = !isNewEntry && entry.id !== initialEntry.id;\n\n if ((isNewEntry || isNewRevision) && onAfterCreate) {\n onAfterSubmitRef.current = onAfterCreate;\n }\n\n return entry;\n };\n\n useEffect(() => {\n if (typeof setSaveEntry === \"function\") {\n setSaveEntry(saveEntry);\n }\n }, [setSaveEntry]);\n\n return (\n <Form<CmsContentEntry>\n onSubmit={onFormSubmit}\n onAfterSubmit={data => {\n onAfterSubmitRef.current(data);\n }}\n onChange={onChange}\n data={initialEntry.values}\n ref={ref}\n validateOnFirstSubmit\n invalidFields={invalidFields}\n onInvalid={invalidFields => {\n setInvalidFields(formValidationToMap(invalidFields));\n onInvalidFields && onInvalidFields(invalidFields);\n showSnackbar(\"Some fields did not pass the validation. Please check the form.\");\n }}\n >\n {formProps => {\n const context: ContentEntryFormContext = {\n entry: { ...initialEntry, values: formProps.data },\n saveEntry,\n invalidFields\n };\n return (\n <ContentEntryFormContext.Provider value={context}>\n {confirmNavigationIfDirty ? (\n <CompositionScope name={\"cms.contentEntryForm\"}>\n <NavigationPrompt\n when={() => !formProps.form.isPristine}\n message={promptMessage}\n />\n </CompositionScope>\n ) : null}\n {children}\n </ContentEntryFormContext.Provider>\n );\n }}\n </Form>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["React","useCallback","useEffect","useRef","useState","DevToolsSection","useDialogs","useSnackbar","useRouter","Form","prepareFormData","promptMessage","ContentEntryFormContext","createContext","undefined","formValidationToMap","invalidFields","Object","keys","reduce","acc","key","message","ContentEntryFormProvider","model","entry","initialEntry","children","persistEntry","onChange","onInvalidFields","onAfterCreate","setSaveEntry","confirmNavigationIfDirty","ref","onAfterSubmitRef","setInvalidFields","showSnackbar","saveOptionsRef","skipValidators","router","dialogs","isPristineRef","addTransitionGuard","guard","current","onBlocked","showDialog","title","content","acceptLabel","cancelLabel","onAccept","confirmTransition","onClose","cancelTransition","saveEntry","options","submit","onFormSubmit","data","values","fields","isNewEntry","id","error","createNewRevision","meta","locked","code","errors","item","fieldId","isNewRevision","unblockTransition","createElement","onSubmit","onAfterSubmit","validateOnFirstSubmit","onInvalid","formProps","form","isPristine","context","Provider","value","name","group","views"],"sources":["ContentEntryFormProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport { DevToolsSection, useDialogs, useSnackbar } from \"@webiny/app-admin\";\nimport { useRouter } from \"@webiny/app\";\nimport type { FormAPI, FormInvalidFields, FormOnSubmit, FormValidation } from \"@webiny/form\";\nimport { Form } from \"@webiny/form\";\nimport { prepareFormData } from \"@webiny/app-headless-cms-common\";\nimport type { CmsContentEntry, CmsModel } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport type {\n CreateEntryResponse,\n UpdateEntryRevisionResponse\n} from \"~/admin/contexts/Cms/index.js\";\nimport type { GenericRecord } from \"@webiny/app/types.js\";\n\nconst promptMessage =\n \"There are some unsaved changes! Are you sure you want to navigate away and discard all changes?\";\n\ninterface SaveEntryOptions {\n skipValidators?: string[];\n createNewRevision?: boolean;\n}\n\nexport interface ContentEntryFormContext {\n entry: Partial<Omit<CmsContentEntry, \"values\">> & Pick<CmsContentEntry, \"values\">;\n saveEntry: (options?: SaveEntryOptions) => Promise<CmsContentEntry | null>;\n invalidFields: FormInvalidFields;\n}\n\nexport const ContentEntryFormContext = React.createContext<ContentEntryFormContext | undefined>(\n undefined\n);\n\nexport interface SetSaveEntry {\n (cb: ContentEntryFormContext[\"saveEntry\"]): void;\n}\n\nexport interface PersistEntry {\n (\n entry: Partial<CmsContentEntry>,\n options?: SaveEntryOptions\n ): Promise<CreateEntryResponse | UpdateEntryRevisionResponse>;\n}\n\ninterface ContentEntryFormProviderProps {\n entry: Partial<Omit<CmsContentEntry, \"values\">> & Pick<CmsContentEntry, \"values\">;\n model: CmsModel;\n persistEntry: PersistEntry;\n confirmNavigationIfDirty: boolean;\n onChange?: FormOnSubmit<Partial<CmsContentEntry>>;\n onInvalidFields?: (invalidFields: FormValidation) => void;\n onAfterCreate?: (entry: CmsContentEntry) => void;\n setSaveEntry?: SetSaveEntry;\n children: React.ReactNode;\n}\n\ninterface InvalidFieldError {\n fieldId: string;\n error: string;\n}\n\nconst formValidationToMap = (invalidFields: FormValidation): FormInvalidFields => {\n return Object.keys(invalidFields).reduce(\n (acc, key) => ({ ...acc, [key]: invalidFields[key].message || \"Value is invalid.\" }),\n {} as FormInvalidFields\n );\n};\n\nexport const ContentEntryFormProvider = ({\n model,\n entry: initialEntry,\n children,\n persistEntry,\n onChange,\n onInvalidFields,\n onAfterCreate,\n setSaveEntry,\n confirmNavigationIfDirty\n}: ContentEntryFormProviderProps) => {\n const ref = useRef<FormAPI<CmsContentEntry> | null>(null);\n const onAfterSubmitRef = useRef<(entry: CmsContentEntry) => void>(() => void 0);\n const [invalidFields, setInvalidFields] = useState<FormInvalidFields>({});\n const { showSnackbar } = useSnackbar();\n const saveOptionsRef = useRef<SaveEntryOptions>({ skipValidators: undefined });\n const router = useRouter();\n const dialogs = useDialogs();\n const isPristineRef = useRef(true);\n\n useEffect(() => {\n if (!confirmNavigationIfDirty) {\n return;\n }\n\n return router.addTransitionGuard({\n guard: () => !isPristineRef.current,\n onBlocked: () => {\n dialogs.showDialog({\n title: \"Confirm Navigation\",\n content: promptMessage,\n acceptLabel: \"Yes!\",\n cancelLabel: \"No, stay here.\",\n onAccept: () => router.confirmTransition(),\n onClose: () => router.cancelTransition()\n });\n }\n });\n }, [confirmNavigationIfDirty]);\n\n const saveEntry = useCallback(async (options: SaveEntryOptions = {}) => {\n saveOptionsRef.current.skipValidators = options.skipValidators;\n\n return (await ref.current!.submit(undefined, {\n skipValidators: options.skipValidators\n })) as Promise<CmsContentEntry | null>;\n }, []);\n\n const onFormSubmit: FormOnSubmit<CmsContentEntry> = async data => {\n const values = prepareFormData<GenericRecord>(data, model.fields);\n const isNewEntry = initialEntry.id === undefined;\n\n const { entry, error } = await persistEntry(\n {\n id: initialEntry.id,\n values\n },\n {\n skipValidators: saveOptionsRef.current.skipValidators,\n createNewRevision: initialEntry.meta?.locked\n }\n );\n\n if (error) {\n if (error.code === \"VALIDATION_FAILED\") {\n const errors: InvalidFieldError[] = error.data || [];\n\n setInvalidFields(\n errors.reduce((acc, item) => ({ ...acc, [item.fieldId]: item.error }), {})\n );\n }\n showSnackbar(error.message);\n\n return;\n }\n\n showSnackbar(\"Entry saved successfully!\");\n setInvalidFields({});\n\n const isNewRevision = !isNewEntry && entry.id !== initialEntry.id;\n\n if ((isNewEntry || isNewRevision) && onAfterCreate) {\n onAfterSubmitRef.current = onAfterCreate;\n }\n\n router.unblockTransition();\n\n return entry;\n };\n\n useEffect(() => {\n if (typeof setSaveEntry === \"function\") {\n setSaveEntry(saveEntry);\n }\n }, [setSaveEntry]);\n\n return (\n <Form<CmsContentEntry>\n onSubmit={onFormSubmit}\n onAfterSubmit={data => {\n onAfterSubmitRef.current(data);\n }}\n onChange={onChange}\n data={initialEntry.values}\n ref={ref}\n validateOnFirstSubmit\n invalidFields={invalidFields}\n onInvalid={invalidFields => {\n setInvalidFields(formValidationToMap(invalidFields));\n onInvalidFields && onInvalidFields(invalidFields);\n showSnackbar(\"Some fields did not pass the validation. Please check the form.\");\n }}\n >\n {formProps => {\n isPristineRef.current = formProps.form.isPristine;\n\n const context: ContentEntryFormContext = {\n entry: { ...initialEntry, values: formProps.data },\n saveEntry,\n invalidFields\n };\n return (\n <ContentEntryFormContext.Provider value={context}>\n <DevToolsSection\n name={\"Entry\"}\n group={\"CMS\"}\n data={context.entry}\n views={\"raw\"}\n />\n {children}\n </ContentEntryFormContext.Provider>\n );\n }}\n </Form>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,13 +2,14 @@ import React from "react";
|
|
|
2
2
|
import { ContentEntryEditorConfig } from "../../../../config/contentEntries/index.js";
|
|
3
3
|
import { usePermission } from "../../../../hooks/usePermission.js";
|
|
4
4
|
import { useContentEntryForm } from "../../useContentEntryForm.js";
|
|
5
|
+
import { useIsModelPublishable } from "../../../../hooks/useIsModelPublishable.js";
|
|
5
6
|
export const SaveContentButton = () => {
|
|
6
|
-
const {
|
|
7
|
-
canEdit
|
|
8
|
-
} = usePermission();
|
|
9
7
|
const {
|
|
10
8
|
useButtons
|
|
11
9
|
} = ContentEntryEditorConfig.Actions.ButtonAction;
|
|
10
|
+
const {
|
|
11
|
+
canEdit
|
|
12
|
+
} = usePermission();
|
|
12
13
|
const {
|
|
13
14
|
ButtonSecondary
|
|
14
15
|
} = useButtons();
|
|
@@ -16,13 +17,15 @@ export const SaveContentButton = () => {
|
|
|
16
17
|
entry,
|
|
17
18
|
saveEntry
|
|
18
19
|
} = useContentEntryForm();
|
|
20
|
+
const isModelPublishable = useIsModelPublishable();
|
|
19
21
|
if (!canEdit(entry, "cms.contentEntry")) {
|
|
20
22
|
return null;
|
|
21
23
|
}
|
|
24
|
+
const skipValidators = isModelPublishable ? ["required"] : [];
|
|
22
25
|
return /*#__PURE__*/React.createElement(ButtonSecondary, {
|
|
23
26
|
"data-testid": "cms-content-save-content-button",
|
|
24
27
|
onAction: () => saveEntry({
|
|
25
|
-
skipValidators
|
|
28
|
+
skipValidators
|
|
26
29
|
})
|
|
27
30
|
}, "Save");
|
|
28
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","ContentEntryEditorConfig","usePermission","useContentEntryForm","
|
|
1
|
+
{"version":3,"names":["React","ContentEntryEditorConfig","usePermission","useContentEntryForm","useIsModelPublishable","SaveContentButton","useButtons","Actions","ButtonAction","canEdit","ButtonSecondary","entry","saveEntry","isModelPublishable","skipValidators","createElement","onAction"],"sources":["SaveContent.tsx"],"sourcesContent":["import React from \"react\";\nimport { ContentEntryEditorConfig } from \"~/admin/config/contentEntries/index.js\";\nimport { usePermission } from \"~/admin/hooks/usePermission.js\";\nimport { useContentEntryForm } from \"~/admin/components/ContentEntryForm/useContentEntryForm.js\";\nimport { useIsModelPublishable } from \"~/admin/hooks/useIsModelPublishable.js\";\n\nexport const SaveContentButton = () => {\n const { useButtons } = ContentEntryEditorConfig.Actions.ButtonAction;\n const { canEdit } = usePermission();\n const { ButtonSecondary } = useButtons();\n const { entry, saveEntry } = useContentEntryForm();\n const isModelPublishable = useIsModelPublishable();\n\n if (!canEdit(entry, \"cms.contentEntry\")) {\n return null;\n }\n\n const skipValidators = isModelPublishable ? [\"required\"] : [];\n\n return (\n <ButtonSecondary\n data-testid={\"cms-content-save-content-button\"}\n onAction={() => saveEntry({ skipValidators })}\n >\n {\"Save\"}\n </ButtonSecondary>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,wBAAwB;AACjC,SAASC,aAAa;AACtB,SAASC,mBAAmB;AAC5B,SAASC,qBAAqB;AAE9B,OAAO,MAAMC,iBAAiB,GAAGA,CAAA,KAAM;EACnC,MAAM;IAAEC;EAAW,CAAC,GAAGL,wBAAwB,CAACM,OAAO,CAACC,YAAY;EACpE,MAAM;IAAEC;EAAQ,CAAC,GAAGP,aAAa,CAAC,CAAC;EACnC,MAAM;IAAEQ;EAAgB,CAAC,GAAGJ,UAAU,CAAC,CAAC;EACxC,MAAM;IAAEK,KAAK;IAAEC;EAAU,CAAC,GAAGT,mBAAmB,CAAC,CAAC;EAClD,MAAMU,kBAAkB,GAAGT,qBAAqB,CAAC,CAAC;EAElD,IAAI,CAACK,OAAO,CAACE,KAAK,EAAE,kBAAkB,CAAC,EAAE;IACrC,OAAO,IAAI;EACf;EAEA,MAAMG,cAAc,GAAGD,kBAAkB,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE;EAE7D,oBACIb,KAAA,CAAAe,aAAA,CAACL,eAAe;IACZ,eAAa,iCAAkC;IAC/CM,QAAQ,EAAEA,CAAA,KAAMJ,SAAS,CAAC;MAAEE;IAAe,CAAC;EAAE,GAE7C,MACY,CAAC;AAE1B,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","createContext","useCallback","useContext","useEffect","useRef","get","useModelField","useForm","ParentField","undefined","useParentField","level","parent","getParentField","ParentFieldProvider","path","value","children","form","formRef","field","fieldContext","current","data","setValue","fieldId","cb","fieldPath","context","createElement","type","Provider"],"sources":["ParentValue.tsx"],"sourcesContent":["import React, { createContext, useCallback, useContext, useEffect, useRef } from \"react\";\nimport get from \"lodash/get.js\";\nimport type { CmsModelField } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport { useModelField } from \"~/admin/components/ModelFieldProvider/index.js\";\nimport type { FormAPI } from \"@webiny/form\";\nimport { useForm } from \"@webiny/form\";\n\ndeclare module \"react\" {\n namespace JSX {\n interface IntrinsicElements {\n \"hcms-parent-field-provider\": React.HTMLProps<HTMLDivElement>;\n }\n }\n}\n\ninterface ParentField {\n value: any;\n setValue: (fieldId: string, cb: (prevValue: any) => any) => void;\n field: CmsModelField;\n getParentField(level: number): ParentField | undefined;\n path: string;\n}\n\nconst ParentField = createContext<ParentField | undefined>(undefined);\n\nexport function useParentField(level = 0): ParentField | undefined {\n const parent = useContext(ParentField);\n\n if (!parent) {\n return undefined;\n }\n\n return level === 0 ? parent : parent.getParentField(level - 1);\n}\n\ninterface ParentFieldProviderProps {\n value: any;\n path: string;\n children: React.ReactNode;\n}\n\nexport const ParentFieldProvider = ({ path, value, children }: ParentFieldProviderProps) => {\n const parent = useContext(ParentField);\n const form = useForm();\n const formRef = useRef<FormAPI>();\n\n let field: CmsModelField | undefined;\n try {\n const fieldContext = useModelField();\n field = fieldContext.field;\n } catch {\n field = undefined;\n }\n\n const getParentField = (level = 0) => {\n return parent ? (level === 0 ? parent : parent.getParentField(level - 1)) : undefined;\n };\n\n useEffect(() => {\n formRef.current = form;\n }, [form.data]);\n\n const setValue = useCallback<ParentField[\"setValue\"]>((fieldId, cb) => {\n const fieldPath = `${path}.${fieldId}`;\n if (!path || !formRef.current) {\n return;\n }\n\n formRef.current.setValue(fieldPath, cb(get(formRef.current.data, fieldPath)));\n }, []);\n\n const context: ParentField | undefined = field\n ? {\n value,\n field,\n getParentField,\n path,\n setValue\n }\n : undefined;\n\n return (\n <hcms-parent-field-provider data-path={path} data-field-type={field?.type}>\n <ParentField.Provider value={context}>{children}</ParentField.Provider>\n </hcms-parent-field-provider>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,WAAW,EAAEC,UAAU,EAAEC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AACxF,OAAOC,GAAG,MAAM,eAAe;AAE/B,SAASC,aAAa;AAEtB,SAASC,OAAO,QAAQ,cAAc;AAkBtC,MAAMC,WAAW,gBAAGR,aAAa,CAA0BS,SAAS,CAAC;AAErE,OAAO,SAASC,cAAcA,CAACC,KAAK,GAAG,CAAC,EAA2B;EAC/D,MAAMC,MAAM,GAAGV,UAAU,CAACM,WAAW,CAAC;EAEtC,IAAI,CAACI,MAAM,EAAE;IACT,OAAOH,SAAS;EACpB;EAEA,OAAOE,KAAK,KAAK,CAAC,GAAGC,MAAM,GAAGA,MAAM,CAACC,cAAc,CAACF,KAAK,GAAG,CAAC,CAAC;AAClE;AAQA,OAAO,MAAMG,mBAAmB,GAAGA,CAAC;EAAEC,IAAI;EAAEC,KAAK;EAAEC;AAAmC,CAAC,KAAK;EACxF,MAAML,MAAM,GAAGV,UAAU,CAACM,WAAW,CAAC;EACtC,MAAMU,IAAI,GAAGX,OAAO,CAAC,CAAC;EACtB,MAAMY,OAAO,GAAGf,MAAM,
|
|
1
|
+
{"version":3,"names":["React","createContext","useCallback","useContext","useEffect","useRef","get","useModelField","useForm","ParentField","undefined","useParentField","level","parent","getParentField","ParentFieldProvider","path","value","children","form","formRef","field","fieldContext","current","data","setValue","fieldId","cb","fieldPath","context","createElement","type","Provider"],"sources":["ParentValue.tsx"],"sourcesContent":["import React, { createContext, useCallback, useContext, useEffect, useRef } from \"react\";\nimport get from \"lodash/get.js\";\nimport type { CmsModelField } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport { useModelField } from \"~/admin/components/ModelFieldProvider/index.js\";\nimport type { FormAPI } from \"@webiny/form\";\nimport { useForm } from \"@webiny/form\";\n\ndeclare module \"react\" {\n namespace JSX {\n interface IntrinsicElements {\n \"hcms-parent-field-provider\": React.HTMLProps<HTMLDivElement>;\n }\n }\n}\n\ninterface ParentField {\n value: any;\n setValue: (fieldId: string, cb: (prevValue: any) => any) => void;\n field: CmsModelField;\n getParentField(level: number): ParentField | undefined;\n path: string;\n}\n\nconst ParentField = createContext<ParentField | undefined>(undefined);\n\nexport function useParentField(level = 0): ParentField | undefined {\n const parent = useContext(ParentField);\n\n if (!parent) {\n return undefined;\n }\n\n return level === 0 ? parent : parent.getParentField(level - 1);\n}\n\ninterface ParentFieldProviderProps {\n value: any;\n path: string;\n children: React.ReactNode;\n}\n\nexport const ParentFieldProvider = ({ path, value, children }: ParentFieldProviderProps) => {\n const parent = useContext(ParentField);\n const form = useForm();\n const formRef = useRef<FormAPI | null>(null);\n\n let field: CmsModelField | undefined;\n try {\n const fieldContext = useModelField();\n field = fieldContext.field;\n } catch {\n field = undefined;\n }\n\n const getParentField = (level = 0) => {\n return parent ? (level === 0 ? parent : parent.getParentField(level - 1)) : undefined;\n };\n\n useEffect(() => {\n formRef.current = form;\n }, [form.data]);\n\n const setValue = useCallback<ParentField[\"setValue\"]>((fieldId, cb) => {\n const fieldPath = `${path}.${fieldId}`;\n if (!path || !formRef.current) {\n return;\n }\n\n formRef.current.setValue(fieldPath, cb(get(formRef.current.data, fieldPath)));\n }, []);\n\n const context: ParentField | undefined = field\n ? {\n value,\n field,\n getParentField,\n path,\n setValue\n }\n : undefined;\n\n return (\n <hcms-parent-field-provider data-path={path} data-field-type={field?.type}>\n <ParentField.Provider value={context}>{children}</ParentField.Provider>\n </hcms-parent-field-provider>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,WAAW,EAAEC,UAAU,EAAEC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AACxF,OAAOC,GAAG,MAAM,eAAe;AAE/B,SAASC,aAAa;AAEtB,SAASC,OAAO,QAAQ,cAAc;AAkBtC,MAAMC,WAAW,gBAAGR,aAAa,CAA0BS,SAAS,CAAC;AAErE,OAAO,SAASC,cAAcA,CAACC,KAAK,GAAG,CAAC,EAA2B;EAC/D,MAAMC,MAAM,GAAGV,UAAU,CAACM,WAAW,CAAC;EAEtC,IAAI,CAACI,MAAM,EAAE;IACT,OAAOH,SAAS;EACpB;EAEA,OAAOE,KAAK,KAAK,CAAC,GAAGC,MAAM,GAAGA,MAAM,CAACC,cAAc,CAACF,KAAK,GAAG,CAAC,CAAC;AAClE;AAQA,OAAO,MAAMG,mBAAmB,GAAGA,CAAC;EAAEC,IAAI;EAAEC,KAAK;EAAEC;AAAmC,CAAC,KAAK;EACxF,MAAML,MAAM,GAAGV,UAAU,CAACM,WAAW,CAAC;EACtC,MAAMU,IAAI,GAAGX,OAAO,CAAC,CAAC;EACtB,MAAMY,OAAO,GAAGf,MAAM,CAAiB,IAAI,CAAC;EAE5C,IAAIgB,KAAgC;EACpC,IAAI;IACA,MAAMC,YAAY,GAAGf,aAAa,CAAC,CAAC;IACpCc,KAAK,GAAGC,YAAY,CAACD,KAAK;EAC9B,CAAC,CAAC,MAAM;IACJA,KAAK,GAAGX,SAAS;EACrB;EAEA,MAAMI,cAAc,GAAGA,CAACF,KAAK,GAAG,CAAC,KAAK;IAClC,OAAOC,MAAM,GAAID,KAAK,KAAK,CAAC,GAAGC,MAAM,GAAGA,MAAM,CAACC,cAAc,CAACF,KAAK,GAAG,CAAC,CAAC,GAAIF,SAAS;EACzF,CAAC;EAEDN,SAAS,CAAC,MAAM;IACZgB,OAAO,CAACG,OAAO,GAAGJ,IAAI;EAC1B,CAAC,EAAE,CAACA,IAAI,CAACK,IAAI,CAAC,CAAC;EAEf,MAAMC,QAAQ,GAAGvB,WAAW,CAA0B,CAACwB,OAAO,EAAEC,EAAE,KAAK;IACnE,MAAMC,SAAS,GAAG,GAAGZ,IAAI,IAAIU,OAAO,EAAE;IACtC,IAAI,CAACV,IAAI,IAAI,CAACI,OAAO,CAACG,OAAO,EAAE;MAC3B;IACJ;IAEAH,OAAO,CAACG,OAAO,CAACE,QAAQ,CAACG,SAAS,EAAED,EAAE,CAACrB,GAAG,CAACc,OAAO,CAACG,OAAO,CAACC,IAAI,EAAEI,SAAS,CAAC,CAAC,CAAC;EACjF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,OAAgC,GAAGR,KAAK,GACxC;IACIJ,KAAK;IACLI,KAAK;IACLP,cAAc;IACdE,IAAI;IACJS;EACJ,CAAC,GACDf,SAAS;EAEf,oBACIV,KAAA,CAAA8B,aAAA;IAA4B,aAAWd,IAAK;IAAC,mBAAiBK,KAAK,EAAEU;EAAK,gBACtE/B,KAAA,CAAA8B,aAAA,CAACrB,WAAW,CAACuB,QAAQ;IAACf,KAAK,EAAEY;EAAQ,GAAEX,QAA+B,CAC9C,CAAC;AAErC,CAAC","ignoreList":[]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect } from "react";
|
|
2
|
-
import { makeDecoratable,
|
|
2
|
+
import { makeDecoratable, useDialogs, LeftPanel, RightPanel, SplitView } from "@webiny/app-admin";
|
|
3
|
+
import { useRouter } from "@webiny/app";
|
|
3
4
|
import { i18n } from "@webiny/app/i18n/index.js";
|
|
4
5
|
import { Heading, OverlayLoader, Tabs, Text, TimeAgo } from "@webiny/admin-ui";
|
|
5
6
|
import { ReactComponent as EditIcon } from "@webiny/icons/edit.svg";
|
|
@@ -23,6 +24,8 @@ export const ContentModelEditor = makeDecoratable("ContentModelEditor", () => {
|
|
|
23
24
|
isPristine,
|
|
24
25
|
contentModel
|
|
25
26
|
} = useModelEditor();
|
|
27
|
+
const router = useRouter();
|
|
28
|
+
const dialogs = useDialogs();
|
|
26
29
|
|
|
27
30
|
// Add a class to <body> to trigger global styles while this component is active
|
|
28
31
|
useEffect(() => {
|
|
@@ -31,6 +34,23 @@ export const ContentModelEditor = makeDecoratable("ContentModelEditor", () => {
|
|
|
31
34
|
document.body.classList.remove("overflow-hidden");
|
|
32
35
|
};
|
|
33
36
|
}, []);
|
|
37
|
+
const isPristineRef = React.useRef(isPristine);
|
|
38
|
+
isPristineRef.current = isPristine;
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
return router.addTransitionGuard({
|
|
41
|
+
guard: () => !isPristineRef.current,
|
|
42
|
+
onBlocked: () => {
|
|
43
|
+
dialogs.showDialog({
|
|
44
|
+
title: "Confirm Navigation",
|
|
45
|
+
content: prompt,
|
|
46
|
+
acceptLabel: "Yes!",
|
|
47
|
+
cancelLabel: "No, stay here.",
|
|
48
|
+
onAccept: () => router.confirmTransition(),
|
|
49
|
+
onClose: () => router.cancelTransition()
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}, []);
|
|
34
54
|
const [activeTab, setActiveTab] = useState("edit");
|
|
35
55
|
const onChange = ({
|
|
36
56
|
fields,
|
|
@@ -53,10 +73,7 @@ export const ContentModelEditor = makeDecoratable("ContentModelEditor", () => {
|
|
|
53
73
|
}
|
|
54
74
|
return /*#__PURE__*/React.createElement("div", {
|
|
55
75
|
className: "content-model-editor flex-1"
|
|
56
|
-
}, /*#__PURE__*/React.createElement(
|
|
57
|
-
when: !isPristine,
|
|
58
|
-
message: prompt
|
|
59
|
-
}), /*#__PURE__*/React.createElement(Header, null), /*#__PURE__*/React.createElement("div", {
|
|
76
|
+
}, /*#__PURE__*/React.createElement(Header, null), /*#__PURE__*/React.createElement("div", {
|
|
60
77
|
className: "w-full overflow-y-auto h-main-content"
|
|
61
78
|
}, /*#__PURE__*/React.createElement(SplitView, null, /*#__PURE__*/React.createElement(LeftPanel, {
|
|
62
79
|
span: 4,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useState","useEffect","makeDecoratable","NavigationPrompt","LeftPanel","RightPanel","SplitView","i18n","Heading","OverlayLoader","Tabs","Text","TimeAgo","ReactComponent","EditIcon","PreviewIcon","FieldsSidebar","FieldEditor","PreviewTab","Header","DragPreview","useModelEditor","ContentEntryEditorWithConfig","ContentEntryProvider","ContentEntriesProvider","ModelIsBeingDeletedError","t","ns","prompt","ContentModelEditor","data","setData","isPristine","contentModel","document","body","classList","add","remove","activeTab","setActiveTab","onChange","fields","layout","createElement","text","isBeingDeleted","model","className","when","message","span","onFieldDragStart","level","name","size","createdBy","displayName","datetime","savedOn","spacing","separator","value","String","onValueChange","tabs","Tab","key","trigger","icon","content","readonly"],"sources":["ContentModelEditor.tsx"],"sourcesContent":["import React, { useState, useEffect } from \"react\";\nimport {\n makeDecoratable,\n NavigationPrompt,\n LeftPanel,\n RightPanel,\n SplitView\n} from \"@webiny/app-admin\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport { Heading, OverlayLoader, Tabs, Text, TimeAgo } from \"@webiny/admin-ui\";\nimport { ReactComponent as EditIcon } from \"@webiny/icons/edit.svg\";\nimport { ReactComponent as PreviewIcon } from \"@webiny/icons/fullscreen.svg\";\nimport { FieldsSidebar } from \"./FieldsSidebar.js\";\nimport { FieldEditor } from \"../FieldEditor/index.js\";\nimport { PreviewTab } from \"./PreviewTab.js\";\nimport Header from \"./Header.js\";\nimport DragPreview from \"../DragPreview.js\";\nimport { useModelEditor } from \"./useModelEditor.js\";\nimport type { CmsEditorFieldsLayout, CmsModelField } from \"~/types.js\";\nimport { ContentEntryEditorWithConfig } from \"~/admin/config/contentEntries/index.js\";\nimport { ContentEntryProvider } from \"~/admin/views/contentEntries/ContentEntry/ContentEntryContext.js\";\nimport { ContentEntriesProvider } from \"~/admin/views/contentEntries/ContentEntriesContext.js\";\nimport { ModelIsBeingDeletedError } from \"~/admin/components/ContentModelEditor/ModelIsBeingDeletedError/index.js\";\n\nconst t = i18n.ns(\"app-headless-cms/admin/editor\");\n\nconst prompt = t`There are some unsaved changes! Are you sure you want to navigate away and discard all changes?`;\n\ninterface OnChangeParams {\n fields: CmsModelField[];\n layout: CmsEditorFieldsLayout;\n}\n\nexport const ContentModelEditor = makeDecoratable(\"ContentModelEditor\", () => {\n const { data, setData, isPristine, contentModel } = useModelEditor();\n\n // Add a class to <body> to trigger global styles while this component is active\n useEffect(() => {\n document.body.classList.add(\"overflow-hidden\");\n\n return () => {\n document.body.classList.remove(\"overflow-hidden\");\n };\n }, []);\n\n const [activeTab, setActiveTab] = useState<string>(\"edit\");\n\n const onChange = ({ fields, layout }: OnChangeParams) => {\n setData(data => ({ ...data, fields, layout }));\n };\n\n if (!data) {\n return <OverlayLoader text={\"Loading content model...\"} />;\n } else if (data.isBeingDeleted) {\n return <ModelIsBeingDeletedError model={data} />;\n }\n\n return (\n <div className={\"content-model-editor flex-1\"}>\n <NavigationPrompt when={!isPristine} message={prompt} />\n <Header />\n <div className={\"w-full overflow-y-auto h-main-content\"}>\n <SplitView>\n <LeftPanel span={4} className={\"bg-neutral-light\"}>\n <div className={\"px-lg py-md h-[calc(100vh-98px)] overflow-y-scroll\"}>\n <FieldsSidebar\n onFieldDragStart={() => {\n setActiveTab(\"edit\");\n }}\n />\n </div>\n </LeftPanel>\n <RightPanel span={8} className={\"bg-neutral-base\"}>\n <div className={\"h-full overflow-y-scroll\"}>\n {contentModel && (\n <div className={\"px-xl pt-lg pb-md-extra\"}>\n <Heading level={4}>{contentModel.name}</Heading>\n <Text size={\"sm\"} className={\"text-neutral-muted\"}>\n {`Created by ${contentModel.createdBy.displayName}. Last modified: `}\n <TimeAgo datetime={contentModel.savedOn} />.\n </Text>\n </div>\n )}\n <Tabs\n size={\"md\"}\n spacing={\"xl\"}\n separator={true}\n value={String(activeTab)}\n onValueChange={setActiveTab}\n tabs={[\n <Tabs.Tab\n key={\"edit\"}\n value={\"edit\"}\n trigger={\"Edit\"}\n icon={<EditIcon />}\n data-testid={\"cms.editor.tab.edit\"}\n content={\n <div className={\"relative mb-lg\"}>\n <FieldEditor\n fields={data.fields}\n layout={data.layout || []}\n onChange={onChange}\n />\n </div>\n }\n />,\n <Tabs.Tab\n key={\"preview\"}\n value={\"preview\"}\n trigger={\"Preview\"}\n icon={<PreviewIcon />}\n data-testid={\"cms.editor.tab.preview\"}\n content={\n <ContentEntryEditorWithConfig>\n <ContentEntriesProvider contentModel={data}>\n <ContentEntryProvider readonly={true}>\n <PreviewTab\n activeTab={activeTab === \"preview\"}\n />\n </ContentEntryProvider>\n </ContentEntriesProvider>\n </ContentEntryEditorWithConfig>\n }\n />\n ]}\n />\n </div>\n </RightPanel>\n </SplitView>\n <DragPreview />\n </div>\n </div>\n );\n});\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["React","useState","useEffect","makeDecoratable","useDialogs","LeftPanel","RightPanel","SplitView","useRouter","i18n","Heading","OverlayLoader","Tabs","Text","TimeAgo","ReactComponent","EditIcon","PreviewIcon","FieldsSidebar","FieldEditor","PreviewTab","Header","DragPreview","useModelEditor","ContentEntryEditorWithConfig","ContentEntryProvider","ContentEntriesProvider","ModelIsBeingDeletedError","t","ns","prompt","ContentModelEditor","data","setData","isPristine","contentModel","router","dialogs","document","body","classList","add","remove","isPristineRef","useRef","current","addTransitionGuard","guard","onBlocked","showDialog","title","content","acceptLabel","cancelLabel","onAccept","confirmTransition","onClose","cancelTransition","activeTab","setActiveTab","onChange","fields","layout","createElement","text","isBeingDeleted","model","className","span","onFieldDragStart","level","name","size","createdBy","displayName","datetime","savedOn","spacing","separator","value","String","onValueChange","tabs","Tab","key","trigger","icon","readonly"],"sources":["ContentModelEditor.tsx"],"sourcesContent":["import React, { useState, useEffect } from \"react\";\nimport { makeDecoratable, useDialogs, LeftPanel, RightPanel, SplitView } from \"@webiny/app-admin\";\nimport { useRouter } from \"@webiny/app\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport { Heading, OverlayLoader, Tabs, Text, TimeAgo } from \"@webiny/admin-ui\";\nimport { ReactComponent as EditIcon } from \"@webiny/icons/edit.svg\";\nimport { ReactComponent as PreviewIcon } from \"@webiny/icons/fullscreen.svg\";\nimport { FieldsSidebar } from \"./FieldsSidebar.js\";\nimport { FieldEditor } from \"../FieldEditor/index.js\";\nimport { PreviewTab } from \"./PreviewTab.js\";\nimport Header from \"./Header.js\";\nimport DragPreview from \"../DragPreview.js\";\nimport { useModelEditor } from \"./useModelEditor.js\";\nimport type { CmsEditorFieldsLayout, CmsModelField } from \"~/types.js\";\nimport { ContentEntryEditorWithConfig } from \"~/admin/config/contentEntries/index.js\";\nimport { ContentEntryProvider } from \"~/admin/views/contentEntries/ContentEntry/ContentEntryContext.js\";\nimport { ContentEntriesProvider } from \"~/admin/views/contentEntries/ContentEntriesContext.js\";\nimport { ModelIsBeingDeletedError } from \"~/admin/components/ContentModelEditor/ModelIsBeingDeletedError/index.js\";\n\nconst t = i18n.ns(\"app-headless-cms/admin/editor\");\n\nconst prompt = t`There are some unsaved changes! Are you sure you want to navigate away and discard all changes?`;\n\ninterface OnChangeParams {\n fields: CmsModelField[];\n layout: CmsEditorFieldsLayout;\n}\n\nexport const ContentModelEditor = makeDecoratable(\"ContentModelEditor\", () => {\n const { data, setData, isPristine, contentModel } = useModelEditor();\n const router = useRouter();\n const dialogs = useDialogs();\n\n // Add a class to <body> to trigger global styles while this component is active\n useEffect(() => {\n document.body.classList.add(\"overflow-hidden\");\n\n return () => {\n document.body.classList.remove(\"overflow-hidden\");\n };\n }, []);\n\n const isPristineRef = React.useRef(isPristine);\n isPristineRef.current = isPristine;\n\n useEffect(() => {\n return router.addTransitionGuard({\n guard: () => !isPristineRef.current,\n onBlocked: () => {\n dialogs.showDialog({\n title: \"Confirm Navigation\",\n content: prompt,\n acceptLabel: \"Yes!\",\n cancelLabel: \"No, stay here.\",\n onAccept: () => router.confirmTransition(),\n onClose: () => router.cancelTransition()\n });\n }\n });\n }, []);\n\n const [activeTab, setActiveTab] = useState<string>(\"edit\");\n\n const onChange = ({ fields, layout }: OnChangeParams) => {\n setData(data => ({ ...data, fields, layout }));\n };\n\n if (!data) {\n return <OverlayLoader text={\"Loading content model...\"} />;\n } else if (data.isBeingDeleted) {\n return <ModelIsBeingDeletedError model={data} />;\n }\n\n return (\n <div className={\"content-model-editor flex-1\"}>\n <Header />\n <div className={\"w-full overflow-y-auto h-main-content\"}>\n <SplitView>\n <LeftPanel span={4} className={\"bg-neutral-light\"}>\n <div className={\"px-lg py-md h-[calc(100vh-98px)] overflow-y-scroll\"}>\n <FieldsSidebar\n onFieldDragStart={() => {\n setActiveTab(\"edit\");\n }}\n />\n </div>\n </LeftPanel>\n <RightPanel span={8} className={\"bg-neutral-base\"}>\n <div className={\"h-full overflow-y-scroll\"}>\n {contentModel && (\n <div className={\"px-xl pt-lg pb-md-extra\"}>\n <Heading level={4}>{contentModel.name}</Heading>\n <Text size={\"sm\"} className={\"text-neutral-muted\"}>\n {`Created by ${contentModel.createdBy.displayName}. Last modified: `}\n <TimeAgo datetime={contentModel.savedOn} />.\n </Text>\n </div>\n )}\n <Tabs\n size={\"md\"}\n spacing={\"xl\"}\n separator={true}\n value={String(activeTab)}\n onValueChange={setActiveTab}\n tabs={[\n <Tabs.Tab\n key={\"edit\"}\n value={\"edit\"}\n trigger={\"Edit\"}\n icon={<EditIcon />}\n data-testid={\"cms.editor.tab.edit\"}\n content={\n <div className={\"relative mb-lg\"}>\n <FieldEditor\n fields={data.fields}\n layout={data.layout || []}\n onChange={onChange}\n />\n </div>\n }\n />,\n <Tabs.Tab\n key={\"preview\"}\n value={\"preview\"}\n trigger={\"Preview\"}\n icon={<PreviewIcon />}\n data-testid={\"cms.editor.tab.preview\"}\n content={\n <ContentEntryEditorWithConfig>\n <ContentEntriesProvider contentModel={data}>\n <ContentEntryProvider readonly={true}>\n <PreviewTab\n activeTab={activeTab === \"preview\"}\n />\n </ContentEntryProvider>\n </ContentEntriesProvider>\n </ContentEntryEditorWithConfig>\n }\n />\n ]}\n />\n </div>\n </RightPanel>\n </SplitView>\n <DragPreview />\n </div>\n </div>\n );\n});\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -20,7 +20,9 @@ const Field = props => {
|
|
|
20
20
|
}, ({
|
|
21
21
|
drag
|
|
22
22
|
}) => /*#__PURE__*/React.createElement("div", {
|
|
23
|
-
ref:
|
|
23
|
+
ref: element => {
|
|
24
|
+
drag(element);
|
|
25
|
+
},
|
|
24
26
|
"data-testid": `cms-editor-fields-field-${type}`,
|
|
25
27
|
onDragStart: onFieldDragStart,
|
|
26
28
|
className: "bg-neutral-base rounded-sm mb-sm py-sm px-md cursor-grab last-of-type:mb-none hover:opacity-80 transition-opacity"
|
|
@@ -56,7 +58,9 @@ const LayoutFieldItem = props => {
|
|
|
56
58
|
}, ({
|
|
57
59
|
drag
|
|
58
60
|
}) => /*#__PURE__*/React.createElement("div", {
|
|
59
|
-
ref:
|
|
61
|
+
ref: element => {
|
|
62
|
+
drag(element);
|
|
63
|
+
},
|
|
60
64
|
"data-testid": `cms-editor-fields-layout-field-${type}`,
|
|
61
65
|
onDragStart: onFieldDragStart,
|
|
62
66
|
className: "bg-neutral-base rounded-sm mb-sm py-sm px-md cursor-grab last-of-type:mb-none hover:opacity-80 transition-opacity"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","plugins","Draggable","Heading","Icon","Text","Field","props","onFieldDragStart","fieldType","type","label","icon","description","createElement","beginDrag","drag","ref","onDragStart","className","size","color","level","LayoutFieldItem","layoutField","layoutFieldType","FieldsSidebar","fieldTypePlugin","byType","filter","p","field","hideInAdmin","layoutFieldPlugins","Fragment","as","map","fieldPlugin","key","length","lp"],"sources":["FieldsSidebar.tsx"],"sourcesContent":["import type { DragEventHandler } from \"react\";\nimport React from \"react\";\nimport { plugins } from \"@webiny/plugins\";\nimport Draggable from \"../Draggable.js\";\nimport type { CmsModelFieldTypePlugin, CmsModelLayoutFieldTypePlugin } from \"~/types.js\";\nimport { Heading, Icon, Text } from \"@webiny/admin-ui\";\n\ninterface FieldProps {\n onFieldDragStart: DragEventHandler;\n fieldType: CmsModelFieldTypePlugin[\"field\"];\n}\n\nconst Field = (props: FieldProps) => {\n const {\n onFieldDragStart,\n fieldType: { type, label, icon, description }\n } = props;\n return (\n <Draggable beginDrag={{ type: \"newField\", fieldType: type }}>\n {({ drag }) => (\n <div\n ref={drag}\n data-testid={`cms-editor-fields-field-${type}`}\n onDragStart={onFieldDragStart}\n className={\n \"bg-neutral-base rounded-sm mb-sm py-sm px-md cursor-grab last-of-type:mb-none hover:opacity-80 transition-opacity\"\n }\n >\n <div className={\"flex items-center gap-md\"}>\n <div>\n <Icon\n icon={icon as React.ReactElement}\n label={label}\n size={\"md\"}\n color={\"neutral-light\"}\n />\n </div>\n <div>\n <Heading level={6}>{label}</Heading>\n <Text size={\"sm\"} className={\"text-neutral-strong\"}>\n {description}\n </Text>\n </div>\n </div>\n </div>\n )}\n </Draggable>\n );\n};\n\ninterface LayoutFieldItemProps {\n onFieldDragStart: DragEventHandler;\n layoutField: CmsModelLayoutFieldTypePlugin[\"field\"];\n}\n\nconst LayoutFieldItem = (props: LayoutFieldItemProps) => {\n const {\n onFieldDragStart,\n layoutField: { type, label, icon, description }\n } = props;\n return (\n <Draggable beginDrag={{ type: \"newLayoutField\", layoutFieldType: type }}>\n {({ drag }) => (\n <div\n ref={drag}\n data-testid={`cms-editor-fields-layout-field-${type}`}\n onDragStart={onFieldDragStart}\n className={\n \"bg-neutral-base rounded-sm mb-sm py-sm px-md cursor-grab last-of-type:mb-none hover:opacity-80 transition-opacity\"\n }\n >\n <div className={\"flex items-center gap-md\"}>\n <div>\n <Icon icon={icon} label={label} size={\"md\"} color={\"neutral-light\"} />\n </div>\n <div>\n <Heading level={6}>{label}</Heading>\n <Text size={\"sm\"} className={\"text-neutral-strong\"}>\n {description}\n </Text>\n </div>\n </div>\n </div>\n )}\n </Draggable>\n );\n};\n\ninterface FieldsSidebarProps {\n onFieldDragStart: DragEventHandler;\n}\n\nexport const FieldsSidebar = ({ onFieldDragStart }: FieldsSidebarProps) => {\n const fieldTypePlugin = plugins\n .byType<CmsModelFieldTypePlugin>(\"cms-editor-field-type\")\n .filter(p => !p.field.hideInAdmin);\n\n const layoutFieldPlugins = plugins.byType<CmsModelLayoutFieldTypePlugin>(\n \"cms-editor-layout-field-type\"\n );\n\n return (\n <>\n <Text\n as=\"div\"\n size={\"md\"}\n className={\"text-neutral-strong uppercase mt-0 mb-md font-semibold\"}\n >\n Fields\n </Text>\n {fieldTypePlugin.map(fieldPlugin => (\n <Field\n key={fieldPlugin.field.type}\n fieldType={fieldPlugin.field}\n onFieldDragStart={onFieldDragStart}\n />\n ))}\n {layoutFieldPlugins.length > 0 && (\n <>\n <Text\n as=\"div\"\n size={\"md\"}\n className={\"text-neutral-strong uppercase my-md font-semibold\"}\n >\n Layout\n </Text>\n {layoutFieldPlugins.map(lp => (\n <LayoutFieldItem\n key={lp.field.type}\n layoutField={lp.field}\n onFieldDragStart={onFieldDragStart}\n />\n ))}\n </>\n )}\n </>\n );\n};\n"],"mappings":"AACA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,OAAO,QAAQ,iBAAiB;AACzC,OAAOC,SAAS;AAEhB,SAASC,OAAO,EAAEC,IAAI,EAAEC,IAAI,QAAQ,kBAAkB;AAOtD,MAAMC,KAAK,GAAIC,KAAiB,IAAK;EACjC,MAAM;IACFC,gBAAgB;IAChBC,SAAS,EAAE;MAAEC,IAAI;MAAEC,KAAK;MAAEC,IAAI;MAAEC;IAAY;EAChD,CAAC,GAAGN,KAAK;EACT,oBACIP,KAAA,CAAAc,aAAA,CAACZ,SAAS;IAACa,SAAS,EAAE;MAAEL,IAAI,EAAE,UAAU;MAAED,SAAS,EAAEC;IAAK;EAAE,GACvD,CAAC;IAAEM;EAAK,CAAC,kBACNhB,KAAA,CAAAc,aAAA;IACIG,GAAG,
|
|
1
|
+
{"version":3,"names":["React","plugins","Draggable","Heading","Icon","Text","Field","props","onFieldDragStart","fieldType","type","label","icon","description","createElement","beginDrag","drag","ref","element","onDragStart","className","size","color","level","LayoutFieldItem","layoutField","layoutFieldType","FieldsSidebar","fieldTypePlugin","byType","filter","p","field","hideInAdmin","layoutFieldPlugins","Fragment","as","map","fieldPlugin","key","length","lp"],"sources":["FieldsSidebar.tsx"],"sourcesContent":["import type { DragEventHandler } from \"react\";\nimport React from \"react\";\nimport { plugins } from \"@webiny/plugins\";\nimport Draggable from \"../Draggable.js\";\nimport type { CmsModelFieldTypePlugin, CmsModelLayoutFieldTypePlugin } from \"~/types.js\";\nimport { Heading, Icon, Text } from \"@webiny/admin-ui\";\n\ninterface FieldProps {\n onFieldDragStart: DragEventHandler;\n fieldType: CmsModelFieldTypePlugin[\"field\"];\n}\n\nconst Field = (props: FieldProps) => {\n const {\n onFieldDragStart,\n fieldType: { type, label, icon, description }\n } = props;\n return (\n <Draggable beginDrag={{ type: \"newField\", fieldType: type }}>\n {({ drag }) => (\n <div\n ref={element => {\n drag(element);\n }}\n data-testid={`cms-editor-fields-field-${type}`}\n onDragStart={onFieldDragStart}\n className={\n \"bg-neutral-base rounded-sm mb-sm py-sm px-md cursor-grab last-of-type:mb-none hover:opacity-80 transition-opacity\"\n }\n >\n <div className={\"flex items-center gap-md\"}>\n <div>\n <Icon\n icon={icon as React.ReactElement}\n label={label}\n size={\"md\"}\n color={\"neutral-light\"}\n />\n </div>\n <div>\n <Heading level={6}>{label}</Heading>\n <Text size={\"sm\"} className={\"text-neutral-strong\"}>\n {description}\n </Text>\n </div>\n </div>\n </div>\n )}\n </Draggable>\n );\n};\n\ninterface LayoutFieldItemProps {\n onFieldDragStart: DragEventHandler;\n layoutField: CmsModelLayoutFieldTypePlugin[\"field\"];\n}\n\nconst LayoutFieldItem = (props: LayoutFieldItemProps) => {\n const {\n onFieldDragStart,\n layoutField: { type, label, icon, description }\n } = props;\n return (\n <Draggable beginDrag={{ type: \"newLayoutField\", layoutFieldType: type }}>\n {({ drag }) => (\n <div\n ref={element => {\n drag(element);\n }}\n data-testid={`cms-editor-fields-layout-field-${type}`}\n onDragStart={onFieldDragStart}\n className={\n \"bg-neutral-base rounded-sm mb-sm py-sm px-md cursor-grab last-of-type:mb-none hover:opacity-80 transition-opacity\"\n }\n >\n <div className={\"flex items-center gap-md\"}>\n <div>\n <Icon icon={icon} label={label} size={\"md\"} color={\"neutral-light\"} />\n </div>\n <div>\n <Heading level={6}>{label}</Heading>\n <Text size={\"sm\"} className={\"text-neutral-strong\"}>\n {description}\n </Text>\n </div>\n </div>\n </div>\n )}\n </Draggable>\n );\n};\n\ninterface FieldsSidebarProps {\n onFieldDragStart: DragEventHandler;\n}\n\nexport const FieldsSidebar = ({ onFieldDragStart }: FieldsSidebarProps) => {\n const fieldTypePlugin = plugins\n .byType<CmsModelFieldTypePlugin>(\"cms-editor-field-type\")\n .filter(p => !p.field.hideInAdmin);\n\n const layoutFieldPlugins = plugins.byType<CmsModelLayoutFieldTypePlugin>(\n \"cms-editor-layout-field-type\"\n );\n\n return (\n <>\n <Text\n as=\"div\"\n size={\"md\"}\n className={\"text-neutral-strong uppercase mt-0 mb-md font-semibold\"}\n >\n Fields\n </Text>\n {fieldTypePlugin.map(fieldPlugin => (\n <Field\n key={fieldPlugin.field.type}\n fieldType={fieldPlugin.field}\n onFieldDragStart={onFieldDragStart}\n />\n ))}\n {layoutFieldPlugins.length > 0 && (\n <>\n <Text\n as=\"div\"\n size={\"md\"}\n className={\"text-neutral-strong uppercase my-md font-semibold\"}\n >\n Layout\n </Text>\n {layoutFieldPlugins.map(lp => (\n <LayoutFieldItem\n key={lp.field.type}\n layoutField={lp.field}\n onFieldDragStart={onFieldDragStart}\n />\n ))}\n </>\n )}\n </>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -12,7 +12,7 @@ const onOffsetChange = monitor => () => {
|
|
|
12
12
|
}
|
|
13
13
|
const transform = `translate(${offset.x - 15}px, ${offset.y - 15}px)`;
|
|
14
14
|
dragPreviewRef.style["transform"] = transform;
|
|
15
|
-
// TODO @ts-refactor figure out better type
|
|
15
|
+
// TODO @ts-refactor figure out better type / possibly not needed in newer browsers
|
|
16
16
|
// @ts-expect-error
|
|
17
17
|
dragPreviewRef.style["-webkit-transform"] = transform;
|
|
18
18
|
};
|
|
@@ -64,7 +64,9 @@ const DragPreview = () => {
|
|
|
64
64
|
},
|
|
65
65
|
className: "fixed pointer-events-none left-0 top-0 w-full h-full"
|
|
66
66
|
}, /*#__PURE__*/React.createElement("div", {
|
|
67
|
-
ref: el =>
|
|
67
|
+
ref: el => {
|
|
68
|
+
dragPreviewRef = el;
|
|
69
|
+
},
|
|
68
70
|
className: "transition-opacity duration-250 ease-in-out block",
|
|
69
71
|
style: {
|
|
70
72
|
opacity: dragHelperOpacity
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["React","useEffect","useState","useDragLayer","subscribedToOffsetChange","dragPreviewRef","onOffsetChange","monitor","offset","getClientOffset","transform","x","y","style","DragPreview","dragHelperOpacity","setDragHelperOpacity","isDragging","initialMonitor","subscribeToOffsetChange","setTimeout","createElement","zIndex","className","ref","el","opacity"],"sources":["DragPreview.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport type { DragSourceMonitor } from \"react-dnd\";\nimport { useDragLayer } from \"react-dnd\";\nimport type { DragSourceMonitorImpl } from \"~/types.js\";\n\nlet subscribedToOffsetChange = false;\n\nlet dragPreviewRef: HTMLDivElement | null = null;\n\nconst onOffsetChange = (monitor: DragSourceMonitor) => () => {\n if (!dragPreviewRef) {\n return;\n }\n\n const offset = monitor.getClientOffset();\n if (!offset) {\n return;\n }\n\n const transform = `translate(${offset.x - 15}px, ${offset.y - 15}px)`;\n dragPreviewRef.style[\"transform\"] = transform;\n // TODO @ts-refactor figure out better type\n // @ts-expect-error\n dragPreviewRef.style[\"-webkit-transform\"] = transform;\n};\n\nconst DragPreview = () => {\n const [dragHelperOpacity, setDragHelperOpacity] = useState(0);\n const { isDragging } = useDragLayer(initialMonitor => {\n /**\n * We must cast because TS is complaining. We know that casting as DragSourceMonitorImpl is ok.\n */\n const monitor = initialMonitor as unknown as DragSourceMonitorImpl;\n if (!subscribedToOffsetChange) {\n monitor.subscribeToOffsetChange(onOffsetChange(monitor));\n subscribedToOffsetChange = true;\n }\n\n return {\n isDragging: monitor.isDragging()\n };\n });\n\n useEffect(() => {\n return () => {\n subscribedToOffsetChange = false;\n dragPreviewRef = null;\n };\n }, []);\n\n // We track the value of \"isDragging\" and apply opacity=1 (after 100ms), when it switches to true.\n // Without this, the drag cursor would be shown in the top-left corner for a short amount of time, and then it\n // would be repositioned correctly. Definitely looks like a glitch. This also adds a nice little fade-in effect.\n useEffect(() => {\n if (isDragging) {\n setTimeout(() => {\n setDragHelperOpacity(isDragging ? 1 : 0);\n }, 100);\n } else {\n setDragHelperOpacity(0);\n }\n }, [isDragging]);\n\n if (!isDragging) {\n return null;\n }\n\n if (!isDragging) {\n return null;\n }\n\n return (\n <div\n style={{ zIndex: 1001 }}\n className=\"fixed pointer-events-none left-0 top-0 w-full h-full\"\n >\n <div\n ref={el =>
|
|
1
|
+
{"version":3,"names":["React","useEffect","useState","useDragLayer","subscribedToOffsetChange","dragPreviewRef","onOffsetChange","monitor","offset","getClientOffset","transform","x","y","style","DragPreview","dragHelperOpacity","setDragHelperOpacity","isDragging","initialMonitor","subscribeToOffsetChange","setTimeout","createElement","zIndex","className","ref","el","opacity"],"sources":["DragPreview.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport type { DragSourceMonitor } from \"react-dnd\";\nimport { useDragLayer } from \"react-dnd\";\nimport type { DragSourceMonitorImpl } from \"~/types.js\";\n\nlet subscribedToOffsetChange = false;\n\nlet dragPreviewRef: HTMLDivElement | null = null;\n\nconst onOffsetChange = (monitor: DragSourceMonitor) => () => {\n if (!dragPreviewRef) {\n return;\n }\n\n const offset = monitor.getClientOffset();\n if (!offset) {\n return;\n }\n\n const transform = `translate(${offset.x - 15}px, ${offset.y - 15}px)`;\n dragPreviewRef.style[\"transform\"] = transform;\n // TODO @ts-refactor figure out better type / possibly not needed in newer browsers\n // @ts-expect-error\n dragPreviewRef.style[\"-webkit-transform\"] = transform;\n};\n\nconst DragPreview = () => {\n const [dragHelperOpacity, setDragHelperOpacity] = useState(0);\n const { isDragging } = useDragLayer(initialMonitor => {\n /**\n * We must cast because TS is complaining. We know that casting as DragSourceMonitorImpl is ok.\n */\n const monitor = initialMonitor as unknown as DragSourceMonitorImpl;\n if (!subscribedToOffsetChange) {\n monitor.subscribeToOffsetChange(onOffsetChange(monitor));\n subscribedToOffsetChange = true;\n }\n\n return {\n isDragging: monitor.isDragging()\n };\n });\n\n useEffect(() => {\n return () => {\n subscribedToOffsetChange = false;\n dragPreviewRef = null;\n };\n }, []);\n\n // We track the value of \"isDragging\" and apply opacity=1 (after 100ms), when it switches to true.\n // Without this, the drag cursor would be shown in the top-left corner for a short amount of time, and then it\n // would be repositioned correctly. Definitely looks like a glitch. This also adds a nice little fade-in effect.\n useEffect(() => {\n if (isDragging) {\n setTimeout(() => {\n setDragHelperOpacity(isDragging ? 1 : 0);\n }, 100);\n } else {\n setDragHelperOpacity(0);\n }\n }, [isDragging]);\n\n if (!isDragging) {\n return null;\n }\n\n if (!isDragging) {\n return null;\n }\n\n return (\n <div\n style={{ zIndex: 1001 }}\n className=\"fixed pointer-events-none left-0 top-0 w-full h-full\"\n >\n <div\n ref={el => {\n dragPreviewRef = el;\n }}\n className=\"transition-opacity duration-250 ease-in-out block\"\n style={{ opacity: dragHelperOpacity }}\n >\n <div className=\"size-lg rounded-full bg-primary\" />\n </div>\n </div>\n );\n};\nexport default DragPreview;\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAElD,SAASC,YAAY,QAAQ,WAAW;AAGxC,IAAIC,wBAAwB,GAAG,KAAK;AAEpC,IAAIC,cAAqC,GAAG,IAAI;AAEhD,MAAMC,cAAc,GAAIC,OAA0B,IAAK,MAAM;EACzD,IAAI,CAACF,cAAc,EAAE;IACjB;EACJ;EAEA,MAAMG,MAAM,GAAGD,OAAO,CAACE,eAAe,CAAC,CAAC;EACxC,IAAI,CAACD,MAAM,EAAE;IACT;EACJ;EAEA,MAAME,SAAS,GAAG,aAAaF,MAAM,CAACG,CAAC,GAAG,EAAE,OAAOH,MAAM,CAACI,CAAC,GAAG,EAAE,KAAK;EACrEP,cAAc,CAACQ,KAAK,CAAC,WAAW,CAAC,GAAGH,SAAS;EAC7C;EACA;EACAL,cAAc,CAACQ,KAAK,CAAC,mBAAmB,CAAC,GAAGH,SAAS;AACzD,CAAC;AAED,MAAMI,WAAW,GAAGA,CAAA,KAAM;EACtB,MAAM,CAACC,iBAAiB,EAAEC,oBAAoB,CAAC,GAAGd,QAAQ,CAAC,CAAC,CAAC;EAC7D,MAAM;IAAEe;EAAW,CAAC,GAAGd,YAAY,CAACe,cAAc,IAAI;IAClD;AACR;AACA;IACQ,MAAMX,OAAO,GAAGW,cAAkD;IAClE,IAAI,CAACd,wBAAwB,EAAE;MAC3BG,OAAO,CAACY,uBAAuB,CAACb,cAAc,CAACC,OAAO,CAAC,CAAC;MACxDH,wBAAwB,GAAG,IAAI;IACnC;IAEA,OAAO;MACHa,UAAU,EAAEV,OAAO,CAACU,UAAU,CAAC;IACnC,CAAC;EACL,CAAC,CAAC;EAEFhB,SAAS,CAAC,MAAM;IACZ,OAAO,MAAM;MACTG,wBAAwB,GAAG,KAAK;MAChCC,cAAc,GAAG,IAAI;IACzB,CAAC;EACL,CAAC,EAAE,EAAE,CAAC;;EAEN;EACA;EACA;EACAJ,SAAS,CAAC,MAAM;IACZ,IAAIgB,UAAU,EAAE;MACZG,UAAU,CAAC,MAAM;QACbJ,oBAAoB,CAACC,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC;MAC5C,CAAC,EAAE,GAAG,CAAC;IACX,CAAC,MAAM;MACHD,oBAAoB,CAAC,CAAC,CAAC;IAC3B;EACJ,CAAC,EAAE,CAACC,UAAU,CAAC,CAAC;EAEhB,IAAI,CAACA,UAAU,EAAE;IACb,OAAO,IAAI;EACf;EAEA,IAAI,CAACA,UAAU,EAAE;IACb,OAAO,IAAI;EACf;EAEA,oBACIjB,KAAA,CAAAqB,aAAA;IACIR,KAAK,EAAE;MAAES,MAAM,EAAE;IAAK,CAAE;IACxBC,SAAS,EAAC;EAAsD,gBAEhEvB,KAAA,CAAAqB,aAAA;IACIG,GAAG,EAAEC,EAAE,IAAI;MACPpB,cAAc,GAAGoB,EAAE;IACvB,CAAE;IACFF,SAAS,EAAC,mDAAmD;IAC7DV,KAAK,EAAE;MAAEa,OAAO,EAAEX;IAAkB;EAAE,gBAEtCf,KAAA,CAAAqB,aAAA;IAAKE,SAAS,EAAC;EAAiC,CAAE,CACjD,CACJ,CAAC;AAEd,CAAC;AACD,eAAeT,WAAW","ignoreList":[]}
|