@webiny/app-headless-cms 6.5.0-beta.6 → 6.5.0-beta.8

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.
@@ -9,6 +9,7 @@ import { ChangeEntryStatus, DeleteEntry, DuplicateEntry, EditEntry, MoveEntry }
9
9
  import { CellActions, CellAuthor, CellCreated, CellLive, CellModified, CellName, CellStatus } from "./admin/components/ContentEntries/Table/Cells/index.js";
10
10
  import { IsModelPublishable } from "./admin/components/IsModelPublishable.js";
11
11
  import { FilterByStatus } from "./admin/components/ContentEntries/FilterByStatus.js";
12
+ import { Ref } from "./admin/components/ContentEntries/Filters/RefFieldRenderer.js";
12
13
  import { CmsTrashBin } from "./presentation/contentEntries/trashBin/CmsTrashBin.js";
13
14
  import { TrashEntryConfirmDialog } from "./admin/components/Dialogs/TrashEntryConfirmDialog.js";
14
15
  import { PublishEntryConfirmDialog } from "./admin/components/Dialogs/PublishEntryConfirmDialog.js";
@@ -129,6 +130,10 @@ const ContentEntriesModule = ()=>/*#__PURE__*/ react.createElement(react.Fragmen
129
130
  hideable: false,
130
131
  truncate: false,
131
132
  className: "flex justify-center"
133
+ }), /*#__PURE__*/ react.createElement(Browser.AdvancedSearch.FieldRenderer, {
134
+ name: "ref",
135
+ type: Browser.AdvancedSearch.FieldRenderer.FieldType.REF,
136
+ element: /*#__PURE__*/ react.createElement(Ref, null)
132
137
  })), /*#__PURE__*/ react.createElement(InternalContentEntryEditorConfig, null, /*#__PURE__*/ react.createElement(IsModelPublishable, null, /*#__PURE__*/ react.createElement(Actions.ButtonAction, {
133
138
  name: "revisionSelector",
134
139
  element: /*#__PURE__*/ react.createElement(RevisionSelector, null)
@@ -1 +1 @@
1
- {"version":3,"file":"ContentEntriesModule.js","sources":["../src/ContentEntriesModule.tsx"],"sourcesContent":["import React from \"react\";\nimport { AdminConfig } from \"@webiny/app-admin\";\nimport { AdvancedSearchConfigs } from \"@webiny/app-aco/components/AdvancedSearch/AdvancedSearchConfigs\";\nimport {\n InternalContentEntryEditorConfig,\n InternalContentEntryListConfig\n} from \"~/admin/config/contentEntries/index.js\";\n\nimport {\n ActionDelete,\n ActionMove,\n ActionPublish,\n ActionUnpublish\n} from \"~/admin/components/ContentEntries/BulkActions/index.js\";\n\nimport {\n TRASH_ENTRY_DIALOG,\n PUBLISH_ENTRY_DIALOG,\n UNPUBLISH_ENTRY_DIALOG,\n DUPLICATE_ENTRY_DIALOG\n} from \"~/presentation/contentEntries/list/ContentEntriesPresenter.js\";\nimport { DeleteFolder, EditFolder, SetFolderPermissions } from \"@webiny/app-aco\";\nimport {\n ChangeEntryStatus,\n DeleteEntry,\n DuplicateEntry,\n EditEntry,\n MoveEntry\n} from \"~/admin/components/ContentEntries/Table/Actions/index.js\";\nimport {\n CellActions,\n CellAuthor,\n CellCreated,\n CellLive,\n CellModified,\n CellName,\n CellStatus\n} from \"~/admin/components/ContentEntries/Table/Cells/index.js\";\nimport { IsModelPublishable } from \"~/admin/components/IsModelPublishable.js\";\nimport { FilterByStatus } from \"~/admin/components/ContentEntries/FilterByStatus.js\";\nimport { CmsTrashBin } from \"~/presentation/contentEntries/trashBin/CmsTrashBin.js\";\nimport { TrashEntryConfirmDialog } from \"~/admin/components/Dialogs/TrashEntryConfirmDialog.js\";\nimport { PublishEntryConfirmDialog } from \"~/admin/components/Dialogs/PublishEntryConfirmDialog.js\";\nimport { UnpublishEntryConfirmDialog } from \"~/admin/components/Dialogs/UnpublishEntryConfirmDialog.js\";\nimport { DuplicateEntryConfirmDialog } from \"~/admin/components/Dialogs/DuplicateEntryConfirmDialog.js\";\nimport { DeleteRevisionConfirmDialog } from \"~/admin/components/Dialogs/DeleteRevisionConfirmDialog.js\";\nimport { EditRevisionNoteDialog } from \"~/admin/components/Dialogs/EditRevisionNoteDialog.js\";\nimport {\n DELETE_REVISION_DIALOG,\n EDIT_REVISION_NOTE_DIALOG\n} from \"~/presentation/contentEntries/revisionsList/RevisionsListPresenter.js\";\nimport { RevisionSelector } from \"~/presentation/contentEntries/views/actions/RevisionSelector.js\";\nimport { ContentFormOptionsMenu } from \"~/presentation/contentEntries/views/actions/ContentFormOptionsMenu.js\";\nimport { SaveContentButton } from \"~/presentation/contentEntries/views/actions/SaveContentButton.js\";\nimport { SaveAndPublishButton } from \"~/presentation/contentEntries/views/actions/SaveAndPublishButton.js\";\nimport { DeleteEntryMenuItem } from \"~/presentation/contentEntries/views/actions/DeleteEntryMenuItem.js\";\nimport { ShowRevisionListMenuItem } from \"~/presentation/contentEntries/views/actions/ShowRevisionListMenuItem.js\";\nimport { CreateNewRevisionButton } from \"~/presentation/contentEntries/views/actions/CreateNewRevisionButton.js\";\nimport { PublishOnlyButton } from \"~/presentation/contentEntries/views/actions/PublishOnlyButton.js\";\n\nconst { Browser } = InternalContentEntryListConfig;\nconst { Actions } = InternalContentEntryEditorConfig;\n\nexport const ContentEntriesModule = () => {\n return (\n <>\n <AdminConfig>\n <AdminConfig.Dialog\n name={TRASH_ENTRY_DIALOG}\n element={<TrashEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={PUBLISH_ENTRY_DIALOG}\n element={<PublishEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={UNPUBLISH_ENTRY_DIALOG}\n element={<UnpublishEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={DUPLICATE_ENTRY_DIALOG}\n element={<DuplicateEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={DELETE_REVISION_DIALOG}\n element={<DeleteRevisionConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={EDIT_REVISION_NOTE_DIALOG}\n element={<EditRevisionNoteDialog />}\n />\n </AdminConfig>\n <InternalContentEntryListConfig>\n <AdvancedSearchConfigs />\n <IsModelPublishable>\n <Browser.Filter name={\"status\"} element={<FilterByStatus />} />\n <Browser.BulkAction name={\"publish\"} element={<ActionPublish />} />\n <Browser.BulkAction name={\"unpublish\"} element={<ActionUnpublish />} />\n </IsModelPublishable>\n <Browser.Sidebar.Footer name={\"trashBin\"} element={<CmsTrashBin />} />\n <Browser.BulkAction name={\"move\"} element={<ActionMove />} />\n <Browser.BulkAction name={\"delete\"} element={<ActionDelete />} />\n <Browser.Folder.Action name={\"edit\"} element={<EditFolder />} />\n <Browser.Folder.Action name={\"permissions\"} element={<SetFolderPermissions />} />\n <Browser.Folder.Action name={\"delete\"} element={<DeleteFolder />} />\n <Browser.Entry.Action name={\"edit\"} element={<EditEntry />} />\n <IsModelPublishable>\n <Browser.Entry.Action name={\"status\"} element={<ChangeEntryStatus />} />\n </IsModelPublishable>\n <Browser.Entry.Action name={\"move\"} element={<MoveEntry />} />\n <Browser.Entry.Action name={\"duplicate\"} element={<DuplicateEntry />} />\n <Browser.Entry.Action name={\"delete\"} element={<DeleteEntry />} after={\"$last\"} />\n <Browser.Table.Column\n name={\"name\"}\n header={\"Name\"}\n cell={<CellName />}\n sortable={true}\n hideable={false}\n size={200}\n />\n <Browser.Table.Column name={\"createdBy\"} header={\"Author\"} cell={<CellAuthor />} />\n <Browser.Table.Column\n name={\"createdOn\"}\n header={\"Created\"}\n cell={<CellCreated />}\n sortable={true}\n />\n <Browser.Table.Column\n name={\"savedOn\"}\n header={\"Modified\"}\n cell={<CellModified />}\n sortable={true}\n />\n <IsModelPublishable>\n <Browser.Table.Column\n name={\"status\"}\n header={\"Status\"}\n cell={<CellStatus />}\n truncate={false}\n />\n <Browser.Table.Column\n name={\"live\"}\n header={\"Live\"}\n truncate={false}\n sortable={true}\n cell={<CellLive />}\n />\n </IsModelPublishable>\n <Browser.Table.Column\n name={\"actions\"}\n header={\"\"}\n cell={<CellActions />}\n size={56}\n resizable={false}\n hideable={false}\n truncate={false}\n className={\"flex justify-center\"}\n />\n </InternalContentEntryListConfig>\n <InternalContentEntryEditorConfig>\n <IsModelPublishable>\n <Actions.ButtonAction\n name={\"revisionSelector\"}\n element={<RevisionSelector />}\n />\n </IsModelPublishable>\n <Actions.ButtonAction name={\"optionsMenu\"} element={<ContentFormOptionsMenu />} />\n <Actions.ButtonAction name={\"save\"} element={<SaveContentButton />} />\n <IsModelPublishable>\n <Actions.ButtonAction\n name={\"cms/createNewRevision\"}\n element={<CreateNewRevisionButton />}\n />\n <Actions.ButtonAction name={\"publish\"} element={<SaveAndPublishButton />} />\n <Actions.ButtonAction name={\"publishOnly\"} element={<PublishOnlyButton />} />\n </IsModelPublishable>\n <Actions.MenuItemAction\n name={\"delete\"}\n element={<DeleteEntryMenuItem />}\n after={\"$last\"}\n />\n <IsModelPublishable>\n <Actions.MenuItemAction\n name={\"showRevisionsList\"}\n element={<ShowRevisionListMenuItem />}\n />\n </IsModelPublishable>\n </InternalContentEntryEditorConfig>\n </>\n );\n};\n"],"names":["Browser","InternalContentEntryListConfig","Actions","InternalContentEntryEditorConfig","ContentEntriesModule","AdminConfig","TRASH_ENTRY_DIALOG","TrashEntryConfirmDialog","PUBLISH_ENTRY_DIALOG","PublishEntryConfirmDialog","UNPUBLISH_ENTRY_DIALOG","UnpublishEntryConfirmDialog","DUPLICATE_ENTRY_DIALOG","DuplicateEntryConfirmDialog","DELETE_REVISION_DIALOG","DeleteRevisionConfirmDialog","EDIT_REVISION_NOTE_DIALOG","EditRevisionNoteDialog","AdvancedSearchConfigs","IsModelPublishable","FilterByStatus","ActionPublish","ActionUnpublish","CmsTrashBin","ActionMove","ActionDelete","EditFolder","SetFolderPermissions","DeleteFolder","EditEntry","ChangeEntryStatus","MoveEntry","DuplicateEntry","DeleteEntry","CellName","CellAuthor","CellCreated","CellModified","CellStatus","CellLive","CellActions","RevisionSelector","ContentFormOptionsMenu","SaveContentButton","CreateNewRevisionButton","SaveAndPublishButton","PublishOnlyButton","DeleteEntryMenuItem","ShowRevisionListMenuItem"],"mappings":"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"}
1
+ {"version":3,"file":"ContentEntriesModule.js","sources":["../src/ContentEntriesModule.tsx"],"sourcesContent":["import React from \"react\";\nimport { AdminConfig } from \"@webiny/app-admin\";\nimport { AdvancedSearchConfigs } from \"@webiny/app-aco/components/AdvancedSearch/AdvancedSearchConfigs\";\nimport {\n InternalContentEntryEditorConfig,\n InternalContentEntryListConfig\n} from \"~/admin/config/contentEntries/index.js\";\n\nimport {\n ActionDelete,\n ActionMove,\n ActionPublish,\n ActionUnpublish\n} from \"~/admin/components/ContentEntries/BulkActions/index.js\";\n\nimport {\n TRASH_ENTRY_DIALOG,\n PUBLISH_ENTRY_DIALOG,\n UNPUBLISH_ENTRY_DIALOG,\n DUPLICATE_ENTRY_DIALOG\n} from \"~/presentation/contentEntries/list/ContentEntriesPresenter.js\";\nimport { DeleteFolder, EditFolder, SetFolderPermissions } from \"@webiny/app-aco\";\nimport {\n ChangeEntryStatus,\n DeleteEntry,\n DuplicateEntry,\n EditEntry,\n MoveEntry\n} from \"~/admin/components/ContentEntries/Table/Actions/index.js\";\nimport {\n CellActions,\n CellAuthor,\n CellCreated,\n CellLive,\n CellModified,\n CellName,\n CellStatus\n} from \"~/admin/components/ContentEntries/Table/Cells/index.js\";\nimport { IsModelPublishable } from \"~/admin/components/IsModelPublishable.js\";\nimport { FilterByStatus } from \"~/admin/components/ContentEntries/FilterByStatus.js\";\nimport { Ref } from \"~/admin/components/ContentEntries/Filters/RefFieldRenderer.js\";\nimport { CmsTrashBin } from \"~/presentation/contentEntries/trashBin/CmsTrashBin.js\";\nimport { TrashEntryConfirmDialog } from \"~/admin/components/Dialogs/TrashEntryConfirmDialog.js\";\nimport { PublishEntryConfirmDialog } from \"~/admin/components/Dialogs/PublishEntryConfirmDialog.js\";\nimport { UnpublishEntryConfirmDialog } from \"~/admin/components/Dialogs/UnpublishEntryConfirmDialog.js\";\nimport { DuplicateEntryConfirmDialog } from \"~/admin/components/Dialogs/DuplicateEntryConfirmDialog.js\";\nimport { DeleteRevisionConfirmDialog } from \"~/admin/components/Dialogs/DeleteRevisionConfirmDialog.js\";\nimport { EditRevisionNoteDialog } from \"~/admin/components/Dialogs/EditRevisionNoteDialog.js\";\nimport {\n DELETE_REVISION_DIALOG,\n EDIT_REVISION_NOTE_DIALOG\n} from \"~/presentation/contentEntries/revisionsList/RevisionsListPresenter.js\";\nimport { RevisionSelector } from \"~/presentation/contentEntries/views/actions/RevisionSelector.js\";\nimport { ContentFormOptionsMenu } from \"~/presentation/contentEntries/views/actions/ContentFormOptionsMenu.js\";\nimport { SaveContentButton } from \"~/presentation/contentEntries/views/actions/SaveContentButton.js\";\nimport { SaveAndPublishButton } from \"~/presentation/contentEntries/views/actions/SaveAndPublishButton.js\";\nimport { DeleteEntryMenuItem } from \"~/presentation/contentEntries/views/actions/DeleteEntryMenuItem.js\";\nimport { ShowRevisionListMenuItem } from \"~/presentation/contentEntries/views/actions/ShowRevisionListMenuItem.js\";\nimport { CreateNewRevisionButton } from \"~/presentation/contentEntries/views/actions/CreateNewRevisionButton.js\";\nimport { PublishOnlyButton } from \"~/presentation/contentEntries/views/actions/PublishOnlyButton.js\";\n\nconst { Browser } = InternalContentEntryListConfig;\nconst { Actions } = InternalContentEntryEditorConfig;\n\nexport const ContentEntriesModule = () => {\n return (\n <>\n <AdminConfig>\n <AdminConfig.Dialog\n name={TRASH_ENTRY_DIALOG}\n element={<TrashEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={PUBLISH_ENTRY_DIALOG}\n element={<PublishEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={UNPUBLISH_ENTRY_DIALOG}\n element={<UnpublishEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={DUPLICATE_ENTRY_DIALOG}\n element={<DuplicateEntryConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={DELETE_REVISION_DIALOG}\n element={<DeleteRevisionConfirmDialog />}\n />\n <AdminConfig.Dialog\n name={EDIT_REVISION_NOTE_DIALOG}\n element={<EditRevisionNoteDialog />}\n />\n </AdminConfig>\n <InternalContentEntryListConfig>\n <AdvancedSearchConfigs />\n <IsModelPublishable>\n <Browser.Filter name={\"status\"} element={<FilterByStatus />} />\n <Browser.BulkAction name={\"publish\"} element={<ActionPublish />} />\n <Browser.BulkAction name={\"unpublish\"} element={<ActionUnpublish />} />\n </IsModelPublishable>\n <Browser.Sidebar.Footer name={\"trashBin\"} element={<CmsTrashBin />} />\n <Browser.BulkAction name={\"move\"} element={<ActionMove />} />\n <Browser.BulkAction name={\"delete\"} element={<ActionDelete />} />\n <Browser.Folder.Action name={\"edit\"} element={<EditFolder />} />\n <Browser.Folder.Action name={\"permissions\"} element={<SetFolderPermissions />} />\n <Browser.Folder.Action name={\"delete\"} element={<DeleteFolder />} />\n <Browser.Entry.Action name={\"edit\"} element={<EditEntry />} />\n <IsModelPublishable>\n <Browser.Entry.Action name={\"status\"} element={<ChangeEntryStatus />} />\n </IsModelPublishable>\n <Browser.Entry.Action name={\"move\"} element={<MoveEntry />} />\n <Browser.Entry.Action name={\"duplicate\"} element={<DuplicateEntry />} />\n <Browser.Entry.Action name={\"delete\"} element={<DeleteEntry />} after={\"$last\"} />\n <Browser.Table.Column\n name={\"name\"}\n header={\"Name\"}\n cell={<CellName />}\n sortable={true}\n hideable={false}\n size={200}\n />\n <Browser.Table.Column name={\"createdBy\"} header={\"Author\"} cell={<CellAuthor />} />\n <Browser.Table.Column\n name={\"createdOn\"}\n header={\"Created\"}\n cell={<CellCreated />}\n sortable={true}\n />\n <Browser.Table.Column\n name={\"savedOn\"}\n header={\"Modified\"}\n cell={<CellModified />}\n sortable={true}\n />\n <IsModelPublishable>\n <Browser.Table.Column\n name={\"status\"}\n header={\"Status\"}\n cell={<CellStatus />}\n truncate={false}\n />\n <Browser.Table.Column\n name={\"live\"}\n header={\"Live\"}\n truncate={false}\n sortable={true}\n cell={<CellLive />}\n />\n </IsModelPublishable>\n <Browser.Table.Column\n name={\"actions\"}\n header={\"\"}\n cell={<CellActions />}\n size={56}\n resizable={false}\n hideable={false}\n truncate={false}\n className={\"flex justify-center\"}\n />\n <Browser.AdvancedSearch.FieldRenderer\n name={\"ref\"}\n type={Browser.AdvancedSearch.FieldRenderer.FieldType.REF}\n element={<Ref />}\n />\n </InternalContentEntryListConfig>\n <InternalContentEntryEditorConfig>\n <IsModelPublishable>\n <Actions.ButtonAction\n name={\"revisionSelector\"}\n element={<RevisionSelector />}\n />\n </IsModelPublishable>\n <Actions.ButtonAction name={\"optionsMenu\"} element={<ContentFormOptionsMenu />} />\n <Actions.ButtonAction name={\"save\"} element={<SaveContentButton />} />\n <IsModelPublishable>\n <Actions.ButtonAction\n name={\"cms/createNewRevision\"}\n element={<CreateNewRevisionButton />}\n />\n <Actions.ButtonAction name={\"publish\"} element={<SaveAndPublishButton />} />\n <Actions.ButtonAction name={\"publishOnly\"} element={<PublishOnlyButton />} />\n </IsModelPublishable>\n <Actions.MenuItemAction\n name={\"delete\"}\n element={<DeleteEntryMenuItem />}\n after={\"$last\"}\n />\n <IsModelPublishable>\n <Actions.MenuItemAction\n name={\"showRevisionsList\"}\n element={<ShowRevisionListMenuItem />}\n />\n </IsModelPublishable>\n </InternalContentEntryEditorConfig>\n </>\n );\n};\n"],"names":["Browser","InternalContentEntryListConfig","Actions","InternalContentEntryEditorConfig","ContentEntriesModule","AdminConfig","TRASH_ENTRY_DIALOG","TrashEntryConfirmDialog","PUBLISH_ENTRY_DIALOG","PublishEntryConfirmDialog","UNPUBLISH_ENTRY_DIALOG","UnpublishEntryConfirmDialog","DUPLICATE_ENTRY_DIALOG","DuplicateEntryConfirmDialog","DELETE_REVISION_DIALOG","DeleteRevisionConfirmDialog","EDIT_REVISION_NOTE_DIALOG","EditRevisionNoteDialog","AdvancedSearchConfigs","IsModelPublishable","FilterByStatus","ActionPublish","ActionUnpublish","CmsTrashBin","ActionMove","ActionDelete","EditFolder","SetFolderPermissions","DeleteFolder","EditEntry","ChangeEntryStatus","MoveEntry","DuplicateEntry","DeleteEntry","CellName","CellAuthor","CellCreated","CellModified","CellStatus","CellLive","CellActions","Ref","RevisionSelector","ContentFormOptionsMenu","SaveContentButton","CreateNewRevisionButton","SaveAndPublishButton","PublishOnlyButton","DeleteEntryMenuItem","ShowRevisionListMenuItem"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,MAAM,EAAEA,SAAAA,OAAO,EAAE,GAAGC;AACpB,MAAM,EAAEC,SAAAA,OAAO,EAAE,GAAGC;AAEb,MAAMC,uBAAuB,IACzB,WAAP,GACI,wDACI,oBAACC,aAAWA,MAAAA,WAAAA,GACR,oBAACA,YAAY,MAAM;QACf,MAAMC;QACN,uBAAS,oBAACC,yBAAuBA;sBAErC,oBAACF,YAAY,MAAM;QACf,MAAMG;QACN,uBAAS,oBAACC,2BAAyBA;sBAEvC,oBAACJ,YAAY,MAAM;QACf,MAAMK;QACN,uBAAS,oBAACC,6BAA2BA;sBAEzC,oBAACN,YAAY,MAAM;QACf,MAAMO;QACN,uBAAS,oBAACC,6BAA2BA;sBAEzC,oBAACR,YAAY,MAAM;QACf,MAAMS;QACN,uBAAS,oBAACC,6BAA2BA;sBAEzC,oBAACV,YAAY,MAAM;QACf,MAAMW;QACN,uBAAS,oBAACC,wBAAsBA;uBAGxC,oBAAChB,gCAA8BA,MAAAA,WAAAA,GAC3B,oBAACiB,uBAAqBA,OAAAA,WAAAA,GACtB,oBAACC,oBAAkBA,MAAAA,WAAAA,GACf,oBAACnB,QAAQ,MAAM;QAAC,MAAM;QAAU,uBAAS,oBAACoB,gBAAcA;sBACxD,oBAACpB,QAAQ,UAAU;QAAC,MAAM;QAAW,uBAAS,oBAACqB,eAAaA;sBAC5D,oBAACrB,QAAQ,UAAU;QAAC,MAAM;QAAa,uBAAS,oBAACsB,iBAAeA;uBAEpE,oBAACtB,QAAQ,OAAO,CAAC,MAAM;QAAC,MAAM;QAAY,uBAAS,oBAACuB,aAAWA;sBAC/D,oBAACvB,QAAQ,UAAU;QAAC,MAAM;QAAQ,uBAAS,oBAACwB,YAAUA;sBACtD,oBAACxB,QAAQ,UAAU;QAAC,MAAM;QAAU,uBAAS,oBAACyB,cAAYA;sBAC1D,oBAACzB,QAAQ,MAAM,CAAC,MAAM;QAAC,MAAM;QAAQ,uBAAS,oBAAC0B,YAAUA;sBACzD,oBAAC1B,QAAQ,MAAM,CAAC,MAAM;QAAC,MAAM;QAAe,uBAAS,oBAAC2B,sBAAoBA;sBAC1E,oBAAC3B,QAAQ,MAAM,CAAC,MAAM;QAAC,MAAM;QAAU,uBAAS,oBAAC4B,cAAYA;sBAC7D,oBAAC5B,QAAQ,KAAK,CAAC,MAAM;QAAC,MAAM;QAAQ,uBAAS,oBAAC6B,WAASA;sBACvD,oBAACV,oBAAkBA,MAAAA,WAAAA,GACf,oBAACnB,QAAQ,KAAK,CAAC,MAAM;QAAC,MAAM;QAAU,uBAAS,oBAAC8B,mBAAiBA;uBAErE,oBAAC9B,QAAQ,KAAK,CAAC,MAAM;QAAC,MAAM;QAAQ,uBAAS,oBAAC+B,WAASA;sBACvD,oBAAC/B,QAAQ,KAAK,CAAC,MAAM;QAAC,MAAM;QAAa,uBAAS,oBAACgC,gBAAcA;sBACjE,oBAAChC,QAAQ,KAAK,CAAC,MAAM;QAAC,MAAM;QAAU,uBAAS,oBAACiC,aAAWA;QAAK,OAAO;sBACvE,oBAACjC,QAAQ,KAAK,CAAC,MAAM;QACjB,MAAM;QACN,QAAQ;QACR,oBAAM,oBAACkC,UAAQA;QACf,UAAU;QACV,UAAU;QACV,MAAM;sBAEV,oBAAClC,QAAQ,KAAK,CAAC,MAAM;QAAC,MAAM;QAAa,QAAQ;QAAU,oBAAM,oBAACmC,YAAUA;sBAC5E,oBAACnC,QAAQ,KAAK,CAAC,MAAM;QACjB,MAAM;QACN,QAAQ;QACR,oBAAM,oBAACoC,aAAWA;QAClB,UAAU;sBAEd,oBAACpC,QAAQ,KAAK,CAAC,MAAM;QACjB,MAAM;QACN,QAAQ;QACR,oBAAM,oBAACqC,cAAYA;QACnB,UAAU;sBAEd,oBAAClB,oBAAkBA,MAAAA,WAAAA,GACf,oBAACnB,QAAQ,KAAK,CAAC,MAAM;QACjB,MAAM;QACN,QAAQ;QACR,oBAAM,oBAACsC,YAAUA;QACjB,UAAU;sBAEd,oBAACtC,QAAQ,KAAK,CAAC,MAAM;QACjB,MAAM;QACN,QAAQ;QACR,UAAU;QACV,UAAU;QACV,oBAAM,oBAACuC,UAAQA;uBAGvB,oBAACvC,QAAQ,KAAK,CAAC,MAAM;QACjB,MAAM;QACN,QAAQ;QACR,oBAAM,oBAACwC,aAAWA;QAClB,MAAM;QACN,WAAW;QACX,UAAU;QACV,UAAU;QACV,WAAW;sBAEf,oBAACxC,QAAQ,cAAc,CAAC,aAAa;QACjC,MAAM;QACN,MAAMA,QAAQ,cAAc,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG;QACxD,uBAAS,oBAACyC,KAAGA;uBAGrB,oBAACtC,kCAAgCA,MAAAA,WAAAA,GAC7B,oBAACgB,oBAAkBA,MAAAA,WAAAA,GACf,oBAACjB,QAAQ,YAAY;QACjB,MAAM;QACN,uBAAS,oBAACwC,kBAAgBA;uBAGlC,oBAACxC,QAAQ,YAAY;QAAC,MAAM;QAAe,uBAAS,oBAACyC,wBAAsBA;sBAC3E,oBAACzC,QAAQ,YAAY;QAAC,MAAM;QAAQ,uBAAS,oBAAC0C,mBAAiBA;sBAC/D,oBAACzB,oBAAkBA,MAAAA,WAAAA,GACf,oBAACjB,QAAQ,YAAY;QACjB,MAAM;QACN,uBAAS,oBAAC2C,yBAAuBA;sBAErC,oBAAC3C,QAAQ,YAAY;QAAC,MAAM;QAAW,uBAAS,oBAAC4C,sBAAoBA;sBACrE,oBAAC5C,QAAQ,YAAY;QAAC,MAAM;QAAe,uBAAS,oBAAC6C,mBAAiBA;uBAE1E,oBAAC7C,QAAQ,cAAc;QACnB,MAAM;QACN,uBAAS,oBAAC8C,qBAAmBA;QAC7B,OAAO;sBAEX,oBAAC7B,oBAAkBA,MAAAA,WAAAA,GACf,oBAACjB,QAAQ,cAAc;QACnB,MAAM;QACN,uBAAS,oBAAC+C,0BAAwBA"}
@@ -0,0 +1,2 @@
1
+ import React from "react";
2
+ export declare const Ref: () => React.JSX.Element;
@@ -0,0 +1,84 @@
1
+ import react, { useEffect, useMemo } from "react";
2
+ import { observer } from "mobx-react-lite";
3
+ import { Bind } from "@webiny/form";
4
+ import { AutoComplete } from "@webiny/admin-ui";
5
+ import { DiContainerProvider, useContainer, useFeature } from "@webiny/app";
6
+ import { ContentEntryListConfig } from "../../../config/contentEntries/index.js";
7
+ import { RefSingleAutocompletePresenterFeature } from "../../../../presentation/fieldRenderers/ref/autocomplete/single/feature.js";
8
+ const { useInputField: useInputField } = ContentEntryListConfig.Browser.AdvancedSearch.FieldRenderer;
9
+ const parseValue = (value)=>{
10
+ if ("string" != typeof value || !value) return null;
11
+ try {
12
+ const parsed = JSON.parse(value);
13
+ if (!parsed?.entryId || !parsed?.modelId) return null;
14
+ return {
15
+ entryId: parsed.entryId,
16
+ modelId: parsed.modelId
17
+ };
18
+ } catch {
19
+ return null;
20
+ }
21
+ };
22
+ const Ref = ()=>{
23
+ const { name, field } = useInputField();
24
+ const parentContainer = useContainer();
25
+ const scopedContainer = useMemo(()=>{
26
+ const child = parentContainer.createChildContainer();
27
+ RefSingleAutocompletePresenterFeature.register(child);
28
+ return child;
29
+ }, [
30
+ field.value
31
+ ]);
32
+ return /*#__PURE__*/ react.createElement(DiContainerProvider, {
33
+ container: scopedContainer,
34
+ key: field.value
35
+ }, /*#__PURE__*/ react.createElement(Bind, {
36
+ name: name
37
+ }, (bind)=>/*#__PURE__*/ react.createElement(RefInner, {
38
+ bind: bind,
39
+ modelIds: field.settings.modelIds
40
+ })));
41
+ };
42
+ const RefInner = observer(({ bind, modelIds })=>{
43
+ const { presenter } = useFeature(RefSingleAutocompletePresenterFeature);
44
+ useEffect(()=>{
45
+ const value = parseValue(bind.value);
46
+ presenter.init({
47
+ modelIds,
48
+ value: value ? {
49
+ id: value.entryId,
50
+ modelId: value.modelId
51
+ } : null
52
+ });
53
+ }, []);
54
+ const vm = presenter.vm;
55
+ return /*#__PURE__*/ react.createElement(AutoComplete, {
56
+ label: "Value",
57
+ size: "lg",
58
+ loading: vm.loading,
59
+ value: vm.value,
60
+ options: vm.options,
61
+ validation: bind.validation,
62
+ onValueSearch: (query)=>presenter.search(query),
63
+ onValueChange: (entryId)=>{
64
+ if (!entryId) {
65
+ presenter.clear();
66
+ bind.onChange("");
67
+ return;
68
+ }
69
+ const ref = presenter.select(entryId);
70
+ if (ref) bind.onChange(JSON.stringify({
71
+ entryId,
72
+ modelId: ref.modelId
73
+ }));
74
+ },
75
+ onValueReset: ()=>{
76
+ presenter.clear();
77
+ bind.onChange("");
78
+ },
79
+ displayResetAction: vm.canReset
80
+ });
81
+ });
82
+ export { Ref };
83
+
84
+ //# sourceMappingURL=RefFieldRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin/components/ContentEntries/Filters/RefFieldRenderer.js","sources":["../../../../../src/admin/components/ContentEntries/Filters/RefFieldRenderer.tsx"],"sourcesContent":["import React, { useEffect, useMemo } from \"react\";\nimport { observer } from \"mobx-react-lite\";\nimport { Bind } from \"@webiny/form\";\nimport type { BindComponentRenderProp } from \"@webiny/form\";\nimport { AutoComplete } from \"@webiny/admin-ui\";\nimport { DiContainerProvider, useContainer, useFeature } from \"@webiny/app\";\nimport { ContentEntryListConfig } from \"~/admin/config/contentEntries/index.js\";\nimport { RefSingleAutocompletePresenterFeature } from \"~/presentation/fieldRenderers/ref/autocomplete/single/feature.js\";\n\nconst { useInputField } = ContentEntryListConfig.Browser.AdvancedSearch.FieldRenderer;\n\n/**\n * The advanced search filter stores the selected reference as a JSON string\n * `{ entryId, modelId }`. `GraphQLInputMapper` reads `entryId` from it to build the\n * `<fieldId>.entryId` where condition, and `modelId` is used to load the label back\n * when a saved filter is opened.\n */\ninterface RefFilterValue {\n entryId: string;\n modelId: string;\n}\n\nconst parseValue = (value: unknown): RefFilterValue | null => {\n if (typeof value !== \"string\" || !value) {\n return null;\n }\n try {\n const parsed = JSON.parse(value);\n if (!parsed?.entryId || !parsed?.modelId) {\n return null;\n }\n return { entryId: parsed.entryId, modelId: parsed.modelId };\n } catch {\n return null;\n }\n};\n\nexport const Ref = () => {\n const { name, field } = useInputField();\n const parentContainer = useContainer();\n\n const scopedContainer = useMemo(() => {\n const child = parentContainer.createChildContainer();\n RefSingleAutocompletePresenterFeature.register(child);\n return child;\n }, [field.value]);\n\n return (\n <DiContainerProvider container={scopedContainer} key={field.value}>\n <Bind name={name}>\n {bind => <RefInner bind={bind} modelIds={field.settings.modelIds} />}\n </Bind>\n </DiContainerProvider>\n );\n};\n\ninterface RefInnerProps {\n bind: BindComponentRenderProp;\n modelIds: string[];\n}\n\nconst RefInner = observer(({ bind, modelIds }: RefInnerProps) => {\n const { presenter } = useFeature(RefSingleAutocompletePresenterFeature);\n\n useEffect(() => {\n const value = parseValue(bind.value);\n presenter.init({\n modelIds,\n value: value ? { id: value.entryId, modelId: value.modelId } : null\n });\n }, []);\n\n const vm = presenter.vm;\n\n return (\n <AutoComplete\n label={\"Value\"}\n size={\"lg\"}\n loading={vm.loading}\n value={vm.value}\n options={vm.options}\n validation={bind.validation}\n onValueSearch={query => presenter.search(query)}\n onValueChange={entryId => {\n if (!entryId) {\n presenter.clear();\n bind.onChange(\"\");\n return;\n }\n const ref = presenter.select(entryId);\n if (ref) {\n bind.onChange(JSON.stringify({ entryId, modelId: ref.modelId }));\n }\n }}\n onValueReset={() => {\n presenter.clear();\n bind.onChange(\"\");\n }}\n displayResetAction={vm.canReset}\n />\n );\n});\n"],"names":["useInputField","ContentEntryListConfig","parseValue","value","parsed","JSON","Ref","name","field","parentContainer","useContainer","scopedContainer","useMemo","child","RefSingleAutocompletePresenterFeature","DiContainerProvider","Bind","bind","RefInner","observer","modelIds","presenter","useFeature","useEffect","vm","AutoComplete","query","entryId","ref"],"mappings":";;;;;;;AASA,MAAM,EAAEA,eAAAA,aAAa,EAAE,GAAGC,uBAAuB,OAAO,CAAC,cAAc,CAAC,aAAa;AAarF,MAAMC,aAAa,CAACC;IAChB,IAAI,AAAiB,YAAjB,OAAOA,SAAsB,CAACA,OAC9B,OAAO;IAEX,IAAI;QACA,MAAMC,SAASC,KAAK,KAAK,CAACF;QAC1B,IAAI,CAACC,QAAQ,WAAW,CAACA,QAAQ,SAC7B,OAAO;QAEX,OAAO;YAAE,SAASA,OAAO,OAAO;YAAE,SAASA,OAAO,OAAO;QAAC;IAC9D,EAAE,OAAM;QACJ,OAAO;IACX;AACJ;AAEO,MAAME,MAAM;IACf,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGR;IACxB,MAAMS,kBAAkBC;IAExB,MAAMC,kBAAkBC,QAAQ;QAC5B,MAAMC,QAAQJ,gBAAgB,oBAAoB;QAClDK,sCAAsC,QAAQ,CAACD;QAC/C,OAAOA;IACX,GAAG;QAACL,MAAM,KAAK;KAAC;IAEhB,OAAO,WAAP,GACI,oBAACO,qBAAmBA;QAAC,WAAWJ;QAAiB,KAAKH,MAAM,KAAK;qBAC7D,oBAACQ,MAAIA;QAAC,MAAMT;OACPU,CAAAA,OAAAA,WAAAA,GAAQ,oBAACC,UAAQA;YAAC,MAAMD;YAAM,UAAUT,MAAM,QAAQ,CAAC,QAAQ;;AAIhF;AAOA,MAAMU,WAAWC,SAAS,CAAC,EAAEF,IAAI,EAAEG,QAAQ,EAAiB;IACxD,MAAM,EAAEC,SAAS,EAAE,GAAGC,WAAWR;IAEjCS,UAAU;QACN,MAAMpB,QAAQD,WAAWe,KAAK,KAAK;QACnCI,UAAU,IAAI,CAAC;YACXD;YACA,OAAOjB,QAAQ;gBAAE,IAAIA,MAAM,OAAO;gBAAE,SAASA,MAAM,OAAO;YAAC,IAAI;QACnE;IACJ,GAAG,EAAE;IAEL,MAAMqB,KAAKH,UAAU,EAAE;IAEvB,OAAO,WAAP,GACI,oBAACI,cAAYA;QACT,OAAO;QACP,MAAM;QACN,SAASD,GAAG,OAAO;QACnB,OAAOA,GAAG,KAAK;QACf,SAASA,GAAG,OAAO;QACnB,YAAYP,KAAK,UAAU;QAC3B,eAAeS,CAAAA,QAASL,UAAU,MAAM,CAACK;QACzC,eAAeC,CAAAA;YACX,IAAI,CAACA,SAAS;gBACVN,UAAU,KAAK;gBACfJ,KAAK,QAAQ,CAAC;gBACd;YACJ;YACA,MAAMW,MAAMP,UAAU,MAAM,CAACM;YAC7B,IAAIC,KACAX,KAAK,QAAQ,CAACZ,KAAK,SAAS,CAAC;gBAAEsB;gBAAS,SAASC,IAAI,OAAO;YAAC;QAErE;QACA,cAAc;YACVP,UAAU,KAAK;YACfJ,KAAK,QAAQ,CAAC;QAClB;QACA,oBAAoBO,GAAG,QAAQ;;AAG3C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/app-headless-cms",
3
- "version": "6.5.0-beta.6",
3
+ "version": "6.5.0-beta.8",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -26,32 +26,32 @@
26
26
  "@fortawesome/free-regular-svg-icons": "7.3.1",
27
27
  "@fortawesome/free-solid-svg-icons": "7.3.1",
28
28
  "@fortawesome/react-fontawesome": "3.5.0",
29
- "@lexical/utils": "0.51.0",
29
+ "@lexical/utils": "0.52.0",
30
30
  "@types/react": "18.3.31",
31
- "@webiny/admin-ui": "6.5.0-beta.6",
32
- "@webiny/app": "6.5.0-beta.6",
33
- "@webiny/app-aco": "6.5.0-beta.6",
34
- "@webiny/app-admin": "6.5.0-beta.6",
35
- "@webiny/app-graphql-playground": "6.5.0-beta.6",
36
- "@webiny/app-headless-cms-common": "6.5.0-beta.6",
37
- "@webiny/cms-sdk": "6.5.0-beta.6",
31
+ "@webiny/admin-ui": "6.5.0-beta.8",
32
+ "@webiny/app": "6.5.0-beta.8",
33
+ "@webiny/app-aco": "6.5.0-beta.8",
34
+ "@webiny/app-admin": "6.5.0-beta.8",
35
+ "@webiny/app-graphql-playground": "6.5.0-beta.8",
36
+ "@webiny/app-headless-cms-common": "6.5.0-beta.8",
37
+ "@webiny/cms-sdk": "6.5.0-beta.8",
38
38
  "@webiny/di": "1.1.0",
39
- "@webiny/feature": "6.5.0-beta.6",
40
- "@webiny/form": "6.5.0-beta.6",
41
- "@webiny/frontend-settings": "6.5.0-beta.6",
42
- "@webiny/icons": "6.5.0-beta.6",
43
- "@webiny/lexical-editor": "6.5.0-beta.6",
44
- "@webiny/lexical-nodes": "6.5.0-beta.6",
45
- "@webiny/plugins": "6.5.0-beta.6",
46
- "@webiny/react-composition": "6.5.0-beta.6",
47
- "@webiny/react-properties": "6.5.0-beta.6",
48
- "@webiny/utils": "6.5.0-beta.6",
49
- "@webiny/validation": "6.5.0-beta.6",
39
+ "@webiny/feature": "6.5.0-beta.8",
40
+ "@webiny/form": "6.5.0-beta.8",
41
+ "@webiny/frontend-settings": "6.5.0-beta.8",
42
+ "@webiny/icons": "6.5.0-beta.8",
43
+ "@webiny/lexical-editor": "6.5.0-beta.8",
44
+ "@webiny/lexical-nodes": "6.5.0-beta.8",
45
+ "@webiny/plugins": "6.5.0-beta.8",
46
+ "@webiny/react-composition": "6.5.0-beta.8",
47
+ "@webiny/react-properties": "6.5.0-beta.8",
48
+ "@webiny/utils": "6.5.0-beta.8",
49
+ "@webiny/validation": "6.5.0-beta.8",
50
50
  "dot-prop-immutable": "2.1.1",
51
51
  "graphql": "16.14.2",
52
52
  "graphql-tag": "2.12.7",
53
53
  "lodash": "4.18.1",
54
- "mobx": "7.0.5",
54
+ "mobx": "7.0.6",
55
55
  "mobx-react-lite": "5.1.0",
56
56
  "react": "18.3.1",
57
57
  "react-dnd": "16.0.1",
@@ -63,10 +63,10 @@
63
63
  "zod": "4.6.5"
64
64
  },
65
65
  "devDependencies": {
66
- "@webiny/build-tools": "6.5.0-beta.6",
66
+ "@webiny/build-tools": "6.5.0-beta.8",
67
67
  "rimraf": "6.1.3",
68
68
  "typescript": "7.0.2",
69
- "vitest": "5.0.2"
69
+ "vitest": "5.0.3"
70
70
  },
71
71
  "publishConfig": {
72
72
  "access": "public"
@@ -79,8 +79,10 @@ class ContentEntryFormPresenterImpl {
79
79
  }
80
80
  async saveRevision(options) {
81
81
  if (!this.form) return false;
82
+ const form = this.form;
83
+ const model = this.model;
82
84
  const skipValidation = options?.skipValidation ?? true;
83
- const data = await this.form.submit({
85
+ const data = await form.submit({
84
86
  skipValidation
85
87
  });
86
88
  if (!data) return false;
@@ -95,9 +97,10 @@ class ContentEntryFormPresenterImpl {
95
97
  skipValidation
96
98
  });
97
99
  runInAction(()=>{
100
+ if (this.form !== form) return;
98
101
  this.entry = entry;
99
- this.form.setData(entry.values);
100
- this.form.reset();
102
+ form.setData(entry.values);
103
+ form.reset();
101
104
  });
102
105
  } else {
103
106
  const createData = {
@@ -114,14 +117,15 @@ class ContentEntryFormPresenterImpl {
114
117
  }
115
118
  });
116
119
  runInAction(()=>{
120
+ if (this.form !== form) return;
117
121
  this.entry = entry;
118
- this.form.setData(entry.values);
119
- this.form.reset();
122
+ form.setData(entry.values);
123
+ form.reset();
120
124
  });
121
125
  }
122
126
  return true;
123
127
  } catch (error) {
124
- this.form.setErrors(toFormErrors(error, this.model));
128
+ if (this.form === form) form.setErrors(toFormErrors(error, model));
125
129
  return false;
126
130
  } finally{
127
131
  runInAction(()=>{
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/form/ContentEntryFormPresenter.js","sources":["../../../../src/presentation/contentEntries/form/ContentEntryFormPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction, toJS } from \"mobx\";\nimport { FormModel, FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { GetEntryUseCase } from \"~/features/contentEntry/getEntry/abstractions.js\";\nimport { CreateEntryUseCase } from \"~/features/contentEntry/createEntry/abstractions.js\";\nimport { UpdateEntryUseCase } from \"~/features/contentEntry/updateEntry/abstractions.js\";\nimport { PublishEntryUseCase } from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryUseCase } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { DeleteEntryUseCase } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionUseCase } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n ContentEntryFormModelModifier,\n ContentEntryFormPresenter as Abstraction\n} from \"./abstractions.js\";\nimport { TRASH_ENTRY_DIALOG } from \"~/presentation/contentEntries/list/ContentEntriesPresenter.js\";\nimport { CreateRevisionFromUseCase } from \"~/features/contentEntry/createRevisionFrom/abstractions.js\";\nimport { toFormErrors } from \"./toFormErrors.js\";\n\ninterface PublishEntryDialogData {\n revisionDescription: string;\n}\n\ninterface SaveEntryParams {\n entry: CmsContentEntry;\n data: Record<string, unknown>;\n skipValidation?: boolean;\n}\n\nexport const PUBLISH_ENTRY_DIALOG = \"publish-entry\";\n\nclass ContentEntryFormPresenterImpl implements Abstraction.Interface {\n private entry: CmsContentEntry | null = null;\n private form: FormModel.Interface | null = null;\n private loading: string | null = null;\n private folderId: string | null = null;\n\n constructor(\n private readonly formModelFactory: FormModelFactory.Interface,\n private readonly cmsFormModelBuilder: CmsFormModelBuilder.Interface,\n private readonly confirmation: Confirmation.Interface,\n private readonly modelAccessor: CmsModelContext.Interface,\n private readonly getEntryUseCase: GetEntryUseCase.Interface,\n private readonly createEntryUseCase: CreateEntryUseCase.Interface,\n private readonly createRevisionFromUseCase: CreateRevisionFromUseCase.Interface,\n private readonly updateEntryUseCase: UpdateEntryUseCase.Interface,\n private readonly publishEntryUseCase: PublishEntryUseCase.Interface,\n private readonly unpublishEntryUseCase: UnpublishEntryUseCase.Interface,\n private readonly deleteEntryUseCase: DeleteEntryUseCase.Interface,\n private readonly updateRevisionDescriptionUseCase: UpdateRevisionDescriptionUseCase.Interface,\n private readonly formModelModifiers: ContentEntryFormModelModifier.Interface[]\n ) {\n makeAutoObservable<\n ContentEntryFormPresenterImpl,\n | \"formModelFactory\"\n | \"cmsFormModelBuilder\"\n | \"confirmation\"\n | \"modelAccessor\"\n | \"getEntryUseCase\"\n | \"createEntryUseCase\"\n | \"updateEntryUseCase\"\n | \"publishEntryUseCase\"\n | \"unpublishEntryUseCase\"\n | \"deleteEntryUseCase\"\n | \"updateRevisionDescriptionUseCase\"\n | \"formModelModifiers\"\n >(this, {\n formModelFactory: false,\n cmsFormModelBuilder: false,\n confirmation: false,\n modelAccessor: false,\n getEntryUseCase: false,\n createEntryUseCase: false,\n updateEntryUseCase: false,\n publishEntryUseCase: false,\n unpublishEntryUseCase: false,\n deleteEntryUseCase: false,\n updateRevisionDescriptionUseCase: false,\n formModelModifiers: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): Abstraction.ViewModel {\n const entry = this.entry;\n const meta = entry?.meta;\n const isLocked = meta?.locked ?? false;\n const status = meta?.status;\n /**\n * Can save if the entry is locked and published/unpublished - it will trigger create new revision.\n * Or if the entry is not locked and the form is not null (meaning we are creating a new entry or editing an existing one).\n */\n const canSave =\n (isLocked && (status === \"published\" || status === \"unpublished\")) ||\n (!isLocked && this.form !== null);\n\n return {\n loading: this.loading,\n model: this.model,\n entry: toJS(this.entry),\n form: this.form?.vm ?? null,\n canSave,\n status,\n canCreateNewRevision:\n !!status && canSave && [\"published\", \"unpublished\"].includes(status),\n canPublish: this.entry !== null && status !== \"published\",\n canUnpublish: this.entry !== null && status === \"published\",\n canDelete: this.entry !== null,\n isNewEntry: this.entry === null && this.form !== null,\n isDirty: this.form?.isDirty ?? false\n };\n }\n\n async saveRevision(options?: { skipValidation?: boolean }): Promise<boolean> {\n if (!this.form) {\n return false;\n }\n\n const skipValidation = options?.skipValidation ?? true;\n const data = await this.form.submit({ skipValidation });\n\n if (!data) {\n return false;\n }\n\n runInAction(() => {\n this.loading = \"Saving...\";\n });\n\n try {\n if (this.entry) {\n /**\n * In case the entry already exists, and it is NOT locked, we will update the existing revision.\n * If it is locked, we will create a new revision from the existing one, and then update that new revision.\n */\n const entry = await this.saveEntry({\n entry: this.entry,\n data,\n skipValidation\n });\n\n runInAction(() => {\n this.entry = entry;\n this.form!.setData(entry.values);\n this.form!.reset();\n });\n } else {\n const createData: Record<string, unknown> = { values: data };\n if (this.folderId) {\n createData.wbyAco_location = { folderId: this.folderId };\n }\n\n const entry = await this.createEntryUseCase.execute({\n model: this.model,\n data: createData,\n options: { skipValidation }\n });\n\n runInAction(() => {\n this.entry = entry;\n this.form!.setData(entry.values);\n this.form!.reset();\n });\n }\n\n return true;\n } catch (error) {\n this.form.setErrors(toFormErrors(error, this.model));\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async publishRevision(): Promise<boolean> {\n if (!this.entry) {\n return false;\n }\n\n const result = await this.confirmation.confirm<PublishEntryDialogData>(\n PUBLISH_ENTRY_DIALOG,\n { entry: this.entry }\n );\n\n if (result === false) {\n return false;\n }\n\n runInAction(() => {\n this.loading = \"Publishing...\";\n });\n\n try {\n if (result.revisionDescription) {\n await this.updateRevisionDescriptionUseCase.execute({\n model: this.model,\n id: this.entry.id,\n revisionDescription: result.revisionDescription\n });\n }\n\n const entry = await this.publishEntryUseCase.execute({\n model: this.model,\n revisionId: this.entry.id\n });\n\n runInAction(() => {\n this.entry = entry;\n });\n\n return true;\n } catch {\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async unpublishRevision(): Promise<boolean> {\n if (!this.entry) {\n return false;\n }\n\n this.loading = \"Unpublishing...\";\n\n try {\n const entry = await this.unpublishEntryUseCase.execute({\n model: this.model,\n revisionId: this.entry.id\n });\n\n runInAction(() => {\n this.entry = entry;\n });\n\n return true;\n } catch {\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async deleteEntry(): Promise<boolean> {\n if (!this.entry) {\n return false;\n }\n\n const model = this.model;\n const entry = this.entry;\n\n return this.confirmation.confirm(\n TRASH_ENTRY_DIALOG,\n { entryId: entry.entryId },\n async () => {\n try {\n await this.deleteEntryUseCase.execute({\n model,\n id: entry.entryId\n });\n\n runInAction(() => {\n this.entry = null;\n this.form = null;\n });\n\n return true;\n } catch {\n return false;\n }\n }\n );\n }\n\n async loadRevision(id: string): Promise<void> {\n this.loading = \"Loading entry...\";\n\n try {\n const entry = await this.getEntryUseCase.execute({\n model: this.model,\n id\n });\n\n runInAction(() => {\n this.entry = entry;\n this.buildAndPopulateForm(entry);\n });\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n setFolderId(folderId: string | null): void {\n this.folderId = folderId;\n }\n\n newEntry(initialValues?: Record<string, unknown>): void {\n this.entry = null;\n this.form = this.buildForm();\n if (initialValues) {\n this.form.setData(initialValues, { dirty: true });\n }\n }\n\n patchEntryMeta(meta: Partial<CmsContentEntry[\"meta\"]>): void {\n if (!this.entry) {\n return;\n }\n this.entry = {\n ...this.entry,\n meta: { ...this.entry.meta, ...meta }\n };\n }\n\n reset(): void {\n this.form = null;\n this.entry = null;\n }\n\n private buildForm(): FormModel.Interface {\n const formConfig = this.cmsFormModelBuilder.build(this.model);\n const form = this.formModelFactory.create(formConfig);\n for (const modifier of this.formModelModifiers) {\n modifier.modifyForm(form, this.model);\n }\n return form;\n }\n\n private buildAndPopulateForm(entry: CmsContentEntry): void {\n this.form = this.buildForm();\n this.form.setData(entry.values);\n this.form.reset();\n }\n /**\n * Depending on whether the entry is locked or not, this method will either create a new revision from the existing one and update it, or simply update the existing revision.\n */\n private async saveEntry(params: SaveEntryParams): Promise<any> {\n const { entry, data, skipValidation } = params;\n\n if (entry.meta.locked) {\n return await this.createRevisionFromUseCase.execute({\n model: this.model,\n revisionId: entry.id,\n data: {\n values: data\n },\n options: { skipValidation }\n });\n }\n return await this.updateEntryUseCase.execute({\n model: this.model,\n revisionId: entry.id,\n data: {\n values: data\n },\n options: { skipValidation }\n });\n }\n}\n\nexport const ContentEntryFormPresenter = Abstraction.createImplementation({\n implementation: ContentEntryFormPresenterImpl,\n dependencies: [\n FormModelFactory,\n CmsFormModelBuilder,\n Confirmation,\n CmsModelContext,\n GetEntryUseCase,\n CreateEntryUseCase,\n CreateRevisionFromUseCase,\n UpdateEntryUseCase,\n PublishEntryUseCase,\n UnpublishEntryUseCase,\n DeleteEntryUseCase,\n UpdateRevisionDescriptionUseCase,\n [ContentEntryFormModelModifier, { multiple: true }]\n ]\n});\n"],"names":["PUBLISH_ENTRY_DIALOG","ContentEntryFormPresenterImpl","formModelFactory","cmsFormModelBuilder","confirmation","modelAccessor","getEntryUseCase","createEntryUseCase","createRevisionFromUseCase","updateEntryUseCase","publishEntryUseCase","unpublishEntryUseCase","deleteEntryUseCase","updateRevisionDescriptionUseCase","formModelModifiers","makeAutoObservable","computed","entry","meta","isLocked","status","canSave","toJS","options","skipValidation","data","runInAction","createData","error","toFormErrors","result","model","TRASH_ENTRY_DIALOG","id","folderId","initialValues","formConfig","form","modifier","params","ContentEntryFormPresenter","Abstraction","FormModelFactory","CmsFormModelBuilder","Confirmation","CmsModelContext","GetEntryUseCase","CreateEntryUseCase","CreateRevisionFromUseCase","UpdateEntryUseCase","PublishEntryUseCase","UnpublishEntryUseCase","DeleteEntryUseCase","UpdateRevisionDescriptionUseCase","ContentEntryFormModelModifier"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/contentEntries/form/ContentEntryFormPresenter.js","sources":["../../../../src/presentation/contentEntries/form/ContentEntryFormPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction, toJS } from \"mobx\";\nimport { FormModel, FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { GetEntryUseCase } from \"~/features/contentEntry/getEntry/abstractions.js\";\nimport { CreateEntryUseCase } from \"~/features/contentEntry/createEntry/abstractions.js\";\nimport { UpdateEntryUseCase } from \"~/features/contentEntry/updateEntry/abstractions.js\";\nimport { PublishEntryUseCase } from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryUseCase } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { DeleteEntryUseCase } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionUseCase } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n ContentEntryFormModelModifier,\n ContentEntryFormPresenter as Abstraction\n} from \"./abstractions.js\";\nimport { TRASH_ENTRY_DIALOG } from \"~/presentation/contentEntries/list/ContentEntriesPresenter.js\";\nimport { CreateRevisionFromUseCase } from \"~/features/contentEntry/createRevisionFrom/abstractions.js\";\nimport { toFormErrors } from \"./toFormErrors.js\";\n\ninterface PublishEntryDialogData {\n revisionDescription: string;\n}\n\ninterface SaveEntryParams {\n entry: CmsContentEntry;\n data: Record<string, unknown>;\n skipValidation?: boolean;\n}\n\nexport const PUBLISH_ENTRY_DIALOG = \"publish-entry\";\n\nclass ContentEntryFormPresenterImpl implements Abstraction.Interface {\n private entry: CmsContentEntry | null = null;\n private form: FormModel.Interface | null = null;\n private loading: string | null = null;\n private folderId: string | null = null;\n\n constructor(\n private readonly formModelFactory: FormModelFactory.Interface,\n private readonly cmsFormModelBuilder: CmsFormModelBuilder.Interface,\n private readonly confirmation: Confirmation.Interface,\n private readonly modelAccessor: CmsModelContext.Interface,\n private readonly getEntryUseCase: GetEntryUseCase.Interface,\n private readonly createEntryUseCase: CreateEntryUseCase.Interface,\n private readonly createRevisionFromUseCase: CreateRevisionFromUseCase.Interface,\n private readonly updateEntryUseCase: UpdateEntryUseCase.Interface,\n private readonly publishEntryUseCase: PublishEntryUseCase.Interface,\n private readonly unpublishEntryUseCase: UnpublishEntryUseCase.Interface,\n private readonly deleteEntryUseCase: DeleteEntryUseCase.Interface,\n private readonly updateRevisionDescriptionUseCase: UpdateRevisionDescriptionUseCase.Interface,\n private readonly formModelModifiers: ContentEntryFormModelModifier.Interface[]\n ) {\n makeAutoObservable<\n ContentEntryFormPresenterImpl,\n | \"formModelFactory\"\n | \"cmsFormModelBuilder\"\n | \"confirmation\"\n | \"modelAccessor\"\n | \"getEntryUseCase\"\n | \"createEntryUseCase\"\n | \"updateEntryUseCase\"\n | \"publishEntryUseCase\"\n | \"unpublishEntryUseCase\"\n | \"deleteEntryUseCase\"\n | \"updateRevisionDescriptionUseCase\"\n | \"formModelModifiers\"\n >(this, {\n formModelFactory: false,\n cmsFormModelBuilder: false,\n confirmation: false,\n modelAccessor: false,\n getEntryUseCase: false,\n createEntryUseCase: false,\n updateEntryUseCase: false,\n publishEntryUseCase: false,\n unpublishEntryUseCase: false,\n deleteEntryUseCase: false,\n updateRevisionDescriptionUseCase: false,\n formModelModifiers: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): Abstraction.ViewModel {\n const entry = this.entry;\n const meta = entry?.meta;\n const isLocked = meta?.locked ?? false;\n const status = meta?.status;\n /**\n * Can save if the entry is locked and published/unpublished - it will trigger create new revision.\n * Or if the entry is not locked and the form is not null (meaning we are creating a new entry or editing an existing one).\n */\n const canSave =\n (isLocked && (status === \"published\" || status === \"unpublished\")) ||\n (!isLocked && this.form !== null);\n\n return {\n loading: this.loading,\n model: this.model,\n entry: toJS(this.entry),\n form: this.form?.vm ?? null,\n canSave,\n status,\n canCreateNewRevision:\n !!status && canSave && [\"published\", \"unpublished\"].includes(status),\n canPublish: this.entry !== null && status !== \"published\",\n canUnpublish: this.entry !== null && status === \"published\",\n canDelete: this.entry !== null,\n isNewEntry: this.entry === null && this.form !== null,\n isDirty: this.form?.isDirty ?? false\n };\n }\n\n async saveRevision(options?: { skipValidation?: boolean }): Promise<boolean> {\n if (!this.form) {\n return false;\n }\n\n /*\n * Saving is async, and the form can be reset or replaced by another entry before it\n * finishes. Keep hold of the form and model being saved, and only write the result back\n * while that form is still the one on screen.\n */\n const form = this.form;\n const model = this.model;\n\n const skipValidation = options?.skipValidation ?? true;\n const data = await form.submit({ skipValidation });\n\n if (!data) {\n return false;\n }\n\n runInAction(() => {\n this.loading = \"Saving...\";\n });\n\n try {\n if (this.entry) {\n /**\n * In case the entry already exists, and it is NOT locked, we will update the existing revision.\n * If it is locked, we will create a new revision from the existing one, and then update that new revision.\n */\n const entry = await this.saveEntry({\n entry: this.entry,\n data,\n skipValidation\n });\n\n runInAction(() => {\n if (this.form !== form) {\n return;\n }\n this.entry = entry;\n form.setData(entry.values);\n form.reset();\n });\n } else {\n const createData: Record<string, unknown> = { values: data };\n if (this.folderId) {\n createData.wbyAco_location = { folderId: this.folderId };\n }\n\n const entry = await this.createEntryUseCase.execute({\n model: this.model,\n data: createData,\n options: { skipValidation }\n });\n\n runInAction(() => {\n if (this.form !== form) {\n return;\n }\n this.entry = entry;\n form.setData(entry.values);\n form.reset();\n });\n }\n\n return true;\n } catch (error) {\n if (this.form === form) {\n form.setErrors(toFormErrors(error, model));\n }\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async publishRevision(): Promise<boolean> {\n if (!this.entry) {\n return false;\n }\n\n const result = await this.confirmation.confirm<PublishEntryDialogData>(\n PUBLISH_ENTRY_DIALOG,\n { entry: this.entry }\n );\n\n if (result === false) {\n return false;\n }\n\n runInAction(() => {\n this.loading = \"Publishing...\";\n });\n\n try {\n if (result.revisionDescription) {\n await this.updateRevisionDescriptionUseCase.execute({\n model: this.model,\n id: this.entry.id,\n revisionDescription: result.revisionDescription\n });\n }\n\n const entry = await this.publishEntryUseCase.execute({\n model: this.model,\n revisionId: this.entry.id\n });\n\n runInAction(() => {\n this.entry = entry;\n });\n\n return true;\n } catch {\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async unpublishRevision(): Promise<boolean> {\n if (!this.entry) {\n return false;\n }\n\n this.loading = \"Unpublishing...\";\n\n try {\n const entry = await this.unpublishEntryUseCase.execute({\n model: this.model,\n revisionId: this.entry.id\n });\n\n runInAction(() => {\n this.entry = entry;\n });\n\n return true;\n } catch {\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async deleteEntry(): Promise<boolean> {\n if (!this.entry) {\n return false;\n }\n\n const model = this.model;\n const entry = this.entry;\n\n return this.confirmation.confirm(\n TRASH_ENTRY_DIALOG,\n { entryId: entry.entryId },\n async () => {\n try {\n await this.deleteEntryUseCase.execute({\n model,\n id: entry.entryId\n });\n\n runInAction(() => {\n this.entry = null;\n this.form = null;\n });\n\n return true;\n } catch {\n return false;\n }\n }\n );\n }\n\n async loadRevision(id: string): Promise<void> {\n this.loading = \"Loading entry...\";\n\n try {\n const entry = await this.getEntryUseCase.execute({\n model: this.model,\n id\n });\n\n runInAction(() => {\n this.entry = entry;\n this.buildAndPopulateForm(entry);\n });\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n setFolderId(folderId: string | null): void {\n this.folderId = folderId;\n }\n\n newEntry(initialValues?: Record<string, unknown>): void {\n this.entry = null;\n this.form = this.buildForm();\n if (initialValues) {\n this.form.setData(initialValues, { dirty: true });\n }\n }\n\n patchEntryMeta(meta: Partial<CmsContentEntry[\"meta\"]>): void {\n if (!this.entry) {\n return;\n }\n this.entry = {\n ...this.entry,\n meta: { ...this.entry.meta, ...meta }\n };\n }\n\n reset(): void {\n this.form = null;\n this.entry = null;\n }\n\n private buildForm(): FormModel.Interface {\n const formConfig = this.cmsFormModelBuilder.build(this.model);\n const form = this.formModelFactory.create(formConfig);\n for (const modifier of this.formModelModifiers) {\n modifier.modifyForm(form, this.model);\n }\n return form;\n }\n\n private buildAndPopulateForm(entry: CmsContentEntry): void {\n this.form = this.buildForm();\n this.form.setData(entry.values);\n this.form.reset();\n }\n /**\n * Depending on whether the entry is locked or not, this method will either create a new revision from the existing one and update it, or simply update the existing revision.\n */\n private async saveEntry(params: SaveEntryParams): Promise<any> {\n const { entry, data, skipValidation } = params;\n\n if (entry.meta.locked) {\n return await this.createRevisionFromUseCase.execute({\n model: this.model,\n revisionId: entry.id,\n data: {\n values: data\n },\n options: { skipValidation }\n });\n }\n return await this.updateEntryUseCase.execute({\n model: this.model,\n revisionId: entry.id,\n data: {\n values: data\n },\n options: { skipValidation }\n });\n }\n}\n\nexport const ContentEntryFormPresenter = Abstraction.createImplementation({\n implementation: ContentEntryFormPresenterImpl,\n dependencies: [\n FormModelFactory,\n CmsFormModelBuilder,\n Confirmation,\n CmsModelContext,\n GetEntryUseCase,\n CreateEntryUseCase,\n CreateRevisionFromUseCase,\n UpdateEntryUseCase,\n PublishEntryUseCase,\n UnpublishEntryUseCase,\n DeleteEntryUseCase,\n UpdateRevisionDescriptionUseCase,\n [ContentEntryFormModelModifier, { multiple: true }]\n ]\n});\n"],"names":["PUBLISH_ENTRY_DIALOG","ContentEntryFormPresenterImpl","formModelFactory","cmsFormModelBuilder","confirmation","modelAccessor","getEntryUseCase","createEntryUseCase","createRevisionFromUseCase","updateEntryUseCase","publishEntryUseCase","unpublishEntryUseCase","deleteEntryUseCase","updateRevisionDescriptionUseCase","formModelModifiers","makeAutoObservable","computed","entry","meta","isLocked","status","canSave","toJS","options","form","model","skipValidation","data","runInAction","createData","error","toFormErrors","result","TRASH_ENTRY_DIALOG","id","folderId","initialValues","formConfig","modifier","params","ContentEntryFormPresenter","Abstraction","FormModelFactory","CmsFormModelBuilder","Confirmation","CmsModelContext","GetEntryUseCase","CreateEntryUseCase","CreateRevisionFromUseCase","UpdateEntryUseCase","PublishEntryUseCase","UnpublishEntryUseCase","DeleteEntryUseCase","UpdateRevisionDescriptionUseCase","ContentEntryFormModelModifier"],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { Container } from "@webiny/di";
3
+ import { FormModelFactory } from "@webiny/app-admin/features/formModel/abstractions.js";
4
+ import { Confirmation } from "@webiny/app-admin/features/confirmation/abstractions.js";
5
+ import { GetEntryUseCase } from "../../../features/contentEntry/getEntry/abstractions.js";
6
+ import { CreateEntryUseCase } from "../../../features/contentEntry/createEntry/abstractions.js";
7
+ import { UpdateEntryUseCase } from "../../../features/contentEntry/updateEntry/abstractions.js";
8
+ import { PublishEntryUseCase } from "../../../features/contentEntry/publishEntry/abstractions.js";
9
+ import { UnpublishEntryUseCase } from "../../../features/contentEntry/unpublishEntry/abstractions.js";
10
+ import { DeleteEntryUseCase } from "../../../features/contentEntry/deleteEntry/abstractions.js";
11
+ import { UpdateRevisionDescriptionUseCase } from "../../../features/contentEntry/updateRevisionDescription/abstractions.js";
12
+ import { CreateRevisionFromUseCase } from "../../../features/contentEntry/createRevisionFrom/abstractions.js";
13
+ import { CmsFormModelBuilder } from "../../../features/formModel/abstractions.js";
14
+ import { CmsModelContext } from "../../../features/contentEntry/abstractions.js";
15
+ import { ContentEntryFormPresenter } from "./abstractions.js";
16
+ import { ContentEntryFormPresenter as external_ContentEntryFormPresenter_js_ContentEntryFormPresenter } from "./ContentEntryFormPresenter.js";
17
+ const createFakeForm = ()=>({
18
+ vm: {},
19
+ isDirty: false,
20
+ submit: vi.fn(async ()=>({
21
+ title: "Draft"
22
+ })),
23
+ setData: vi.fn(),
24
+ reset: vi.fn(),
25
+ setErrors: vi.fn()
26
+ });
27
+ const deferred = ()=>{
28
+ let resolve;
29
+ let reject;
30
+ const promise = new Promise((res, rej)=>{
31
+ resolve = res;
32
+ reject = rej;
33
+ });
34
+ return {
35
+ promise,
36
+ resolve,
37
+ reject
38
+ };
39
+ };
40
+ const setup = ()=>{
41
+ const forms = [];
42
+ const create = deferred();
43
+ const container = new Container();
44
+ container.registerInstance(FormModelFactory, {
45
+ create: ()=>{
46
+ const form = createFakeForm();
47
+ forms.push(form);
48
+ return form;
49
+ }
50
+ });
51
+ container.registerInstance(CmsFormModelBuilder, {
52
+ build: ()=>({})
53
+ });
54
+ container.registerInstance(CmsModelContext, {
55
+ getModel: ()=>({
56
+ modelId: "article",
57
+ fields: []
58
+ })
59
+ });
60
+ container.registerInstance(CreateEntryUseCase, {
61
+ execute: ()=>create.promise
62
+ });
63
+ for (const abstraction of [
64
+ Confirmation,
65
+ GetEntryUseCase,
66
+ CreateRevisionFromUseCase,
67
+ UpdateEntryUseCase,
68
+ PublishEntryUseCase,
69
+ UnpublishEntryUseCase,
70
+ DeleteEntryUseCase,
71
+ UpdateRevisionDescriptionUseCase
72
+ ])container.registerInstance(abstraction, {});
73
+ container.register(external_ContentEntryFormPresenter_js_ContentEntryFormPresenter);
74
+ return {
75
+ presenter: container.resolve(ContentEntryFormPresenter),
76
+ forms,
77
+ create
78
+ };
79
+ };
80
+ describe("ContentEntryFormPresenter.saveRevision", ()=>{
81
+ it("puts a rejected save's errors on the form", async ()=>{
82
+ const { presenter, forms, create } = setup();
83
+ presenter.newEntry();
84
+ const saving = presenter.saveRevision();
85
+ create.reject(new Error("Value must be unique."));
86
+ await expect(saving).resolves.toBe(false);
87
+ expect(forms[0].setErrors).toHaveBeenCalledTimes(1);
88
+ });
89
+ it("returns false instead of throwing when the form was reset mid-save", async ()=>{
90
+ const { presenter, create } = setup();
91
+ presenter.newEntry();
92
+ const saving = presenter.saveRevision();
93
+ presenter.reset();
94
+ create.reject(new Error("Value must be unique."));
95
+ await expect(saving).resolves.toBe(false);
96
+ });
97
+ it("leaves a form built after the save started alone", async ()=>{
98
+ const { presenter, forms, create } = setup();
99
+ presenter.newEntry();
100
+ const saving = presenter.saveRevision();
101
+ presenter.newEntry();
102
+ create.reject(new Error("Value must be unique."));
103
+ await expect(saving).resolves.toBe(false);
104
+ expect(forms).toHaveLength(2);
105
+ expect(forms[0].setErrors).not.toHaveBeenCalled();
106
+ expect(forms[1].setErrors).not.toHaveBeenCalled();
107
+ });
108
+ });
109
+
110
+ //# sourceMappingURL=ContentEntryFormPresenter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/form/ContentEntryFormPresenter.test.js","sources":["../../../../src/presentation/contentEntries/form/ContentEntryFormPresenter.test.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport { describe, it, expect, vi } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport { GetEntryUseCase } from \"~/features/contentEntry/getEntry/abstractions.js\";\nimport { CreateEntryUseCase } from \"~/features/contentEntry/createEntry/abstractions.js\";\nimport { UpdateEntryUseCase } from \"~/features/contentEntry/updateEntry/abstractions.js\";\nimport { PublishEntryUseCase } from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryUseCase } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { DeleteEntryUseCase } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionUseCase } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport { CreateRevisionFromUseCase } from \"~/features/contentEntry/createRevisionFrom/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport { ContentEntryFormPresenter as Abstraction } from \"./abstractions.js\";\nimport { ContentEntryFormPresenter } from \"./ContentEntryFormPresenter.js\";\n\nconst createFakeForm = () => ({\n vm: {},\n isDirty: false,\n submit: vi.fn(async () => ({ title: \"Draft\" })),\n setData: vi.fn(),\n reset: vi.fn(),\n setErrors: vi.fn()\n});\n\n/** A promise the test settles by hand, so it can act while a save is still in flight. */\nconst deferred = <T>() => {\n let resolve!: (value: T) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst setup = () => {\n const forms: ReturnType<typeof createFakeForm>[] = [];\n const create = deferred<any>();\n\n const container = new Container();\n container.registerInstance(FormModelFactory, {\n create: () => {\n const form = createFakeForm();\n forms.push(form);\n return form;\n }\n } as unknown as FormModelFactory.Interface);\n container.registerInstance(CmsFormModelBuilder, {\n build: () => ({})\n } as unknown as CmsFormModelBuilder.Interface);\n container.registerInstance(CmsModelContext, {\n getModel: () => ({ modelId: \"article\", fields: [] })\n } as unknown as CmsModelContext.Interface);\n container.registerInstance(CreateEntryUseCase, {\n execute: () => create.promise\n } as unknown as CreateEntryUseCase.Interface);\n\n // Not reached by the create path these tests exercise.\n for (const abstraction of [\n Confirmation,\n GetEntryUseCase,\n CreateRevisionFromUseCase,\n UpdateEntryUseCase,\n PublishEntryUseCase,\n UnpublishEntryUseCase,\n DeleteEntryUseCase,\n UpdateRevisionDescriptionUseCase\n ]) {\n container.registerInstance(abstraction as any, {});\n }\n container.register(ContentEntryFormPresenter);\n\n return { presenter: container.resolve(Abstraction), forms, create };\n};\n\ndescribe(\"ContentEntryFormPresenter.saveRevision\", () => {\n it(\"puts a rejected save's errors on the form\", async () => {\n const { presenter, forms, create } = setup();\n presenter.newEntry();\n\n const saving = presenter.saveRevision();\n create.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n expect(forms[0].setErrors).toHaveBeenCalledTimes(1);\n });\n\n it(\"returns false instead of throwing when the form was reset mid-save\", async () => {\n const { presenter, create } = setup();\n presenter.newEntry();\n\n const saving = presenter.saveRevision();\n presenter.reset();\n create.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n });\n\n it(\"leaves a form built after the save started alone\", async () => {\n const { presenter, forms, create } = setup();\n presenter.newEntry();\n\n const saving = presenter.saveRevision();\n presenter.newEntry();\n create.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n expect(forms).toHaveLength(2);\n expect(forms[0].setErrors).not.toHaveBeenCalled();\n expect(forms[1].setErrors).not.toHaveBeenCalled();\n });\n});\n"],"names":["createFakeForm","vi","deferred","resolve","reject","promise","Promise","res","rej","setup","forms","create","container","Container","FormModelFactory","form","CmsFormModelBuilder","CmsModelContext","CreateEntryUseCase","abstraction","Confirmation","GetEntryUseCase","CreateRevisionFromUseCase","UpdateEntryUseCase","PublishEntryUseCase","UnpublishEntryUseCase","DeleteEntryUseCase","UpdateRevisionDescriptionUseCase","ContentEntryFormPresenter","Abstraction","describe","it","presenter","saving","Error","expect"],"mappings":";;;;;;;;;;;;;;;;AAkBA,MAAMA,iBAAiB,IAAO;QAC1B,IAAI,CAAC;QACL,SAAS;QACT,QAAQC,GAAG,EAAE,CAAC,UAAa;gBAAE,OAAO;YAAQ;QAC5C,SAASA,GAAG,EAAE;QACd,OAAOA,GAAG,EAAE;QACZ,WAAWA,GAAG,EAAE;IACpB;AAGA,MAAMC,WAAW;IACb,IAAIC;IACJ,IAAIC;IACJ,MAAMC,UAAU,IAAIC,QAAW,CAACC,KAAKC;QACjCL,UAAUI;QACVH,SAASI;IACb;IACA,OAAO;QAAEH;QAASF;QAASC;IAAO;AACtC;AAEA,MAAMK,QAAQ;IACV,MAAMC,QAA6C,EAAE;IACrD,MAAMC,SAAST;IAEf,MAAMU,YAAY,IAAIC;IACtBD,UAAU,gBAAgB,CAACE,kBAAkB;QACzC,QAAQ;YACJ,MAAMC,OAAOf;YACbU,MAAM,IAAI,CAACK;YACX,OAAOA;QACX;IACJ;IACAH,UAAU,gBAAgB,CAACI,qBAAqB;QAC5C,OAAO,IAAO,EAAC;IACnB;IACAJ,UAAU,gBAAgB,CAACK,iBAAiB;QACxC,UAAU,IAAO;gBAAE,SAAS;gBAAW,QAAQ,EAAE;YAAC;IACtD;IACAL,UAAU,gBAAgB,CAACM,oBAAoB;QAC3C,SAAS,IAAMP,OAAO,OAAO;IACjC;IAGA,KAAK,MAAMQ,eAAe;QACtBC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;KACH,CACGf,UAAU,gBAAgB,CAACO,aAAoB,CAAC;IAEpDP,UAAU,QAAQ,CAACgB;IAEnB,OAAO;QAAE,WAAWhB,UAAU,OAAO,CAACiB;QAAcnB;QAAOC;IAAO;AACtE;AAEAmB,SAAS,0CAA0C;IAC/CC,GAAG,6CAA6C;QAC5C,MAAM,EAAEC,SAAS,EAAEtB,KAAK,EAAEC,MAAM,EAAE,GAAGF;QACrCuB,UAAU,QAAQ;QAElB,MAAMC,SAASD,UAAU,YAAY;QACrCrB,OAAO,MAAM,CAAC,IAAIuB,MAAM;QAExB,MAAMC,OAAOF,QAAQ,QAAQ,CAAC,IAAI,CAAC;QACnCE,OAAOzB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,CAAC;IACrD;IAEAqB,GAAG,sEAAsE;QACrE,MAAM,EAAEC,SAAS,EAAErB,MAAM,EAAE,GAAGF;QAC9BuB,UAAU,QAAQ;QAElB,MAAMC,SAASD,UAAU,YAAY;QACrCA,UAAU,KAAK;QACfrB,OAAO,MAAM,CAAC,IAAIuB,MAAM;QAExB,MAAMC,OAAOF,QAAQ,QAAQ,CAAC,IAAI,CAAC;IACvC;IAEAF,GAAG,oDAAoD;QACnD,MAAM,EAAEC,SAAS,EAAEtB,KAAK,EAAEC,MAAM,EAAE,GAAGF;QACrCuB,UAAU,QAAQ;QAElB,MAAMC,SAASD,UAAU,YAAY;QACrCA,UAAU,QAAQ;QAClBrB,OAAO,MAAM,CAAC,IAAIuB,MAAM;QAExB,MAAMC,OAAOF,QAAQ,QAAQ,CAAC,IAAI,CAAC;QACnCE,OAAOzB,OAAO,YAAY,CAAC;QAC3ByB,OAAOzB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,gBAAgB;QAC/CyB,OAAOzB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,gBAAgB;IACnD;AACJ"}
@@ -38,7 +38,9 @@ class SingleEntryPresenterImpl {
38
38
  }
39
39
  async save() {
40
40
  if (!this.form) return false;
41
- const data = await this.form.submit();
41
+ const form = this.form;
42
+ const model = this.model;
43
+ const data = await form.submit();
42
44
  if (!data) return false;
43
45
  this.loading = "Saving...";
44
46
  try {
@@ -49,13 +51,14 @@ class SingleEntryPresenterImpl {
49
51
  }
50
52
  });
51
53
  runInAction(()=>{
54
+ if (this.form !== form) return;
52
55
  this.entry = entry;
53
- this.form.setData(entry.values);
54
- this.form.reset();
56
+ form.setData(entry.values);
57
+ form.reset();
55
58
  });
56
59
  return true;
57
60
  } catch (error) {
58
- this.form.setErrors(toFormErrors(error, this.model));
61
+ if (this.form === form) form.setErrors(toFormErrors(error, model));
59
62
  return false;
60
63
  } finally{
61
64
  runInAction(()=>{
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/singleEntry/SingleEntryPresenter.js","sources":["../../../../src/presentation/contentEntries/singleEntry/SingleEntryPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { GetSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { UpdateSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n SingleEntryPresenter as Abstraction,\n type ISingleEntryPresenter,\n type ISingleEntryViewModel\n} from \"./abstractions.js\";\nimport { toFormErrors } from \"~/presentation/contentEntries/form/toFormErrors.js\";\n\nclass SingleEntryPresenterImpl implements ISingleEntryPresenter {\n private entry: CmsContentEntry | null = null;\n private form: IFormModel | null = null;\n private loading: string | null = null;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private cmsFormModelBuilder: CmsFormModelBuilder.Interface,\n private modelAccessor: CmsModelContext.Interface,\n private getSingletonEntryUseCase: GetSingletonEntryUseCase.Interface,\n private updateSingletonEntryUseCase: UpdateSingletonEntryUseCase.Interface\n ) {\n makeAutoObservable<\n SingleEntryPresenterImpl,\n | \"formModelFactory\"\n | \"cmsFormModelBuilder\"\n | \"modelAccessor\"\n | \"getSingletonEntryUseCase\"\n | \"updateSingletonEntryUseCase\"\n >(this, {\n formModelFactory: false,\n cmsFormModelBuilder: false,\n modelAccessor: false,\n getSingletonEntryUseCase: false,\n updateSingletonEntryUseCase: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): ISingleEntryViewModel {\n return {\n loading: this.loading,\n entry: this.entry,\n form: this.form?.vm ?? null,\n canSave: this.form !== null,\n isDirty: this.form?.isDirty ?? false\n };\n }\n\n async save(): Promise<boolean> {\n if (!this.form) {\n return false;\n }\n\n const data = await this.form.submit();\n if (!data) {\n return false;\n }\n\n this.loading = \"Saving...\";\n\n try {\n const entry = await this.updateSingletonEntryUseCase.execute({\n model: this.model,\n data: {\n values: data\n }\n });\n\n runInAction(() => {\n this.entry = entry;\n this.form!.setData(entry.values);\n this.form!.reset();\n });\n\n return true;\n } catch (error) {\n this.form.setErrors(toFormErrors(error, this.model));\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async init(): Promise<void> {\n this.loading = \"Loading...\";\n\n try {\n const entry = await this.getSingletonEntryUseCase.execute({\n model: this.model\n });\n\n runInAction(() => {\n this.entry = entry;\n const formConfig = this.cmsFormModelBuilder.build(this.model);\n this.form = this.formModelFactory.create(formConfig);\n this.form.setData(entry.values);\n this.form.reset();\n });\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n dispose(): void {\n this.form = null;\n this.entry = null;\n }\n}\n\nexport const SingleEntryPresenter = Abstraction.createImplementation({\n implementation: SingleEntryPresenterImpl,\n dependencies: [\n FormModelFactory,\n CmsFormModelBuilder,\n CmsModelContext,\n GetSingletonEntryUseCase,\n UpdateSingletonEntryUseCase\n ]\n});\n"],"names":["SingleEntryPresenterImpl","formModelFactory","cmsFormModelBuilder","modelAccessor","getSingletonEntryUseCase","updateSingletonEntryUseCase","makeAutoObservable","computed","data","entry","runInAction","error","toFormErrors","formConfig","SingleEntryPresenter","Abstraction","FormModelFactory","CmsFormModelBuilder","CmsModelContext","GetSingletonEntryUseCase","UpdateSingletonEntryUseCase"],"mappings":";;;;;;;AAeA,MAAMA;IAKF,YACYC,gBAA4C,EAC5CC,mBAAkD,EAClDC,aAAwC,EACxCC,wBAA4D,EAC5DC,2BAAkE,CAC5E;aALUJ,gBAAgB,GAAhBA;aACAC,mBAAmB,GAAnBA;aACAC,aAAa,GAAbA;aACAC,wBAAwB,GAAxBA;aACAC,2BAA2B,GAA3BA;aATJ,KAAK,GAA2B;aAChC,IAAI,GAAsB;aAC1B,OAAO,GAAkB;QAS7BC,mBAOE,IAAI,EAAE;YACJ,kBAAkB;YAClB,qBAAqB;YACrB,eAAe;YACf,0BAA0B;YAC1B,6BAA6B;YAC7B,IAAIC;QACR;IACJ;IAEA,IAAY,QAAQ;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ;IACtC;IAEA,IAAI,KAA4B;QAC5B,OAAO;YACH,SAAS,IAAI,CAAC,OAAO;YACrB,OAAO,IAAI,CAAC,KAAK;YACjB,MAAM,IAAI,CAAC,IAAI,EAAE,MAAM;YACvB,SAAS,AAAc,SAAd,IAAI,CAAC,IAAI;YAClB,SAAS,IAAI,CAAC,IAAI,EAAE,WAAW;QACnC;IACJ;IAEA,MAAM,OAAyB;QAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,EACV,OAAO;QAGX,MAAMC,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM;QACnC,IAAI,CAACA,MACD,OAAO;QAGX,IAAI,CAAC,OAAO,GAAG;QAEf,IAAI;YACA,MAAMC,QAAQ,MAAM,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC;gBACzD,OAAO,IAAI,CAAC,KAAK;gBACjB,MAAM;oBACF,QAAQD;gBACZ;YACJ;YAEAE,YAAY;gBACR,IAAI,CAAC,KAAK,GAAGD;gBACb,IAAI,CAAC,IAAI,CAAE,OAAO,CAACA,MAAM,MAAM;gBAC/B,IAAI,CAAC,IAAI,CAAE,KAAK;YACpB;YAEA,OAAO;QACX,EAAE,OAAOE,OAAO;YACZ,IAAI,CAAC,IAAI,CAAC,SAAS,CAACC,aAAaD,OAAO,IAAI,CAAC,KAAK;YAClD,OAAO;QACX,SAAU;YACND,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;YACnB;QACJ;IACJ;IAEA,MAAM,OAAsB;QACxB,IAAI,CAAC,OAAO,GAAG;QAEf,IAAI;YACA,MAAMD,QAAQ,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;gBACtD,OAAO,IAAI,CAAC,KAAK;YACrB;YAEAC,YAAY;gBACR,IAAI,CAAC,KAAK,GAAGD;gBACb,MAAMI,aAAa,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;gBAC5D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACA;gBACzC,IAAI,CAAC,IAAI,CAAC,OAAO,CAACJ,MAAM,MAAM;gBAC9B,IAAI,CAAC,IAAI,CAAC,KAAK;YACnB;QACJ,SAAU;YACNC,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;YACnB;QACJ;IACJ;IAEA,UAAgB;QACZ,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,KAAK,GAAG;IACjB;AACJ;AAEO,MAAMI,4CAAuBC,qBAAAA,oBAAgC,CAAC;IACjE,gBAAgBf;IAChB,cAAc;QACVgB;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
1
+ {"version":3,"file":"presentation/contentEntries/singleEntry/SingleEntryPresenter.js","sources":["../../../../src/presentation/contentEntries/singleEntry/SingleEntryPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { GetSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { UpdateSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n SingleEntryPresenter as Abstraction,\n type ISingleEntryPresenter,\n type ISingleEntryViewModel\n} from \"./abstractions.js\";\nimport { toFormErrors } from \"~/presentation/contentEntries/form/toFormErrors.js\";\n\nclass SingleEntryPresenterImpl implements ISingleEntryPresenter {\n private entry: CmsContentEntry | null = null;\n private form: IFormModel | null = null;\n private loading: string | null = null;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private cmsFormModelBuilder: CmsFormModelBuilder.Interface,\n private modelAccessor: CmsModelContext.Interface,\n private getSingletonEntryUseCase: GetSingletonEntryUseCase.Interface,\n private updateSingletonEntryUseCase: UpdateSingletonEntryUseCase.Interface\n ) {\n makeAutoObservable<\n SingleEntryPresenterImpl,\n | \"formModelFactory\"\n | \"cmsFormModelBuilder\"\n | \"modelAccessor\"\n | \"getSingletonEntryUseCase\"\n | \"updateSingletonEntryUseCase\"\n >(this, {\n formModelFactory: false,\n cmsFormModelBuilder: false,\n modelAccessor: false,\n getSingletonEntryUseCase: false,\n updateSingletonEntryUseCase: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): ISingleEntryViewModel {\n return {\n loading: this.loading,\n entry: this.entry,\n form: this.form?.vm ?? null,\n canSave: this.form !== null,\n isDirty: this.form?.isDirty ?? false\n };\n }\n\n async save(): Promise<boolean> {\n if (!this.form) {\n return false;\n }\n\n // The form can be disposed or rebuilt while saving; only the form being saved gets the result.\n const form = this.form;\n const model = this.model;\n\n const data = await form.submit();\n if (!data) {\n return false;\n }\n\n this.loading = \"Saving...\";\n\n try {\n const entry = await this.updateSingletonEntryUseCase.execute({\n model: this.model,\n data: {\n values: data\n }\n });\n\n runInAction(() => {\n if (this.form !== form) {\n return;\n }\n this.entry = entry;\n form.setData(entry.values);\n form.reset();\n });\n\n return true;\n } catch (error) {\n if (this.form === form) {\n form.setErrors(toFormErrors(error, model));\n }\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async init(): Promise<void> {\n this.loading = \"Loading...\";\n\n try {\n const entry = await this.getSingletonEntryUseCase.execute({\n model: this.model\n });\n\n runInAction(() => {\n this.entry = entry;\n const formConfig = this.cmsFormModelBuilder.build(this.model);\n this.form = this.formModelFactory.create(formConfig);\n this.form.setData(entry.values);\n this.form.reset();\n });\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n dispose(): void {\n this.form = null;\n this.entry = null;\n }\n}\n\nexport const SingleEntryPresenter = Abstraction.createImplementation({\n implementation: SingleEntryPresenterImpl,\n dependencies: [\n FormModelFactory,\n CmsFormModelBuilder,\n CmsModelContext,\n GetSingletonEntryUseCase,\n UpdateSingletonEntryUseCase\n ]\n});\n"],"names":["SingleEntryPresenterImpl","formModelFactory","cmsFormModelBuilder","modelAccessor","getSingletonEntryUseCase","updateSingletonEntryUseCase","makeAutoObservable","computed","form","model","data","entry","runInAction","error","toFormErrors","formConfig","SingleEntryPresenter","Abstraction","FormModelFactory","CmsFormModelBuilder","CmsModelContext","GetSingletonEntryUseCase","UpdateSingletonEntryUseCase"],"mappings":";;;;;;;AAeA,MAAMA;IAKF,YACYC,gBAA4C,EAC5CC,mBAAkD,EAClDC,aAAwC,EACxCC,wBAA4D,EAC5DC,2BAAkE,CAC5E;aALUJ,gBAAgB,GAAhBA;aACAC,mBAAmB,GAAnBA;aACAC,aAAa,GAAbA;aACAC,wBAAwB,GAAxBA;aACAC,2BAA2B,GAA3BA;aATJ,KAAK,GAA2B;aAChC,IAAI,GAAsB;aAC1B,OAAO,GAAkB;QAS7BC,mBAOE,IAAI,EAAE;YACJ,kBAAkB;YAClB,qBAAqB;YACrB,eAAe;YACf,0BAA0B;YAC1B,6BAA6B;YAC7B,IAAIC;QACR;IACJ;IAEA,IAAY,QAAQ;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ;IACtC;IAEA,IAAI,KAA4B;QAC5B,OAAO;YACH,SAAS,IAAI,CAAC,OAAO;YACrB,OAAO,IAAI,CAAC,KAAK;YACjB,MAAM,IAAI,CAAC,IAAI,EAAE,MAAM;YACvB,SAAS,AAAc,SAAd,IAAI,CAAC,IAAI;YAClB,SAAS,IAAI,CAAC,IAAI,EAAE,WAAW;QACnC;IACJ;IAEA,MAAM,OAAyB;QAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,EACV,OAAO;QAIX,MAAMC,OAAO,IAAI,CAAC,IAAI;QACtB,MAAMC,QAAQ,IAAI,CAAC,KAAK;QAExB,MAAMC,OAAO,MAAMF,KAAK,MAAM;QAC9B,IAAI,CAACE,MACD,OAAO;QAGX,IAAI,CAAC,OAAO,GAAG;QAEf,IAAI;YACA,MAAMC,QAAQ,MAAM,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC;gBACzD,OAAO,IAAI,CAAC,KAAK;gBACjB,MAAM;oBACF,QAAQD;gBACZ;YACJ;YAEAE,YAAY;gBACR,IAAI,IAAI,CAAC,IAAI,KAAKJ,MACd;gBAEJ,IAAI,CAAC,KAAK,GAAGG;gBACbH,KAAK,OAAO,CAACG,MAAM,MAAM;gBACzBH,KAAK,KAAK;YACd;YAEA,OAAO;QACX,EAAE,OAAOK,OAAO;YACZ,IAAI,IAAI,CAAC,IAAI,KAAKL,MACdA,KAAK,SAAS,CAACM,aAAaD,OAAOJ;YAEvC,OAAO;QACX,SAAU;YACNG,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;YACnB;QACJ;IACJ;IAEA,MAAM,OAAsB;QACxB,IAAI,CAAC,OAAO,GAAG;QAEf,IAAI;YACA,MAAMD,QAAQ,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;gBACtD,OAAO,IAAI,CAAC,KAAK;YACrB;YAEAC,YAAY;gBACR,IAAI,CAAC,KAAK,GAAGD;gBACb,MAAMI,aAAa,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;gBAC5D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACA;gBACzC,IAAI,CAAC,IAAI,CAAC,OAAO,CAACJ,MAAM,MAAM;gBAC9B,IAAI,CAAC,IAAI,CAAC,KAAK;YACnB;QACJ,SAAU;YACNC,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;YACnB;QACJ;IACJ;IAEA,UAAgB;QACZ,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,KAAK,GAAG;IACjB;AACJ;AAEO,MAAMI,4CAAuBC,qBAAAA,oBAAgC,CAAC;IACjE,gBAAgBjB;IAChB,cAAc;QACVkB;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
@@ -0,0 +1,122 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { Container } from "@webiny/di";
3
+ import { FormModelFactory } from "@webiny/app-admin/features/formModel/abstractions.js";
4
+ import { CmsFormModelBuilder } from "../../../features/formModel/abstractions.js";
5
+ import { CmsModelContext } from "../../../features/contentEntry/abstractions.js";
6
+ import { GetSingletonEntryUseCase, UpdateSingletonEntryUseCase } from "../../../features/contentEntry/singletonEntry/abstractions.js";
7
+ import { SingleEntryPresenter } from "./abstractions.js";
8
+ import { SingleEntryPresenter as external_SingleEntryPresenter_js_SingleEntryPresenter } from "./SingleEntryPresenter.js";
9
+ const createFakeForm = ()=>({
10
+ vm: {},
11
+ isDirty: false,
12
+ submit: vi.fn(async ()=>({
13
+ title: "Draft"
14
+ })),
15
+ setData: vi.fn(),
16
+ reset: vi.fn(),
17
+ setErrors: vi.fn()
18
+ });
19
+ const deferred = ()=>{
20
+ let resolve;
21
+ let reject;
22
+ const promise = new Promise((res, rej)=>{
23
+ resolve = res;
24
+ reject = rej;
25
+ });
26
+ return {
27
+ promise,
28
+ resolve,
29
+ reject
30
+ };
31
+ };
32
+ const setup = ()=>{
33
+ const forms = [];
34
+ let pendingUpdate = deferred();
35
+ const container = new Container();
36
+ container.registerInstance(FormModelFactory, {
37
+ create: ()=>{
38
+ const form = createFakeForm();
39
+ forms.push(form);
40
+ return form;
41
+ }
42
+ });
43
+ container.registerInstance(CmsFormModelBuilder, {
44
+ build: ()=>({})
45
+ });
46
+ container.registerInstance(CmsModelContext, {
47
+ getModel: ()=>({
48
+ modelId: "settings",
49
+ fields: []
50
+ })
51
+ });
52
+ container.registerInstance(GetSingletonEntryUseCase, {
53
+ execute: async ()=>({
54
+ id: "settings#0001",
55
+ values: {
56
+ title: "Saved"
57
+ }
58
+ })
59
+ });
60
+ container.registerInstance(UpdateSingletonEntryUseCase, {
61
+ execute: ()=>pendingUpdate.promise
62
+ });
63
+ container.register(external_SingleEntryPresenter_js_SingleEntryPresenter);
64
+ return {
65
+ presenter: container.resolve(SingleEntryPresenter),
66
+ forms,
67
+ nextUpdate: ()=>{
68
+ pendingUpdate = deferred();
69
+ return pendingUpdate;
70
+ }
71
+ };
72
+ };
73
+ describe("SingleEntryPresenter.save", ()=>{
74
+ it("puts a rejected save's errors on the form", async ()=>{
75
+ const { presenter, forms, nextUpdate } = setup();
76
+ await presenter.init();
77
+ const update = nextUpdate();
78
+ const saving = presenter.save();
79
+ update.reject(new Error("Value must be unique."));
80
+ await expect(saving).resolves.toBe(false);
81
+ expect(forms[0].setErrors).toHaveBeenCalledTimes(1);
82
+ });
83
+ it("returns false instead of throwing when the form was disposed mid-save", async ()=>{
84
+ const { presenter, nextUpdate } = setup();
85
+ await presenter.init();
86
+ const update = nextUpdate();
87
+ const saving = presenter.save();
88
+ presenter.dispose();
89
+ update.reject(new Error("Value must be unique."));
90
+ await expect(saving).resolves.toBe(false);
91
+ });
92
+ it("doesn't put a rejected save's errors on a form built after it started", async ()=>{
93
+ const { presenter, forms, nextUpdate } = setup();
94
+ await presenter.init();
95
+ const update = nextUpdate();
96
+ const saving = presenter.save();
97
+ await presenter.init();
98
+ update.reject(new Error("Value must be unique."));
99
+ await expect(saving).resolves.toBe(false);
100
+ expect(forms).toHaveLength(2);
101
+ expect(forms[0].setErrors).not.toHaveBeenCalled();
102
+ expect(forms[1].setErrors).not.toHaveBeenCalled();
103
+ });
104
+ it("doesn't overwrite a form built after a successful save started", async ()=>{
105
+ const { presenter, forms, nextUpdate } = setup();
106
+ await presenter.init();
107
+ const update = nextUpdate();
108
+ const saving = presenter.save();
109
+ await presenter.init();
110
+ const setDataCallsBefore = forms[1].setData.mock.calls.length;
111
+ update.resolve({
112
+ id: "settings#0002",
113
+ values: {
114
+ title: "From the old save"
115
+ }
116
+ });
117
+ await expect(saving).resolves.toBe(true);
118
+ expect(forms[1].setData).toHaveBeenCalledTimes(setDataCallsBefore);
119
+ });
120
+ });
121
+
122
+ //# sourceMappingURL=SingleEntryPresenter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js","sources":["../../../../src/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.ts"],"sourcesContent":["import { describe, it, expect, vi } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n GetSingletonEntryUseCase,\n UpdateSingletonEntryUseCase\n} from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { SingleEntryPresenter as Abstraction } from \"./abstractions.js\";\nimport { SingleEntryPresenter } from \"./SingleEntryPresenter.js\";\n\nconst createFakeForm = () => ({\n vm: {},\n isDirty: false,\n submit: vi.fn(async () => ({ title: \"Draft\" })),\n setData: vi.fn(),\n reset: vi.fn(),\n setErrors: vi.fn()\n});\n\n/** A promise the test settles by hand, so it can act while a save is still in flight. */\nconst deferred = <T>() => {\n let resolve!: (value: T) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst setup = () => {\n const forms: ReturnType<typeof createFakeForm>[] = [];\n let pendingUpdate = deferred<any>();\n\n const container = new Container();\n container.registerInstance(FormModelFactory, {\n create: () => {\n const form = createFakeForm();\n forms.push(form);\n return form;\n }\n } as unknown as FormModelFactory.Interface);\n container.registerInstance(CmsFormModelBuilder, {\n build: () => ({})\n } as unknown as CmsFormModelBuilder.Interface);\n container.registerInstance(CmsModelContext, {\n getModel: () => ({ modelId: \"settings\", fields: [] })\n } as unknown as CmsModelContext.Interface);\n container.registerInstance(GetSingletonEntryUseCase, {\n execute: async () => ({ id: \"settings#0001\", values: { title: \"Saved\" } })\n } as unknown as GetSingletonEntryUseCase.Interface);\n container.registerInstance(UpdateSingletonEntryUseCase, {\n execute: () => pendingUpdate.promise\n } as unknown as UpdateSingletonEntryUseCase.Interface);\n container.register(SingleEntryPresenter);\n\n return {\n presenter: container.resolve(Abstraction),\n forms,\n nextUpdate: () => {\n pendingUpdate = deferred<any>();\n return pendingUpdate;\n }\n };\n};\n\ndescribe(\"SingleEntryPresenter.save\", () => {\n it(\"puts a rejected save's errors on the form\", async () => {\n const { presenter, forms, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n update.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n expect(forms[0].setErrors).toHaveBeenCalledTimes(1);\n });\n\n it(\"returns false instead of throwing when the form was disposed mid-save\", async () => {\n const { presenter, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n presenter.dispose();\n update.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n });\n\n it(\"doesn't put a rejected save's errors on a form built after it started\", async () => {\n const { presenter, forms, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n await presenter.init();\n update.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n expect(forms).toHaveLength(2);\n expect(forms[0].setErrors).not.toHaveBeenCalled();\n expect(forms[1].setErrors).not.toHaveBeenCalled();\n });\n\n it(\"doesn't overwrite a form built after a successful save started\", async () => {\n const { presenter, forms, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n await presenter.init();\n const setDataCallsBefore = forms[1].setData.mock.calls.length;\n update.resolve({ id: \"settings#0002\", values: { title: \"From the old save\" } });\n\n await expect(saving).resolves.toBe(true);\n expect(forms[1].setData).toHaveBeenCalledTimes(setDataCallsBefore);\n });\n});\n"],"names":["createFakeForm","vi","deferred","resolve","reject","promise","Promise","res","rej","setup","forms","pendingUpdate","container","Container","FormModelFactory","form","CmsFormModelBuilder","CmsModelContext","GetSingletonEntryUseCase","UpdateSingletonEntryUseCase","SingleEntryPresenter","Abstraction","describe","it","presenter","nextUpdate","update","saving","Error","expect","setDataCallsBefore"],"mappings":"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"}