@webiny/app-headless-cms 6.5.0-beta.0 → 6.5.0-beta.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/app-headless-cms",
3
- "version": "6.5.0-beta.0",
3
+ "version": "6.5.0-beta.2",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -28,25 +28,25 @@
28
28
  "@fortawesome/react-fontawesome": "3.5.0",
29
29
  "@lexical/utils": "0.48.0",
30
30
  "@types/react": "18.3.31",
31
- "@webiny/admin-ui": "6.5.0-beta.0",
32
- "@webiny/app": "6.5.0-beta.0",
33
- "@webiny/app-aco": "6.5.0-beta.0",
34
- "@webiny/app-admin": "6.5.0-beta.0",
35
- "@webiny/app-graphql-playground": "6.5.0-beta.0",
36
- "@webiny/app-headless-cms-common": "6.5.0-beta.0",
37
- "@webiny/cms-sdk": "6.5.0-beta.0",
31
+ "@webiny/admin-ui": "6.5.0-beta.2",
32
+ "@webiny/app": "6.5.0-beta.2",
33
+ "@webiny/app-aco": "6.5.0-beta.2",
34
+ "@webiny/app-admin": "6.5.0-beta.2",
35
+ "@webiny/app-graphql-playground": "6.5.0-beta.2",
36
+ "@webiny/app-headless-cms-common": "6.5.0-beta.2",
37
+ "@webiny/cms-sdk": "6.5.0-beta.2",
38
38
  "@webiny/di": "1.0.2",
39
- "@webiny/feature": "6.5.0-beta.0",
40
- "@webiny/form": "6.5.0-beta.0",
41
- "@webiny/frontend-settings": "6.5.0-beta.0",
42
- "@webiny/icons": "6.5.0-beta.0",
43
- "@webiny/lexical-editor": "6.5.0-beta.0",
44
- "@webiny/lexical-nodes": "6.5.0-beta.0",
45
- "@webiny/plugins": "6.5.0-beta.0",
46
- "@webiny/react-composition": "6.5.0-beta.0",
47
- "@webiny/react-properties": "6.5.0-beta.0",
48
- "@webiny/utils": "6.5.0-beta.0",
49
- "@webiny/validation": "6.5.0-beta.0",
39
+ "@webiny/feature": "6.5.0-beta.2",
40
+ "@webiny/form": "6.5.0-beta.2",
41
+ "@webiny/frontend-settings": "6.5.0-beta.2",
42
+ "@webiny/icons": "6.5.0-beta.2",
43
+ "@webiny/lexical-editor": "6.5.0-beta.2",
44
+ "@webiny/lexical-nodes": "6.5.0-beta.2",
45
+ "@webiny/plugins": "6.5.0-beta.2",
46
+ "@webiny/react-composition": "6.5.0-beta.2",
47
+ "@webiny/react-properties": "6.5.0-beta.2",
48
+ "@webiny/utils": "6.5.0-beta.2",
49
+ "@webiny/validation": "6.5.0-beta.2",
50
50
  "dot-prop-immutable": "2.1.1",
51
51
  "graphql": "16.14.2",
52
52
  "graphql-tag": "2.12.7",
@@ -63,7 +63,7 @@
63
63
  "zod": "4.4.3"
64
64
  },
65
65
  "devDependencies": {
66
- "@webiny/build-tools": "6.5.0-beta.0",
66
+ "@webiny/build-tools": "6.5.0-beta.2",
67
67
  "rimraf": "6.1.3",
68
68
  "typescript": "7.0.2",
69
69
  "vitest": "4.1.10"
@@ -17,6 +17,7 @@ declare class CloneContentModelPresenterImpl implements ICloneContentModelPresen
17
17
  private sourceModel;
18
18
  constructor(formModelFactory: FormModelFactory.Interface, listModelGroupsUseCase: ListModelGroupsUseCase.Interface, cloneModelUseCase: CloneModelUseCase.Interface, groupsCache: ModelGroupsCache.Interface, modelsCache: ModelsCache.Interface);
19
19
  get vm(): ICloneContentModelPresenterViewModel;
20
+ private get groupOptions();
20
21
  init(sourceModel: CmsModel): Promise<void>;
21
22
  save(): Promise<CmsModel | null>;
22
23
  reset(): void;
@@ -26,18 +26,20 @@ class CloneContentModelPresenterImpl {
26
26
  });
27
27
  }
28
28
  get vm() {
29
- const groups = this.groupsCache.getItems().map((g)=>({
30
- value: g.slug,
31
- label: g.name
32
- }));
33
29
  return {
34
30
  loading: this.loading,
35
31
  saving: this.saving,
36
- groups,
32
+ groups: this.groupOptions,
37
33
  models: this.modelsCache.getItems(),
38
34
  form: this.form.vm
39
35
  };
40
36
  }
37
+ get groupOptions() {
38
+ return this.groupsCache.getItems().map((group)=>({
39
+ value: group.slug,
40
+ label: group.name
41
+ }));
42
+ }
41
43
  async init(sourceModel) {
42
44
  this.sourceModel = sourceModel;
43
45
  try {
@@ -91,7 +93,7 @@ class CloneContentModelPresenterImpl {
91
93
  name: fields.text().label("Name").required("Name is required."),
92
94
  singularApiName: fields.text().label("Singular API Name").required("Singular API Name is required."),
93
95
  pluralApiName: fields.text().label("Plural API Name").required("Plural API Name is required."),
94
- group: fields.text().label("Content model group").required("Group is required."),
96
+ group: fields.text().label("Content model group").required("Group is required.").options(()=>this.groupOptions),
95
97
  icon: fields.text().label("Icon").renderer("cmsIconPicker"),
96
98
  description: fields.text().label("Description").renderer("textarea")
97
99
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/cloneContentModel/CloneContentModelPresenter.js","sources":["../../../src/presentation/cloneContentModel/CloneContentModelPresenter.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModel } from \"~/types.js\";\nimport { ListModelGroupsUseCase } from \"~/features/modelGroup/listModelGroups/abstractions.js\";\nimport { CloneModelUseCase } from \"~/features/model/cloneModel/abstractions.js\";\nimport { ModelGroupsCache } from \"~/features/modelGroup/abstractions.js\";\nimport { ModelsCache } from \"~/features/model/abstractions.js\";\nimport {\n CloneContentModelPresenter as Abstraction,\n type ICloneContentModelPresenter,\n type ICloneContentModelPresenterViewModel\n} from \"./abstractions.js\";\n\nclass CloneContentModelPresenterImpl implements ICloneContentModelPresenter {\n private loading = true;\n private saving = false;\n private form: IFormModel;\n private sourceModel: CmsModel | null = null;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private listModelGroupsUseCase: ListModelGroupsUseCase.Interface,\n private cloneModelUseCase: CloneModelUseCase.Interface,\n private groupsCache: ModelGroupsCache.Interface,\n private modelsCache: ModelsCache.Interface\n ) {\n this.form = this.buildForm();\n makeAutoObservable<\n CloneContentModelPresenterImpl,\n | \"formModelFactory\"\n | \"listModelGroupsUseCase\"\n | \"cloneModelUseCase\"\n | \"groupsCache\"\n | \"modelsCache\"\n >(this, {\n formModelFactory: false,\n listModelGroupsUseCase: false,\n cloneModelUseCase: false,\n groupsCache: false,\n modelsCache: false,\n vm: computed\n });\n }\n\n get vm(): ICloneContentModelPresenterViewModel {\n const groups = this.groupsCache.getItems().map(g => ({\n value: g.slug,\n label: g.name\n }));\n\n return {\n loading: this.loading,\n saving: this.saving,\n groups,\n models: this.modelsCache.getItems(),\n form: this.form.vm\n };\n }\n\n async init(sourceModel: CmsModel): Promise<void> {\n this.sourceModel = sourceModel;\n\n try {\n await this.listModelGroupsUseCase.execute();\n } finally {\n runInAction(() => {\n this.loading = false;\n this.form = this.buildForm();\n this.form.setData({\n name: sourceModel.name,\n group: sourceModel.group\n });\n });\n }\n }\n\n async save(): Promise<CmsModel | null> {\n if (!this.sourceModel) {\n return null;\n }\n\n const data = await this.form.submit<Record<string, any>>();\n if (!data) {\n return null;\n }\n\n runInAction(() => {\n this.saving = true;\n });\n\n try {\n const model = await this.cloneModelUseCase.execute({\n modelId: this.sourceModel.modelId,\n data: {\n name: data.name as string,\n singularApiName: data.singularApiName as string | undefined,\n pluralApiName: data.pluralApiName as string | undefined,\n group: data.group as string | undefined,\n icon: data.icon as string | undefined,\n description: data.description as string | undefined\n }\n });\n\n return model;\n } catch {\n return null;\n } finally {\n runInAction(() => {\n this.saving = false;\n });\n }\n }\n\n reset(): void {\n this.sourceModel = null;\n this.form = this.buildForm();\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required.\"),\n singularApiName: fields\n .text()\n .label(\"Singular API Name\")\n .required(\"Singular API Name is required.\"),\n pluralApiName: fields\n .text()\n .label(\"Plural API Name\")\n .required(\"Plural API Name is required.\"),\n group: fields.text().label(\"Content model group\").required(\"Group is required.\"),\n icon: fields.text().label(\"Icon\").renderer(\"cmsIconPicker\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\")\n }),\n layout: layout => [\n layout.row(\"name\"),\n layout.row(\"singularApiName\"),\n layout.row(\"pluralApiName\"),\n layout.row(\"group\"),\n layout.row(\"icon\"),\n layout.row(\"description\")\n ]\n });\n }\n}\n\nexport const CloneContentModelPresenter = Abstraction.createImplementation({\n implementation: CloneContentModelPresenterImpl,\n dependencies: [\n FormModelFactory,\n ListModelGroupsUseCase,\n CloneModelUseCase,\n ModelGroupsCache,\n ModelsCache\n ]\n});\n"],"names":["CloneContentModelPresenterImpl","formModelFactory","listModelGroupsUseCase","cloneModelUseCase","groupsCache","modelsCache","makeAutoObservable","computed","groups","g","sourceModel","runInAction","data","model","fields","layout","CloneContentModelPresenter","Abstraction","FormModelFactory","ListModelGroupsUseCase","CloneModelUseCase","ModelGroupsCache","ModelsCache"],"mappings":";;;;;;;AAcA,MAAMA;IAMF,YACYC,gBAA4C,EAC5CC,sBAAwD,EACxDC,iBAA8C,EAC9CC,WAAuC,EACvCC,WAAkC,CAC5C;aALUJ,gBAAgB,GAAhBA;aACAC,sBAAsB,GAAtBA;aACAC,iBAAiB,GAAjBA;aACAC,WAAW,GAAXA;aACAC,WAAW,GAAXA;aAVJ,OAAO,GAAG;aACV,MAAM,GAAG;aAET,WAAW,GAAoB;QASnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS;QAC1BC,mBAOE,IAAI,EAAE;YACJ,kBAAkB;YAClB,wBAAwB;YACxB,mBAAmB;YACnB,aAAa;YACb,aAAa;YACb,IAAIC;QACR;IACJ;IAEA,IAAI,KAA2C;QAC3C,MAAMC,SAAS,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,GAAG,CAACC,CAAAA,IAAM;gBACjD,OAAOA,EAAE,IAAI;gBACb,OAAOA,EAAE,IAAI;YACjB;QAEA,OAAO;YACH,SAAS,IAAI,CAAC,OAAO;YACrB,QAAQ,IAAI,CAAC,MAAM;YACnBD;YACA,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ;YACjC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE;QACtB;IACJ;IAEA,MAAM,KAAKE,WAAqB,EAAiB;QAC7C,IAAI,CAAC,WAAW,GAAGA;QAEnB,IAAI;YACA,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO;QAC7C,SAAU;YACNC,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;gBACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS;gBAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;oBACd,MAAMD,YAAY,IAAI;oBACtB,OAAOA,YAAY,KAAK;gBAC5B;YACJ;QACJ;IACJ;IAEA,MAAM,OAAiC;QACnC,IAAI,CAAC,IAAI,CAAC,WAAW,EACjB,OAAO;QAGX,MAAME,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM;QACnC,IAAI,CAACA,MACD,OAAO;QAGXD,YAAY;YACR,IAAI,CAAC,MAAM,GAAG;QAClB;QAEA,IAAI;YACA,MAAME,QAAQ,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC;gBAC/C,SAAS,IAAI,CAAC,WAAW,CAAC,OAAO;gBACjC,MAAM;oBACF,MAAMD,KAAK,IAAI;oBACf,iBAAiBA,KAAK,eAAe;oBACrC,eAAeA,KAAK,aAAa;oBACjC,OAAOA,KAAK,KAAK;oBACjB,MAAMA,KAAK,IAAI;oBACf,aAAaA,KAAK,WAAW;gBACjC;YACJ;YAEA,OAAOC;QACX,EAAE,OAAM;YACJ,OAAO;QACX,SAAU;YACNF,YAAY;gBACR,IAAI,CAAC,MAAM,GAAG;YAClB;QACJ;IACJ;IAEA,QAAc;QACV,IAAI,CAAC,WAAW,GAAG;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS;IAC9B;IAEQ,YAAwB;QAC5B,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAChC,QAAQG,CAAAA,SAAW;oBACf,MAAMA,OAAO,IAAI,GAAG,KAAK,CAAC,QAAQ,QAAQ,CAAC;oBAC3C,iBAAiBA,OACZ,IAAI,GACJ,KAAK,CAAC,qBACN,QAAQ,CAAC;oBACd,eAAeA,OACV,IAAI,GACJ,KAAK,CAAC,mBACN,QAAQ,CAAC;oBACd,OAAOA,OAAO,IAAI,GAAG,KAAK,CAAC,uBAAuB,QAAQ,CAAC;oBAC3D,MAAMA,OAAO,IAAI,GAAG,KAAK,CAAC,QAAQ,QAAQ,CAAC;oBAC3C,aAAaA,OAAO,IAAI,GAAG,KAAK,CAAC,eAAe,QAAQ,CAAC;gBAC7D;YACA,QAAQC,CAAAA,SAAU;oBACdA,OAAO,GAAG,CAAC;oBACXA,OAAO,GAAG,CAAC;oBACXA,OAAO,GAAG,CAAC;oBACXA,OAAO,GAAG,CAAC;oBACXA,OAAO,GAAG,CAAC;oBACXA,OAAO,GAAG,CAAC;iBACd;QACL;IACJ;AACJ;AAEO,MAAMC,wDAA6BC,2BAAAA,oBAAgC,CAAC;IACvE,gBAAgBjB;IAChB,cAAc;QACVkB;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
1
+ {"version":3,"file":"presentation/cloneContentModel/CloneContentModelPresenter.js","sources":["../../../src/presentation/cloneContentModel/CloneContentModelPresenter.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModel } from \"~/types.js\";\nimport { ListModelGroupsUseCase } from \"~/features/modelGroup/listModelGroups/abstractions.js\";\nimport { CloneModelUseCase } from \"~/features/model/cloneModel/abstractions.js\";\nimport { ModelGroupsCache } from \"~/features/modelGroup/abstractions.js\";\nimport { ModelsCache } from \"~/features/model/abstractions.js\";\nimport {\n CloneContentModelPresenter as Abstraction,\n type ICloneContentModelPresenter,\n type ICloneContentModelPresenterViewModel\n} from \"./abstractions.js\";\n\nclass CloneContentModelPresenterImpl implements ICloneContentModelPresenter {\n private loading = true;\n private saving = false;\n private form: IFormModel;\n private sourceModel: CmsModel | null = null;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private listModelGroupsUseCase: ListModelGroupsUseCase.Interface,\n private cloneModelUseCase: CloneModelUseCase.Interface,\n private groupsCache: ModelGroupsCache.Interface,\n private modelsCache: ModelsCache.Interface\n ) {\n this.form = this.buildForm();\n makeAutoObservable<\n CloneContentModelPresenterImpl,\n | \"formModelFactory\"\n | \"listModelGroupsUseCase\"\n | \"cloneModelUseCase\"\n | \"groupsCache\"\n | \"modelsCache\"\n >(this, {\n formModelFactory: false,\n listModelGroupsUseCase: false,\n cloneModelUseCase: false,\n groupsCache: false,\n modelsCache: false,\n vm: computed\n });\n }\n\n get vm(): ICloneContentModelPresenterViewModel {\n return {\n loading: this.loading,\n saving: this.saving,\n groups: this.groupOptions,\n models: this.modelsCache.getItems(),\n form: this.form.vm\n };\n }\n\n private get groupOptions() {\n return this.groupsCache.getItems().map(group => ({\n value: group.slug,\n label: group.name\n }));\n }\n\n async init(sourceModel: CmsModel): Promise<void> {\n this.sourceModel = sourceModel;\n\n try {\n await this.listModelGroupsUseCase.execute();\n } finally {\n runInAction(() => {\n this.loading = false;\n this.form = this.buildForm();\n this.form.setData({\n name: sourceModel.name,\n group: sourceModel.group\n });\n });\n }\n }\n\n async save(): Promise<CmsModel | null> {\n if (!this.sourceModel) {\n return null;\n }\n\n const data = await this.form.submit<Record<string, any>>();\n if (!data) {\n return null;\n }\n\n runInAction(() => {\n this.saving = true;\n });\n\n try {\n const model = await this.cloneModelUseCase.execute({\n modelId: this.sourceModel.modelId,\n data: {\n name: data.name as string,\n singularApiName: data.singularApiName as string | undefined,\n pluralApiName: data.pluralApiName as string | undefined,\n group: data.group as string | undefined,\n icon: data.icon as string | undefined,\n description: data.description as string | undefined\n }\n });\n\n return model;\n } catch {\n return null;\n } finally {\n runInAction(() => {\n this.saving = false;\n });\n }\n }\n\n reset(): void {\n this.sourceModel = null;\n this.form = this.buildForm();\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required.\"),\n singularApiName: fields\n .text()\n .label(\"Singular API Name\")\n .required(\"Singular API Name is required.\"),\n pluralApiName: fields\n .text()\n .label(\"Plural API Name\")\n .required(\"Plural API Name is required.\"),\n group: fields\n .text()\n .label(\"Content model group\")\n .required(\"Group is required.\")\n /*\n * Options turn the text field into a select. The groups arrive after the form\n * is built, so they have to be read through a callback.\n */\n .options(() => this.groupOptions),\n icon: fields.text().label(\"Icon\").renderer(\"cmsIconPicker\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\")\n }),\n layout: layout => [\n layout.row(\"name\"),\n layout.row(\"singularApiName\"),\n layout.row(\"pluralApiName\"),\n layout.row(\"group\"),\n layout.row(\"icon\"),\n layout.row(\"description\")\n ]\n });\n }\n}\n\nexport const CloneContentModelPresenter = Abstraction.createImplementation({\n implementation: CloneContentModelPresenterImpl,\n dependencies: [\n FormModelFactory,\n ListModelGroupsUseCase,\n CloneModelUseCase,\n ModelGroupsCache,\n ModelsCache\n ]\n});\n"],"names":["CloneContentModelPresenterImpl","formModelFactory","listModelGroupsUseCase","cloneModelUseCase","groupsCache","modelsCache","makeAutoObservable","computed","group","sourceModel","runInAction","data","model","fields","layout","CloneContentModelPresenter","Abstraction","FormModelFactory","ListModelGroupsUseCase","CloneModelUseCase","ModelGroupsCache","ModelsCache"],"mappings":"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"}
@@ -10,6 +10,11 @@ export declare class ContentEntriesDataSource extends FolderAwareDataSource<CmsC
10
10
  private cache;
11
11
  constructor(model: CmsModel, listEntriesUseCase: IListEntriesUseCase, cache: IListCache<CmsContentEntry>, getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase, registeredFilterNames?: string[]);
12
12
  get rows(): CmsContentEntry[];
13
+ /**
14
+ * Mirrors `mapSort`: the list's sort fields that are not entry fields map to the
15
+ * fields the API sorts by.
16
+ */
17
+ private getSortValue;
13
18
  fetch(params: FetchParams): Promise<FetchResult<CmsContentEntry>>;
14
19
  private mapSort;
15
20
  }
@@ -5,11 +5,20 @@ class ContentEntriesDataSource extends FolderAwareDataSource {
5
5
  locationField: "wbyAco_location",
6
6
  keyField: "entryId",
7
7
  registeredFilterNames,
8
- getDescendantFolders: getDescendantFoldersUseCase
8
+ getDescendantFolders: getDescendantFoldersUseCase,
9
+ getSortValue: (entry, field)=>this.getSortValue(entry, field)
9
10
  }), this.model = model, this.listEntriesUseCase = listEntriesUseCase, this.cache = cache;
10
11
  }
11
12
  get rows() {
12
- return this.queryMatcher.filter(this.cache.getItems());
13
+ return this.queryMatcher.select(this.cache.getItems());
14
+ }
15
+ getSortValue(entry, field) {
16
+ if ("live" === field) return entry.lastPublishedOn;
17
+ if ("name" === field) {
18
+ const titleFieldId = this.model.titleFieldId;
19
+ return titleFieldId ? entry.values?.[titleFieldId] : entry.id;
20
+ }
21
+ return entry[field];
13
22
  }
14
23
  async fetch(params) {
15
24
  return this.listEntriesUseCase.execute({
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/list/ContentEntriesDataSource.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesDataSource.ts"],"sourcesContent":["import { FolderAwareDataSource } from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type {\n FetchParams,\n FetchResult\n} from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport type { IGetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport type { IListEntriesUseCase } from \"~/features/contentEntry/listEntries/abstractions.js\";\n\nexport class ContentEntriesDataSource extends FolderAwareDataSource<CmsContentEntry> {\n constructor(\n private model: CmsModel,\n private listEntriesUseCase: IListEntriesUseCase,\n private cache: IListCache<CmsContentEntry>,\n getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase,\n registeredFilterNames: string[] = []\n ) {\n super({\n locationField: \"wbyAco_location\",\n keyField: \"entryId\",\n registeredFilterNames,\n getDescendantFolders: getDescendantFoldersUseCase\n });\n }\n\n get rows(): CmsContentEntry[] {\n return this.queryMatcher.filter(this.cache.getItems());\n }\n\n async fetch(params: FetchParams): Promise<FetchResult<CmsContentEntry>> {\n return this.listEntriesUseCase.execute({\n model: this.model,\n where: params.where,\n sort: this.mapSort(params.sort),\n search: params.search,\n limit: params.limit,\n after: params.after\n });\n }\n\n private mapSort(sort: string[] | undefined): string[] | undefined {\n if (!sort) {\n return undefined;\n }\n\n const titleFieldId = this.model.titleFieldId;\n\n return sort.map(s => {\n if (s.startsWith(\"live_\")) {\n return s.replace(/^live_/, \"lastPublishedOn_\");\n }\n if (s.startsWith(\"name_\")) {\n return titleFieldId\n ? s.replace(/^name_/, `values_${titleFieldId}_`)\n : s.replace(/^name_/, \"id_\");\n }\n return s;\n });\n }\n}\n"],"names":["ContentEntriesDataSource","FolderAwareDataSource","model","listEntriesUseCase","cache","getDescendantFoldersUseCase","registeredFilterNames","params","sort","titleFieldId","s"],"mappings":";AAUO,MAAMA,iCAAiCC;IAC1C,YACYC,KAAe,EACfC,kBAAuC,EACvCC,KAAkC,EAC1CC,2BAA0D,EAC1DC,wBAAkC,EAAE,CACtC;QACE,KAAK,CAAC;YACF,eAAe;YACf,UAAU;YACVA;YACA,sBAAsBD;QAC1B,SAXQH,KAAK,GAALA,OAAAA,IAAAA,CACAC,kBAAkB,GAAlBA,oBAAAA,IAAAA,CACAC,KAAK,GAALA;IAUZ;IAEA,IAAI,OAA0B;QAC1B,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;IACvD;IAEA,MAAM,MAAMG,MAAmB,EAAyC;QACpE,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK;YACjB,OAAOA,OAAO,KAAK;YACnB,MAAM,IAAI,CAAC,OAAO,CAACA,OAAO,IAAI;YAC9B,QAAQA,OAAO,MAAM;YACrB,OAAOA,OAAO,KAAK;YACnB,OAAOA,OAAO,KAAK;QACvB;IACJ;IAEQ,QAAQC,IAA0B,EAAwB;QAC9D,IAAI,CAACA,MACD;QAGJ,MAAMC,eAAe,IAAI,CAAC,KAAK,CAAC,YAAY;QAE5C,OAAOD,KAAK,GAAG,CAACE,CAAAA;YACZ,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOA,EAAE,OAAO,CAAC,UAAU;YAE/B,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOD,eACDC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,EAAED,aAAa,CAAC,CAAC,IAC7CC,EAAE,OAAO,CAAC,UAAU;YAE9B,OAAOA;QACX;IACJ;AACJ"}
1
+ {"version":3,"file":"presentation/contentEntries/list/ContentEntriesDataSource.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesDataSource.ts"],"sourcesContent":["import { FolderAwareDataSource } from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type {\n FetchParams,\n FetchResult\n} from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport type { IGetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport type { IListEntriesUseCase } from \"~/features/contentEntry/listEntries/abstractions.js\";\n\nexport class ContentEntriesDataSource extends FolderAwareDataSource<CmsContentEntry> {\n constructor(\n private model: CmsModel,\n private listEntriesUseCase: IListEntriesUseCase,\n private cache: IListCache<CmsContentEntry>,\n getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase,\n registeredFilterNames: string[] = []\n ) {\n super({\n locationField: \"wbyAco_location\",\n keyField: \"entryId\",\n registeredFilterNames,\n getDescendantFolders: getDescendantFoldersUseCase,\n getSortValue: (entry, field) => this.getSortValue(entry, field)\n });\n }\n\n get rows(): CmsContentEntry[] {\n return this.queryMatcher.select(this.cache.getItems());\n }\n\n /**\n * Mirrors `mapSort`: the list's sort fields that are not entry fields map to the\n * fields the API sorts by.\n */\n private getSortValue(entry: CmsContentEntry, field: string): unknown {\n if (field === \"live\") {\n return entry.lastPublishedOn;\n }\n if (field === \"name\") {\n const titleFieldId = this.model.titleFieldId;\n return titleFieldId ? entry.values?.[titleFieldId] : entry.id;\n }\n return (entry as unknown as Record<string, unknown>)[field];\n }\n\n async fetch(params: FetchParams): Promise<FetchResult<CmsContentEntry>> {\n return this.listEntriesUseCase.execute({\n model: this.model,\n where: params.where,\n sort: this.mapSort(params.sort),\n search: params.search,\n limit: params.limit,\n after: params.after\n });\n }\n\n private mapSort(sort: string[] | undefined): string[] | undefined {\n if (!sort) {\n return undefined;\n }\n\n const titleFieldId = this.model.titleFieldId;\n\n return sort.map(s => {\n if (s.startsWith(\"live_\")) {\n return s.replace(/^live_/, \"lastPublishedOn_\");\n }\n if (s.startsWith(\"name_\")) {\n return titleFieldId\n ? s.replace(/^name_/, `values_${titleFieldId}_`)\n : s.replace(/^name_/, \"id_\");\n }\n return s;\n });\n }\n}\n"],"names":["ContentEntriesDataSource","FolderAwareDataSource","model","listEntriesUseCase","cache","getDescendantFoldersUseCase","registeredFilterNames","entry","field","titleFieldId","params","sort","s"],"mappings":";AAUO,MAAMA,iCAAiCC;IAC1C,YACYC,KAAe,EACfC,kBAAuC,EACvCC,KAAkC,EAC1CC,2BAA0D,EAC1DC,wBAAkC,EAAE,CACtC;QACE,KAAK,CAAC;YACF,eAAe;YACf,UAAU;YACVA;YACA,sBAAsBD;YACtB,cAAc,CAACE,OAAOC,QAAU,IAAI,CAAC,YAAY,CAACD,OAAOC;QAC7D,SAZQN,KAAK,GAALA,OAAAA,IAAAA,CACAC,kBAAkB,GAAlBA,oBAAAA,IAAAA,CACAC,KAAK,GAALA;IAWZ;IAEA,IAAI,OAA0B;QAC1B,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;IACvD;IAMQ,aAAaG,KAAsB,EAAEC,KAAa,EAAW;QACjE,IAAIA,AAAU,WAAVA,OACA,OAAOD,MAAM,eAAe;QAEhC,IAAIC,AAAU,WAAVA,OAAkB;YAClB,MAAMC,eAAe,IAAI,CAAC,KAAK,CAAC,YAAY;YAC5C,OAAOA,eAAeF,MAAM,MAAM,EAAE,CAACE,aAAa,GAAGF,MAAM,EAAE;QACjE;QACA,OAAQA,KAA4C,CAACC,MAAM;IAC/D;IAEA,MAAM,MAAME,MAAmB,EAAyC;QACpE,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK;YACjB,OAAOA,OAAO,KAAK;YACnB,MAAM,IAAI,CAAC,OAAO,CAACA,OAAO,IAAI;YAC9B,QAAQA,OAAO,MAAM;YACrB,OAAOA,OAAO,KAAK;YACnB,OAAOA,OAAO,KAAK;QACvB;IACJ;IAEQ,QAAQC,IAA0B,EAAwB;QAC9D,IAAI,CAACA,MACD;QAGJ,MAAMF,eAAe,IAAI,CAAC,KAAK,CAAC,YAAY;QAE5C,OAAOE,KAAK,GAAG,CAACC,CAAAA;YACZ,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOA,EAAE,OAAO,CAAC,UAAU;YAE/B,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOH,eACDG,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,EAAEH,aAAa,CAAC,CAAC,IAC7CG,EAAE,OAAO,CAAC,UAAU;YAE9B,OAAOA;QACX;IACJ;AACJ"}
@@ -16,7 +16,7 @@ import { MoveEntryFeature } from "../../../features/contentEntry/moveEntry/featu
16
16
  import { UpdateRevisionDescriptionFeature } from "../../../features/contentEntry/updateRevisionDescription/feature.js";
17
17
  import { ListEntriesGateway } from "../../../features/contentEntry/listEntries/abstractions.js";
18
18
  import { DeleteEntryGateway } from "../../../features/contentEntry/deleteEntry/abstractions.js";
19
- import { PublishEntryGateway } from "../../../features/contentEntry/publishEntry/abstractions.js";
19
+ import { PublishEntryGateway, PublishEntryUseCase } from "../../../features/contentEntry/publishEntry/abstractions.js";
20
20
  import { UnpublishEntryGateway } from "../../../features/contentEntry/unpublishEntry/abstractions.js";
21
21
  import { MoveEntryGateway } from "../../../features/contentEntry/moveEntry/abstractions.js";
22
22
  import { UpdateRevisionDescriptionGateway } from "../../../features/contentEntry/updateRevisionDescription/abstractions.js";
@@ -144,9 +144,10 @@ function setup() {
144
144
  container.registerInstance(ListEntriesGateway, listEntriesGateway);
145
145
  container.registerInstance(MoveEntryGateway, moveEntryGateway);
146
146
  container.registerInstance(DeleteEntryGateway, deleteEntryGateway);
147
- container.registerInstance(PublishEntryGateway, {
147
+ const publishEntryGateway = {
148
148
  execute: vi.fn()
149
- });
149
+ };
150
+ container.registerInstance(PublishEntryGateway, publishEntryGateway);
150
151
  container.registerInstance(UnpublishEntryGateway, {
151
152
  execute: vi.fn()
152
153
  });
@@ -161,7 +162,9 @@ function setup() {
161
162
  moveEntryGateway,
162
163
  deleteEntryGateway,
163
164
  getDescendantFolders,
164
- foldersPresenter
165
+ foldersPresenter,
166
+ publishEntryGateway,
167
+ container
165
168
  };
166
169
  }
167
170
  async function initPresenter(t, gatewayResponse) {
@@ -582,6 +585,71 @@ describe("ContentEntriesPresenter", ()=>{
582
585
  });
583
586
  });
584
587
  });
588
+ describe("publish entry", ()=>{
589
+ const entries = [
590
+ createEntry("entry-3", "root", {
591
+ savedOn: "2024-01-03T00:00:00.000Z"
592
+ }),
593
+ createEntry("entry-2", "root", {
594
+ savedOn: "2024-01-02T00:00:00.000Z"
595
+ }),
596
+ createEntry("entry-1", "root", {
597
+ savedOn: "2024-01-01T00:00:00.000Z"
598
+ })
599
+ ];
600
+ const publish = async (entry)=>{
601
+ t.publishEntryGateway.execute.mockResolvedValueOnce({
602
+ ...entry,
603
+ meta: {
604
+ ...entry.meta,
605
+ status: "published",
606
+ locked: true
607
+ }
608
+ });
609
+ await t.container.resolve(PublishEntryUseCase).execute({
610
+ model: MODEL,
611
+ revisionId: entry.id
612
+ });
613
+ };
614
+ it("should keep a published entry in its position", async ()=>{
615
+ await initPresenter(t, {
616
+ data: entries
617
+ });
618
+ await publish(entries[1]);
619
+ const rows = t.presenter.list.vm.rows;
620
+ expect(rows.map((r)=>r.entryId)).toEqual([
621
+ "entry-3",
622
+ "entry-2",
623
+ "entry-1"
624
+ ]);
625
+ expect(rows[1].meta.status).toBe("published");
626
+ });
627
+ it("should keep a published entry in its position when sorted ascending", async ()=>{
628
+ await initPresenter(t, {
629
+ data: entries
630
+ });
631
+ t.listEntriesGateway.execute.mockResolvedValueOnce({
632
+ data: [
633
+ ...entries
634
+ ].reverse(),
635
+ meta: {
636
+ cursor: null,
637
+ hasMoreItems: false,
638
+ totalCount: entries.length
639
+ }
640
+ });
641
+ t.presenter.list.actions.sort.set("savedOn", "ASC");
642
+ await vi.waitFor(()=>{
643
+ expect(t.presenter.list.vm.appliedQuery?.sort?.direction).toBe("ASC");
644
+ });
645
+ await publish(entries[1]);
646
+ expect(t.presenter.list.vm.rows.map((r)=>r.entryId)).toEqual([
647
+ "entry-1",
648
+ "entry-2",
649
+ "entry-3"
650
+ ]);
651
+ });
652
+ });
585
653
  });
586
654
 
587
655
  //# sourceMappingURL=ContentEntriesPresenter.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/list/ContentEntriesPresenter.test.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesPresenter.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { makeAutoObservable } from \"mobx\";\nimport { ListPresenterFeature } from \"@webiny/app-admin/presentation/listPresenter/index.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport { ContentEntriesCacheProvider } from \"~/features/contentEntry/ContentEntriesCacheProvider.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport { CmsModelContext as CmsModelContextImpl } from \"~/features/contentEntry/CmsModelContext.js\";\nimport { ListEntriesFeature } from \"~/features/contentEntry/listEntries/feature.js\";\nimport { DeleteEntryFeature } from \"~/features/contentEntry/deleteEntry/feature.js\";\nimport { PublishEntryFeature } from \"~/features/contentEntry/publishEntry/feature.js\";\nimport { UnpublishEntryFeature } from \"~/features/contentEntry/unpublishEntry/feature.js\";\nimport { MoveEntryFeature } from \"~/features/contentEntry/moveEntry/feature.js\";\nimport { UpdateRevisionDescriptionFeature } from \"~/features/contentEntry/updateRevisionDescription/feature.js\";\nimport { ListEntriesGateway } from \"~/features/contentEntry/listEntries/abstractions.js\";\nimport { DeleteEntryGateway } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport { PublishEntryGateway } from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryGateway } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { MoveEntryGateway } from \"~/features/contentEntry/moveEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionGateway } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport { EventPublisher } from \"@webiny/app/features/eventPublisher/index.js\";\nimport { ContentEntriesPresenter as Abstraction } from \"./abstractions.js\";\nimport { ContentEntriesPresenter } from \"./ContentEntriesPresenter.js\";\nimport type { IContentEntriesPresenter } from \"./abstractions.js\";\nimport type {\n IFolderTreeViewModel,\n IFolderOperationState\n} from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\n\nconst MODEL: CmsModel = {\n modelId: \"testModel\",\n name: \"Test Model\",\n singularApiName: \"TestModel\",\n pluralApiName: \"TestModels\",\n fields: [],\n layout: [],\n group: \"group-1\",\n titleFieldId: \"title\",\n descriptionFieldId: null,\n imageFieldId: null,\n tags: [],\n savedOn: \"\"\n} as unknown as CmsModel;\n\nfunction createEntry(\n entryId: string,\n folderId: string,\n overrides: Partial<CmsContentEntry> = {}\n): CmsContentEntry {\n return {\n id: `${entryId}#0001`,\n entryId,\n meta: {\n title: entryId,\n status: \"draft\",\n version: 1,\n locked: false\n },\n wbyAco_location: { folderId },\n values: {},\n createdBy: { id: \"user-1\", displayName: \"Test\", type: \"admin\" },\n createdOn: \"2024-01-01T00:00:00Z\",\n savedOn: \"2024-01-01T00:00:00Z\",\n ...overrides\n } as unknown as CmsContentEntry;\n}\n\nclass MockFolderTreePresenter implements FolderTreePresenter.Interface {\n private _currentFolderId: string | null = null;\n\n constructor() {\n makeAutoObservable(this);\n }\n\n get vm(): IFolderTreeViewModel {\n return {\n folders: [],\n tree: [],\n currentFolderId: this._currentFolderId,\n currentFolder: null,\n isRootFolder: this._currentFolderId === null,\n currentFolderTitle: \"Home\",\n childFolders: [],\n loading: false,\n loadingNodeIds: [],\n operation: { active: false, mode: null } as IFolderOperationState\n };\n }\n\n selectFolder(folderId: string | null): void {\n this._currentFolderId = folderId;\n }\n\n createFolder(): void {}\n editFolder(): void {}\n async deleteFolder(): Promise<void> {}\n async moveFolder(): Promise<void> {}\n async loadChildFolders(): Promise<void> {}\n canManageStructure(): boolean {\n return true;\n }\n getAncestorIds(): string[] {\n return [];\n }\n async submitOperation(): Promise<boolean> {\n return true;\n }\n cancelOperation(): void {}\n onFolderChange(): () => void {\n return () => {};\n }\n}\n\ninterface TestSetup {\n presenter: IContentEntriesPresenter;\n listEntriesGateway: { execute: ReturnType<typeof vi.fn> };\n moveEntryGateway: { execute: ReturnType<typeof vi.fn> };\n deleteEntryGateway: { execute: ReturnType<typeof vi.fn> };\n getDescendantFolders: ReturnType<typeof vi.fn>;\n foldersPresenter: MockFolderTreePresenter;\n}\n\nfunction setup(): TestSetup {\n const container = new Container();\n\n ListPresenterFeature.register(container);\n\n const foldersPresenter = new MockFolderTreePresenter();\n container.registerInstance(FolderTreePresenter, foldersPresenter);\n\n container.registerInstance(Confirmation, {\n confirm: vi.fn(async (_name, _params, execute) => {\n if (execute) {\n await execute(undefined);\n }\n return true;\n })\n } as unknown as Confirmation.Interface);\n\n const getDescendantFolders = vi.fn().mockReturnValue([]);\n container.registerInstance(GetDescendantFoldersUseCase, {\n execute: getDescendantFolders\n });\n\n container.registerInstance(EventPublisher, { publish: vi.fn() });\n container.register(ContentEntriesCacheProvider).inSingletonScope();\n container.register(CmsModelContextImpl).inSingletonScope();\n container.resolve(CmsModelContext).setModel(MODEL);\n\n ListEntriesFeature.register(container);\n DeleteEntryFeature.register(container);\n PublishEntryFeature.register(container);\n UnpublishEntryFeature.register(container);\n MoveEntryFeature.register(container);\n UpdateRevisionDescriptionFeature.register(container);\n\n const listEntriesGateway = { execute: vi.fn() };\n const moveEntryGateway = { execute: vi.fn() };\n const deleteEntryGateway = { execute: vi.fn() };\n\n container.registerInstance(ListEntriesGateway, listEntriesGateway);\n container.registerInstance(MoveEntryGateway, moveEntryGateway);\n container.registerInstance(DeleteEntryGateway, deleteEntryGateway);\n container.registerInstance(PublishEntryGateway, { execute: vi.fn() });\n container.registerInstance(UnpublishEntryGateway, { execute: vi.fn() });\n container.registerInstance(UpdateRevisionDescriptionGateway, { execute: vi.fn() });\n\n container.register(ContentEntriesPresenter).inSingletonScope();\n const presenter = container.resolve(Abstraction);\n\n return {\n presenter,\n listEntriesGateway,\n moveEntryGateway,\n deleteEntryGateway,\n getDescendantFolders,\n foldersPresenter\n };\n}\n\nasync function initPresenter(\n t: TestSetup,\n gatewayResponse: { data: CmsContentEntry[]; meta?: object }\n) {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: gatewayResponse.data,\n meta: gatewayResponse.meta ?? {\n cursor: null,\n hasMoreItems: false,\n totalCount: gatewayResponse.data.length\n }\n });\n\n t.presenter.init();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n}\n\ndescribe(\"ContentEntriesPresenter\", () => {\n let t: TestSetup;\n\n beforeEach(() => {\n t = setup();\n });\n\n describe(\"initial load\", () => {\n it(\"should show root entries after setModel\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n\n await initPresenter(t, { data: entries });\n\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"entry-1\", \"entry-2\"]);\n });\n\n it(\"should send folderId=root in the gateway query\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.listEntriesGateway.execute).toHaveBeenCalledWith(\n expect.objectContaining({\n where: expect.objectContaining({\n wbyAco_location: { folderId: \"root\" }\n })\n })\n );\n });\n\n it(\"should set model after init\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n });\n\n describe(\"folder navigation\", () => {\n it(\"should filter to folder entries when navigating to a subfolder\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"folder-2\", \"folder-a\")\n ];\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"folder-1\", \"folder-2\"]);\n });\n\n it(\"should show only root entries when navigating back to root\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"folder-1\");\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n\n it(\"should not leak subfolder entries into root view\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"folder-1\", \"folder-a\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n });\n\n describe(\"search\", () => {\n it(\"should show only search results from API\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const searchResults = [createEntry(\"entry-1\", \"root\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-1\");\n });\n\n it(\"should include entries from subfolders when searching from root\", async () => {\n await initPresenter(t, { data: [] });\n\n const searchResults = [\n createEntry(\"root-1\", \"root\"),\n createEntry(\"folder-1\", \"folder-a\")\n ];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n\n it(\"should search with folderId_in containing all descendant folders when in a subfolder\", async () => {\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.init({ initialFolderId: \"folder-a\" });\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n\n t.getDescendantFolders.mockReturnValue([\n { id: \"folder-a\" },\n { id: \"folder-a-1\" },\n { id: \"folder-a-2\" }\n ]);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"sub-1\", \"folder-a-1\"),\n createEntry(\"sub-2\", \"folder-a-2\")\n ],\n meta: { cursor: null, hasMoreItems: false, totalCount: 3 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(3);\n });\n\n expect(t.getDescendantFolders).toHaveBeenCalledWith(\"folder-a\");\n\n const searchCall = t.listEntriesGateway.execute.mock.calls.at(-1) ?? [];\n expect(searchCall[0].where).toEqual(\n expect.objectContaining({\n wbyAco_location: {\n folderId_in: [\"folder-a\", \"folder-a-1\", \"folder-a-2\"]\n }\n })\n );\n });\n\n it(\"should restore folder view when clearing search\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"entry-1\", \"root\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.clear();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n });\n\n describe(\"status filter\", () => {\n it(\"should filter by status locally\", async () => {\n const entries = [\n createEntry(\"draft-1\", \"root\", {\n meta: {\n title: \"draft-1\",\n status: \"draft\",\n version: 1,\n locked: false\n }\n }),\n createEntry(\"published-1\", \"root\", {\n meta: {\n title: \"published-1\",\n status: \"published\",\n version: 1,\n locked: false\n }\n })\n ];\n await initPresenter(t, { data: entries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: entries.filter(e => (e.meta as { status: string }).status === \"published\"),\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.filter.set(\"status\", \"published\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"published-1\");\n });\n });\n });\n\n describe(\"move entry\", () => {\n it(\"should remove entry from current view after move\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.moveEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.moveEntry(\"entry-1#0001\", \"folder-b\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"delete entry\", () => {\n it(\"should remove entry from current view after delete\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.deleteEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.deleteEntry(\"entry-1#0001\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"vm\", () => {\n it(\"should set model on init\", () => {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n t.presenter.init();\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n\n it(\"should track selected entry\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showingEntry).toBe(false);\n\n t.presenter.selectEntry(\"some-id\");\n expect(t.presenter.vm.selectedEntryId).toBe(\"some-id\");\n expect(t.presenter.vm.showingEntry).toBe(true);\n\n t.presenter.deselectEntry();\n expect(t.presenter.vm.selectedEntryId).toBeNull();\n expect(t.presenter.vm.showingEntry).toBe(false);\n });\n\n it(\"should set selectedEntryId to 'new' on createEntry\", async () => {\n await initPresenter(t, { data: [] });\n\n t.presenter.createEntry();\n expect(t.presenter.vm.selectedEntryId).toBe(\"new\");\n });\n\n it(\"should show folders when no search or non-folder filters active\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showFolders).toBe(true);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.vm.showFolders).toBe(false);\n });\n });\n });\n});\n"],"names":["MODEL","createEntry","entryId","folderId","overrides","MockFolderTreePresenter","makeAutoObservable","setup","container","Container","ListPresenterFeature","foldersPresenter","FolderTreePresenter","Confirmation","vi","_name","_params","execute","undefined","getDescendantFolders","GetDescendantFoldersUseCase","EventPublisher","ContentEntriesCacheProvider","CmsModelContextImpl","CmsModelContext","ListEntriesFeature","DeleteEntryFeature","PublishEntryFeature","UnpublishEntryFeature","MoveEntryFeature","UpdateRevisionDescriptionFeature","listEntriesGateway","moveEntryGateway","deleteEntryGateway","ListEntriesGateway","MoveEntryGateway","DeleteEntryGateway","PublishEntryGateway","UnpublishEntryGateway","UpdateRevisionDescriptionGateway","ContentEntriesPresenter","presenter","Abstraction","initPresenter","t","gatewayResponse","expect","describe","beforeEach","it","entries","r","rootEntries","folderEntries","searchResults","searchCall","e"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/contentEntries/list/ContentEntriesPresenter.test.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesPresenter.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { makeAutoObservable } from \"mobx\";\nimport { ListPresenterFeature } from \"@webiny/app-admin/presentation/listPresenter/index.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport { ContentEntriesCacheProvider } from \"~/features/contentEntry/ContentEntriesCacheProvider.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport { CmsModelContext as CmsModelContextImpl } from \"~/features/contentEntry/CmsModelContext.js\";\nimport { ListEntriesFeature } from \"~/features/contentEntry/listEntries/feature.js\";\nimport { DeleteEntryFeature } from \"~/features/contentEntry/deleteEntry/feature.js\";\nimport { PublishEntryFeature } from \"~/features/contentEntry/publishEntry/feature.js\";\nimport { UnpublishEntryFeature } from \"~/features/contentEntry/unpublishEntry/feature.js\";\nimport { MoveEntryFeature } from \"~/features/contentEntry/moveEntry/feature.js\";\nimport { UpdateRevisionDescriptionFeature } from \"~/features/contentEntry/updateRevisionDescription/feature.js\";\nimport { ListEntriesGateway } from \"~/features/contentEntry/listEntries/abstractions.js\";\nimport { DeleteEntryGateway } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport {\n PublishEntryGateway,\n PublishEntryUseCase\n} from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryGateway } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { MoveEntryGateway } from \"~/features/contentEntry/moveEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionGateway } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport { EventPublisher } from \"@webiny/app/features/eventPublisher/index.js\";\nimport { ContentEntriesPresenter as Abstraction } from \"./abstractions.js\";\nimport { ContentEntriesPresenter } from \"./ContentEntriesPresenter.js\";\nimport type { IContentEntriesPresenter } from \"./abstractions.js\";\nimport type {\n IFolderTreeViewModel,\n IFolderOperationState\n} from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\n\nconst MODEL: CmsModel = {\n modelId: \"testModel\",\n name: \"Test Model\",\n singularApiName: \"TestModel\",\n pluralApiName: \"TestModels\",\n fields: [],\n layout: [],\n group: \"group-1\",\n titleFieldId: \"title\",\n descriptionFieldId: null,\n imageFieldId: null,\n tags: [],\n savedOn: \"\"\n} as unknown as CmsModel;\n\nfunction createEntry(\n entryId: string,\n folderId: string,\n overrides: Partial<CmsContentEntry> = {}\n): CmsContentEntry {\n return {\n id: `${entryId}#0001`,\n entryId,\n meta: {\n title: entryId,\n status: \"draft\",\n version: 1,\n locked: false\n },\n wbyAco_location: { folderId },\n values: {},\n createdBy: { id: \"user-1\", displayName: \"Test\", type: \"admin\" },\n createdOn: \"2024-01-01T00:00:00Z\",\n savedOn: \"2024-01-01T00:00:00Z\",\n ...overrides\n } as unknown as CmsContentEntry;\n}\n\nclass MockFolderTreePresenter implements FolderTreePresenter.Interface {\n private _currentFolderId: string | null = null;\n\n constructor() {\n makeAutoObservable(this);\n }\n\n get vm(): IFolderTreeViewModel {\n return {\n folders: [],\n tree: [],\n currentFolderId: this._currentFolderId,\n currentFolder: null,\n isRootFolder: this._currentFolderId === null,\n currentFolderTitle: \"Home\",\n childFolders: [],\n loading: false,\n loadingNodeIds: [],\n operation: { active: false, mode: null } as IFolderOperationState\n };\n }\n\n selectFolder(folderId: string | null): void {\n this._currentFolderId = folderId;\n }\n\n createFolder(): void {}\n editFolder(): void {}\n async deleteFolder(): Promise<void> {}\n async moveFolder(): Promise<void> {}\n async loadChildFolders(): Promise<void> {}\n canManageStructure(): boolean {\n return true;\n }\n getAncestorIds(): string[] {\n return [];\n }\n async submitOperation(): Promise<boolean> {\n return true;\n }\n cancelOperation(): void {}\n onFolderChange(): () => void {\n return () => {};\n }\n}\n\ninterface TestSetup {\n presenter: IContentEntriesPresenter;\n listEntriesGateway: { execute: ReturnType<typeof vi.fn> };\n moveEntryGateway: { execute: ReturnType<typeof vi.fn> };\n deleteEntryGateway: { execute: ReturnType<typeof vi.fn> };\n getDescendantFolders: ReturnType<typeof vi.fn>;\n foldersPresenter: MockFolderTreePresenter;\n publishEntryGateway: { execute: ReturnType<typeof vi.fn> };\n container: Container;\n}\n\nfunction setup(): TestSetup {\n const container = new Container();\n\n ListPresenterFeature.register(container);\n\n const foldersPresenter = new MockFolderTreePresenter();\n container.registerInstance(FolderTreePresenter, foldersPresenter);\n\n container.registerInstance(Confirmation, {\n confirm: vi.fn(async (_name, _params, execute) => {\n if (execute) {\n await execute(undefined);\n }\n return true;\n })\n } as unknown as Confirmation.Interface);\n\n const getDescendantFolders = vi.fn().mockReturnValue([]);\n container.registerInstance(GetDescendantFoldersUseCase, {\n execute: getDescendantFolders\n });\n\n container.registerInstance(EventPublisher, { publish: vi.fn() });\n container.register(ContentEntriesCacheProvider).inSingletonScope();\n container.register(CmsModelContextImpl).inSingletonScope();\n container.resolve(CmsModelContext).setModel(MODEL);\n\n ListEntriesFeature.register(container);\n DeleteEntryFeature.register(container);\n PublishEntryFeature.register(container);\n UnpublishEntryFeature.register(container);\n MoveEntryFeature.register(container);\n UpdateRevisionDescriptionFeature.register(container);\n\n const listEntriesGateway = { execute: vi.fn() };\n const moveEntryGateway = { execute: vi.fn() };\n const deleteEntryGateway = { execute: vi.fn() };\n\n container.registerInstance(ListEntriesGateway, listEntriesGateway);\n container.registerInstance(MoveEntryGateway, moveEntryGateway);\n container.registerInstance(DeleteEntryGateway, deleteEntryGateway);\n const publishEntryGateway = { execute: vi.fn() };\n container.registerInstance(PublishEntryGateway, publishEntryGateway);\n container.registerInstance(UnpublishEntryGateway, { execute: vi.fn() });\n container.registerInstance(UpdateRevisionDescriptionGateway, { execute: vi.fn() });\n\n container.register(ContentEntriesPresenter).inSingletonScope();\n const presenter = container.resolve(Abstraction);\n\n return {\n presenter,\n listEntriesGateway,\n moveEntryGateway,\n deleteEntryGateway,\n getDescendantFolders,\n foldersPresenter,\n publishEntryGateway,\n container\n };\n}\n\nasync function initPresenter(\n t: TestSetup,\n gatewayResponse: { data: CmsContentEntry[]; meta?: object }\n) {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: gatewayResponse.data,\n meta: gatewayResponse.meta ?? {\n cursor: null,\n hasMoreItems: false,\n totalCount: gatewayResponse.data.length\n }\n });\n\n t.presenter.init();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n}\n\ndescribe(\"ContentEntriesPresenter\", () => {\n let t: TestSetup;\n\n beforeEach(() => {\n t = setup();\n });\n\n describe(\"initial load\", () => {\n it(\"should show root entries after setModel\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n\n await initPresenter(t, { data: entries });\n\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"entry-1\", \"entry-2\"]);\n });\n\n it(\"should send folderId=root in the gateway query\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.listEntriesGateway.execute).toHaveBeenCalledWith(\n expect.objectContaining({\n where: expect.objectContaining({\n wbyAco_location: { folderId: \"root\" }\n })\n })\n );\n });\n\n it(\"should set model after init\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n });\n\n describe(\"folder navigation\", () => {\n it(\"should filter to folder entries when navigating to a subfolder\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"folder-2\", \"folder-a\")\n ];\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"folder-1\", \"folder-2\"]);\n });\n\n it(\"should show only root entries when navigating back to root\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"folder-1\");\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n\n it(\"should not leak subfolder entries into root view\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"folder-1\", \"folder-a\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n });\n\n describe(\"search\", () => {\n it(\"should show only search results from API\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const searchResults = [createEntry(\"entry-1\", \"root\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-1\");\n });\n\n it(\"should include entries from subfolders when searching from root\", async () => {\n await initPresenter(t, { data: [] });\n\n const searchResults = [\n createEntry(\"root-1\", \"root\"),\n createEntry(\"folder-1\", \"folder-a\")\n ];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n\n it(\"should search with folderId_in containing all descendant folders when in a subfolder\", async () => {\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.init({ initialFolderId: \"folder-a\" });\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n\n t.getDescendantFolders.mockReturnValue([\n { id: \"folder-a\" },\n { id: \"folder-a-1\" },\n { id: \"folder-a-2\" }\n ]);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"sub-1\", \"folder-a-1\"),\n createEntry(\"sub-2\", \"folder-a-2\")\n ],\n meta: { cursor: null, hasMoreItems: false, totalCount: 3 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(3);\n });\n\n expect(t.getDescendantFolders).toHaveBeenCalledWith(\"folder-a\");\n\n const searchCall = t.listEntriesGateway.execute.mock.calls.at(-1) ?? [];\n expect(searchCall[0].where).toEqual(\n expect.objectContaining({\n wbyAco_location: {\n folderId_in: [\"folder-a\", \"folder-a-1\", \"folder-a-2\"]\n }\n })\n );\n });\n\n it(\"should restore folder view when clearing search\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"entry-1\", \"root\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.clear();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n });\n\n describe(\"status filter\", () => {\n it(\"should filter by status locally\", async () => {\n const entries = [\n createEntry(\"draft-1\", \"root\", {\n meta: {\n title: \"draft-1\",\n status: \"draft\",\n version: 1,\n locked: false\n }\n }),\n createEntry(\"published-1\", \"root\", {\n meta: {\n title: \"published-1\",\n status: \"published\",\n version: 1,\n locked: false\n }\n })\n ];\n await initPresenter(t, { data: entries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: entries.filter(e => (e.meta as { status: string }).status === \"published\"),\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.filter.set(\"status\", \"published\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"published-1\");\n });\n });\n });\n\n describe(\"move entry\", () => {\n it(\"should remove entry from current view after move\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.moveEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.moveEntry(\"entry-1#0001\", \"folder-b\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"delete entry\", () => {\n it(\"should remove entry from current view after delete\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.deleteEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.deleteEntry(\"entry-1#0001\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"vm\", () => {\n it(\"should set model on init\", () => {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n t.presenter.init();\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n\n it(\"should track selected entry\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showingEntry).toBe(false);\n\n t.presenter.selectEntry(\"some-id\");\n expect(t.presenter.vm.selectedEntryId).toBe(\"some-id\");\n expect(t.presenter.vm.showingEntry).toBe(true);\n\n t.presenter.deselectEntry();\n expect(t.presenter.vm.selectedEntryId).toBeNull();\n expect(t.presenter.vm.showingEntry).toBe(false);\n });\n\n it(\"should set selectedEntryId to 'new' on createEntry\", async () => {\n await initPresenter(t, { data: [] });\n\n t.presenter.createEntry();\n expect(t.presenter.vm.selectedEntryId).toBe(\"new\");\n });\n\n it(\"should show folders when no search or non-folder filters active\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showFolders).toBe(true);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.vm.showFolders).toBe(false);\n });\n });\n });\n\n describe(\"publish entry\", () => {\n /**\n * Publishing is not a content modification: the API returns the entry with its\n * `savedOn` unchanged, so the entry must keep its position in a list sorted by `savedOn`.\n */\n const entries = [\n createEntry(\"entry-3\", \"root\", { savedOn: \"2024-01-03T00:00:00.000Z\" }),\n createEntry(\"entry-2\", \"root\", { savedOn: \"2024-01-02T00:00:00.000Z\" }),\n createEntry(\"entry-1\", \"root\", { savedOn: \"2024-01-01T00:00:00.000Z\" })\n ];\n\n const publish = async (entry: CmsContentEntry) => {\n t.publishEntryGateway.execute.mockResolvedValueOnce({\n ...entry,\n meta: { ...entry.meta, status: \"published\", locked: true }\n });\n await t.container\n .resolve(PublishEntryUseCase)\n .execute({ model: MODEL, revisionId: entry.id });\n };\n\n it(\"should keep a published entry in its position\", async () => {\n await initPresenter(t, { data: entries });\n\n await publish(entries[1]);\n\n const rows = t.presenter.list.vm.rows;\n expect(rows.map(r => r.entryId)).toEqual([\"entry-3\", \"entry-2\", \"entry-1\"]);\n expect((rows[1].meta as { status: string }).status).toBe(\"published\");\n });\n\n it(\"should keep a published entry in its position when sorted ascending\", async () => {\n await initPresenter(t, { data: entries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [...entries].reverse(),\n meta: { cursor: null, hasMoreItems: false, totalCount: entries.length }\n });\n t.presenter.list.actions.sort.set(\"savedOn\", \"ASC\");\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.appliedQuery?.sort?.direction).toBe(\"ASC\");\n });\n\n await publish(entries[1]);\n\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\n \"entry-1\",\n \"entry-2\",\n \"entry-3\"\n ]);\n });\n });\n});\n"],"names":["MODEL","createEntry","entryId","folderId","overrides","MockFolderTreePresenter","makeAutoObservable","setup","container","Container","ListPresenterFeature","foldersPresenter","FolderTreePresenter","Confirmation","vi","_name","_params","execute","undefined","getDescendantFolders","GetDescendantFoldersUseCase","EventPublisher","ContentEntriesCacheProvider","CmsModelContextImpl","CmsModelContext","ListEntriesFeature","DeleteEntryFeature","PublishEntryFeature","UnpublishEntryFeature","MoveEntryFeature","UpdateRevisionDescriptionFeature","listEntriesGateway","moveEntryGateway","deleteEntryGateway","ListEntriesGateway","MoveEntryGateway","DeleteEntryGateway","publishEntryGateway","PublishEntryGateway","UnpublishEntryGateway","UpdateRevisionDescriptionGateway","ContentEntriesPresenter","presenter","Abstraction","initPresenter","t","gatewayResponse","expect","describe","beforeEach","it","entries","r","rootEntries","folderEntries","searchResults","searchCall","e","publish","entry","PublishEntryUseCase","rows"],"mappings":"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"}
@@ -16,6 +16,7 @@ declare class NewContentModelPresenterImpl implements INewContentModelPresenter
16
16
  private form;
17
17
  constructor(formModelFactory: FormModelFactory.Interface, listModelGroupsUseCase: ListModelGroupsUseCase.Interface, createModelUseCase: CreateModelUseCase.Interface, groupsCache: ModelGroupsCache.Interface, modelsCache: ModelsCache.Interface);
18
18
  get vm(): INewContentModelPresenterViewModel;
19
+ private get groupOptions();
19
20
  init(): Promise<void>;
20
21
  save(): Promise<CmsModel | null>;
21
22
  reset(): void;
@@ -26,18 +26,20 @@ class NewContentModelPresenterImpl {
26
26
  });
27
27
  }
28
28
  get vm() {
29
- const groups = this.groupsCache.getItems().map((g)=>({
30
- value: g.slug,
31
- label: g.name
32
- }));
33
29
  return {
34
30
  loading: this.loading,
35
31
  saving: this.saving,
36
- groups,
32
+ groups: this.groupOptions,
37
33
  models: this.modelsCache.getItems(),
38
34
  form: this.form.vm
39
35
  };
40
36
  }
37
+ get groupOptions() {
38
+ return this.groupsCache.getItems().map((group)=>({
39
+ value: group.slug,
40
+ label: group.name
41
+ }));
42
+ }
41
43
  async init() {
42
44
  try {
43
45
  await this.listModelGroupsUseCase.execute();
@@ -97,7 +99,7 @@ class NewContentModelPresenterImpl {
97
99
  singularApiName: fields.text().label("Singular API Name").required("Singular API Name is required."),
98
100
  singleEntry: fields.boolean().label("Single entry model").defaultValue(false),
99
101
  pluralApiName: fields.text().label("Plural API Name"),
100
- group: fields.text().label("Content model group").required("Group is required."),
102
+ group: fields.text().label("Content model group").required("Group is required.").options(()=>this.groupOptions),
101
103
  icon: fields.text().label("Icon").renderer("cmsIconPicker"),
102
104
  description: fields.text().label("Description").renderer("textarea"),
103
105
  defaultFields: fields.boolean().label("Create model with default fields").defaultValue(true)
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/newContentModel/NewContentModelPresenter.js","sources":["../../../src/presentation/newContentModel/NewContentModelPresenter.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModel } from \"~/types.js\";\nimport { ListModelGroupsUseCase } from \"~/features/modelGroup/listModelGroups/abstractions.js\";\nimport { CreateModelUseCase } from \"~/features/model/createModel/abstractions.js\";\nimport { ModelGroupsCache } from \"~/features/modelGroup/abstractions.js\";\nimport { ModelsCache } from \"~/features/model/abstractions.js\";\nconst CMS_MODEL_SINGLETON_TAG = \"singleEntry\";\nimport {\n NewContentModelPresenter as Abstraction,\n type INewContentModelPresenter,\n type INewContentModelPresenterViewModel\n} from \"./abstractions.js\";\n\nclass NewContentModelPresenterImpl implements INewContentModelPresenter {\n private loading = true;\n private saving = false;\n private form: IFormModel;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private listModelGroupsUseCase: ListModelGroupsUseCase.Interface,\n private createModelUseCase: CreateModelUseCase.Interface,\n private groupsCache: ModelGroupsCache.Interface,\n private modelsCache: ModelsCache.Interface\n ) {\n this.form = this.buildForm();\n makeAutoObservable<\n NewContentModelPresenterImpl,\n | \"formModelFactory\"\n | \"listModelGroupsUseCase\"\n | \"createModelUseCase\"\n | \"groupsCache\"\n | \"modelsCache\"\n >(this, {\n formModelFactory: false,\n listModelGroupsUseCase: false,\n createModelUseCase: false,\n groupsCache: false,\n modelsCache: false,\n vm: computed\n });\n }\n\n get vm(): INewContentModelPresenterViewModel {\n const groups = this.groupsCache.getItems().map(g => ({\n value: g.slug,\n label: g.name\n }));\n\n return {\n loading: this.loading,\n saving: this.saving,\n groups,\n models: this.modelsCache.getItems(),\n form: this.form.vm\n };\n }\n\n async init(): Promise<void> {\n try {\n await this.listModelGroupsUseCase.execute();\n } finally {\n runInAction(() => {\n this.loading = false;\n const groups = this.groupsCache.getItems();\n if (groups.length > 0) {\n this.form.setData({ group: groups[0].slug });\n }\n });\n }\n }\n\n async save(): Promise<CmsModel | null> {\n const data = await this.form.submit<Record<string, any>>();\n if (!data) {\n return null;\n }\n\n runInAction(() => {\n this.saving = true;\n });\n\n try {\n const tags: string[] = Array.isArray(data.tags) ? data.tags : [];\n let pluralApiName = data.pluralApiName as string;\n\n if (data.singleEntry) {\n tags.push(CMS_MODEL_SINGLETON_TAG);\n pluralApiName = `${data.singularApiName}Unused`;\n }\n\n const model = await this.createModelUseCase.execute({\n name: data.name as string,\n singularApiName: data.singularApiName as string,\n pluralApiName,\n group: data.group as string,\n icon: data.icon as string | undefined,\n description: data.description as string | undefined,\n defaultFields: data.defaultFields as boolean | undefined,\n tags\n });\n\n return model;\n } catch {\n return null;\n } finally {\n runInAction(() => {\n this.saving = false;\n });\n }\n }\n\n reset(): void {\n this.form = this.buildForm();\n const groups = this.groupsCache.getItems();\n if (groups.length > 0) {\n this.form.setData({ group: groups[0].slug });\n }\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required.\"),\n singularApiName: fields\n .text()\n .label(\"Singular API Name\")\n .required(\"Singular API Name is required.\"),\n singleEntry: fields.boolean().label(\"Single entry model\").defaultValue(false),\n pluralApiName: fields.text().label(\"Plural API Name\"),\n group: fields.text().label(\"Content model group\").required(\"Group is required.\"),\n icon: fields.text().label(\"Icon\").renderer(\"cmsIconPicker\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\"),\n defaultFields: fields\n .boolean()\n .label(\"Create model with default fields\")\n .defaultValue(true)\n }),\n layout: layout => [\n layout.row(\"name\"),\n layout.row(\"singularApiName\"),\n layout.row(\"singleEntry\"),\n layout.row(\"pluralApiName\"),\n layout.row(\"group\"),\n layout.row(\"icon\"),\n layout.row(\"description\"),\n layout.row(\"defaultFields\")\n ]\n });\n }\n}\n\nexport const NewContentModelPresenter = Abstraction.createImplementation({\n implementation: NewContentModelPresenterImpl,\n dependencies: [\n FormModelFactory,\n ListModelGroupsUseCase,\n CreateModelUseCase,\n ModelGroupsCache,\n ModelsCache\n ]\n});\n"],"names":["CMS_MODEL_SINGLETON_TAG","NewContentModelPresenterImpl","formModelFactory","listModelGroupsUseCase","createModelUseCase","groupsCache","modelsCache","makeAutoObservable","computed","groups","g","runInAction","data","tags","Array","pluralApiName","model","fields","layout","NewContentModelPresenter","Abstraction","FormModelFactory","ListModelGroupsUseCase","CreateModelUseCase","ModelGroupsCache","ModelsCache"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/newContentModel/NewContentModelPresenter.js","sources":["../../../src/presentation/newContentModel/NewContentModelPresenter.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsModel } from \"~/types.js\";\nimport { ListModelGroupsUseCase } from \"~/features/modelGroup/listModelGroups/abstractions.js\";\nimport { CreateModelUseCase } from \"~/features/model/createModel/abstractions.js\";\nimport { ModelGroupsCache } from \"~/features/modelGroup/abstractions.js\";\nimport { ModelsCache } from \"~/features/model/abstractions.js\";\nconst CMS_MODEL_SINGLETON_TAG = \"singleEntry\";\nimport {\n NewContentModelPresenter as Abstraction,\n type INewContentModelPresenter,\n type INewContentModelPresenterViewModel\n} from \"./abstractions.js\";\n\nclass NewContentModelPresenterImpl implements INewContentModelPresenter {\n private loading = true;\n private saving = false;\n private form: IFormModel;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private listModelGroupsUseCase: ListModelGroupsUseCase.Interface,\n private createModelUseCase: CreateModelUseCase.Interface,\n private groupsCache: ModelGroupsCache.Interface,\n private modelsCache: ModelsCache.Interface\n ) {\n this.form = this.buildForm();\n makeAutoObservable<\n NewContentModelPresenterImpl,\n | \"formModelFactory\"\n | \"listModelGroupsUseCase\"\n | \"createModelUseCase\"\n | \"groupsCache\"\n | \"modelsCache\"\n >(this, {\n formModelFactory: false,\n listModelGroupsUseCase: false,\n createModelUseCase: false,\n groupsCache: false,\n modelsCache: false,\n vm: computed\n });\n }\n\n get vm(): INewContentModelPresenterViewModel {\n return {\n loading: this.loading,\n saving: this.saving,\n groups: this.groupOptions,\n models: this.modelsCache.getItems(),\n form: this.form.vm\n };\n }\n\n private get groupOptions() {\n return this.groupsCache.getItems().map(group => ({\n value: group.slug,\n label: group.name\n }));\n }\n\n async init(): Promise<void> {\n try {\n await this.listModelGroupsUseCase.execute();\n } finally {\n runInAction(() => {\n this.loading = false;\n const groups = this.groupsCache.getItems();\n if (groups.length > 0) {\n this.form.setData({ group: groups[0].slug });\n }\n });\n }\n }\n\n async save(): Promise<CmsModel | null> {\n const data = await this.form.submit<Record<string, any>>();\n if (!data) {\n return null;\n }\n\n runInAction(() => {\n this.saving = true;\n });\n\n try {\n const tags: string[] = Array.isArray(data.tags) ? data.tags : [];\n let pluralApiName = data.pluralApiName as string;\n\n if (data.singleEntry) {\n tags.push(CMS_MODEL_SINGLETON_TAG);\n pluralApiName = `${data.singularApiName}Unused`;\n }\n\n const model = await this.createModelUseCase.execute({\n name: data.name as string,\n singularApiName: data.singularApiName as string,\n pluralApiName,\n group: data.group as string,\n icon: data.icon as string | undefined,\n description: data.description as string | undefined,\n defaultFields: data.defaultFields as boolean | undefined,\n tags\n });\n\n return model;\n } catch {\n return null;\n } finally {\n runInAction(() => {\n this.saving = false;\n });\n }\n }\n\n reset(): void {\n this.form = this.buildForm();\n const groups = this.groupsCache.getItems();\n if (groups.length > 0) {\n this.form.setData({ group: groups[0].slug });\n }\n }\n\n private buildForm(): IFormModel {\n return this.formModelFactory.create({\n fields: fields => ({\n name: fields.text().label(\"Name\").required(\"Name is required.\"),\n singularApiName: fields\n .text()\n .label(\"Singular API Name\")\n .required(\"Singular API Name is required.\"),\n singleEntry: fields.boolean().label(\"Single entry model\").defaultValue(false),\n pluralApiName: fields.text().label(\"Plural API Name\"),\n group: fields\n .text()\n .label(\"Content model group\")\n .required(\"Group is required.\")\n /*\n * Options turn the text field into a select. The groups arrive after the form\n * is built, so they have to be read through a callback.\n */\n .options(() => this.groupOptions),\n icon: fields.text().label(\"Icon\").renderer(\"cmsIconPicker\"),\n description: fields.text().label(\"Description\").renderer(\"textarea\"),\n defaultFields: fields\n .boolean()\n .label(\"Create model with default fields\")\n .defaultValue(true)\n }),\n layout: layout => [\n layout.row(\"name\"),\n layout.row(\"singularApiName\"),\n layout.row(\"singleEntry\"),\n layout.row(\"pluralApiName\"),\n layout.row(\"group\"),\n layout.row(\"icon\"),\n layout.row(\"description\"),\n layout.row(\"defaultFields\")\n ]\n });\n }\n}\n\nexport const NewContentModelPresenter = Abstraction.createImplementation({\n implementation: NewContentModelPresenterImpl,\n dependencies: [\n FormModelFactory,\n ListModelGroupsUseCase,\n CreateModelUseCase,\n ModelGroupsCache,\n ModelsCache\n ]\n});\n"],"names":["CMS_MODEL_SINGLETON_TAG","NewContentModelPresenterImpl","formModelFactory","listModelGroupsUseCase","createModelUseCase","groupsCache","modelsCache","makeAutoObservable","computed","group","runInAction","groups","data","tags","Array","pluralApiName","model","fields","layout","NewContentModelPresenter","Abstraction","FormModelFactory","ListModelGroupsUseCase","CreateModelUseCase","ModelGroupsCache","ModelsCache"],"mappings":"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"}