@webiny/app-headless-cms 6.5.0-beta.0 → 6.5.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +20 -20
- package/presentation/cloneContentModel/CloneContentModelPresenter.d.ts +1 -0
- package/presentation/cloneContentModel/CloneContentModelPresenter.js +8 -6
- package/presentation/cloneContentModel/CloneContentModelPresenter.js.map +1 -1
- package/presentation/contentEntries/list/ContentEntriesDataSource.d.ts +5 -0
- package/presentation/contentEntries/list/ContentEntriesDataSource.js +11 -2
- package/presentation/contentEntries/list/ContentEntriesDataSource.js.map +1 -1
- package/presentation/contentEntries/list/ContentEntriesPresenter.test.js +72 -4
- package/presentation/contentEntries/list/ContentEntriesPresenter.test.js.map +1 -1
- package/presentation/newContentModel/NewContentModelPresenter.d.ts +1 -0
- package/presentation/newContentModel/NewContentModelPresenter.js +8 -6
- package/presentation/newContentModel/NewContentModelPresenter.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-headless-cms",
|
|
3
|
-
"version": "6.5.0-beta.
|
|
3
|
+
"version": "6.5.0-beta.1",
|
|
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.
|
|
32
|
-
"@webiny/app": "6.5.0-beta.
|
|
33
|
-
"@webiny/app-aco": "6.5.0-beta.
|
|
34
|
-
"@webiny/app-admin": "6.5.0-beta.
|
|
35
|
-
"@webiny/app-graphql-playground": "6.5.0-beta.
|
|
36
|
-
"@webiny/app-headless-cms-common": "6.5.0-beta.
|
|
37
|
-
"@webiny/cms-sdk": "6.5.0-beta.
|
|
31
|
+
"@webiny/admin-ui": "6.5.0-beta.1",
|
|
32
|
+
"@webiny/app": "6.5.0-beta.1",
|
|
33
|
+
"@webiny/app-aco": "6.5.0-beta.1",
|
|
34
|
+
"@webiny/app-admin": "6.5.0-beta.1",
|
|
35
|
+
"@webiny/app-graphql-playground": "6.5.0-beta.1",
|
|
36
|
+
"@webiny/app-headless-cms-common": "6.5.0-beta.1",
|
|
37
|
+
"@webiny/cms-sdk": "6.5.0-beta.1",
|
|
38
38
|
"@webiny/di": "1.0.2",
|
|
39
|
-
"@webiny/feature": "6.5.0-beta.
|
|
40
|
-
"@webiny/form": "6.5.0-beta.
|
|
41
|
-
"@webiny/frontend-settings": "6.5.0-beta.
|
|
42
|
-
"@webiny/icons": "6.5.0-beta.
|
|
43
|
-
"@webiny/lexical-editor": "6.5.0-beta.
|
|
44
|
-
"@webiny/lexical-nodes": "6.5.0-beta.
|
|
45
|
-
"@webiny/plugins": "6.5.0-beta.
|
|
46
|
-
"@webiny/react-composition": "6.5.0-beta.
|
|
47
|
-
"@webiny/react-properties": "6.5.0-beta.
|
|
48
|
-
"@webiny/utils": "6.5.0-beta.
|
|
49
|
-
"@webiny/validation": "6.5.0-beta.
|
|
39
|
+
"@webiny/feature": "6.5.0-beta.1",
|
|
40
|
+
"@webiny/form": "6.5.0-beta.1",
|
|
41
|
+
"@webiny/frontend-settings": "6.5.0-beta.1",
|
|
42
|
+
"@webiny/icons": "6.5.0-beta.1",
|
|
43
|
+
"@webiny/lexical-editor": "6.5.0-beta.1",
|
|
44
|
+
"@webiny/lexical-nodes": "6.5.0-beta.1",
|
|
45
|
+
"@webiny/plugins": "6.5.0-beta.1",
|
|
46
|
+
"@webiny/react-composition": "6.5.0-beta.1",
|
|
47
|
+
"@webiny/react-properties": "6.5.0-beta.1",
|
|
48
|
+
"@webiny/utils": "6.5.0-beta.1",
|
|
49
|
+
"@webiny/validation": "6.5.0-beta.1",
|
|
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.
|
|
66
|
+
"@webiny/build-tools": "6.5.0-beta.1",
|
|
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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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":";;;;;;;AAQA,MAAMA,0BAA0B;AAOhC,MAAMC;IAKF,YACYC,gBAA4C,EAC5CC,sBAAwD,EACxDC,kBAAgD,EAChDC,WAAuC,EACvCC,WAAkC,CAC5C;aALUJ,gBAAgB,GAAhBA;aACAC,sBAAsB,GAAtBA;aACAC,kBAAkB,GAAlBA;aACAC,WAAW,GAAXA;aACAC,WAAW,GAAXA;aATJ,OAAO,GAAG;aACV,MAAM,GAAG;QAUb,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS;QAC1BC,mBAOE,IAAI,EAAE;YACJ,kBAAkB;YAClB,wBAAwB;YACxB,oBAAoB;YACpB,aAAa;YACb,aAAa;YACb,IAAIC;QACR;IACJ;IAEA,IAAI,KAAyC;QACzC,OAAO;YACH,SAAS,IAAI,CAAC,OAAO;YACrB,QAAQ,IAAI,CAAC,MAAM;YACnB,QAAQ,IAAI,CAAC,YAAY;YACzB,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ;YACjC,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE;QACtB;IACJ;IAEA,IAAY,eAAe;QACvB,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,GAAG,CAACC,CAAAA,QAAU;gBAC7C,OAAOA,MAAM,IAAI;gBACjB,OAAOA,MAAM,IAAI;YACrB;IACJ;IAEA,MAAM,OAAsB;QACxB,IAAI;YACA,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO;QAC7C,SAAU;YACNC,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;gBACf,MAAMC,SAAS,IAAI,CAAC,WAAW,CAAC,QAAQ;gBACxC,IAAIA,OAAO,MAAM,GAAG,GAChB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;oBAAE,OAAOA,MAAM,CAAC,EAAE,CAAC,IAAI;gBAAC;YAElD;QACJ;IACJ;IAEA,MAAM,OAAiC;QACnC,MAAMC,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM;QACnC,IAAI,CAACA,MACD,OAAO;QAGXF,YAAY;YACR,IAAI,CAAC,MAAM,GAAG;QAClB;QAEA,IAAI;YACA,MAAMG,OAAiBC,MAAM,OAAO,CAACF,KAAK,IAAI,IAAIA,KAAK,IAAI,GAAG,EAAE;YAChE,IAAIG,gBAAgBH,KAAK,aAAa;YAEtC,IAAIA,KAAK,WAAW,EAAE;gBAClBC,KAAK,IAAI,CAACb;gBACVe,gBAAgB,GAAGH,KAAK,eAAe,CAAC,MAAM,CAAC;YACnD;YAEA,MAAMI,QAAQ,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;gBAChD,MAAMJ,KAAK,IAAI;gBACf,iBAAiBA,KAAK,eAAe;gBACrCG;gBACA,OAAOH,KAAK,KAAK;gBACjB,MAAMA,KAAK,IAAI;gBACf,aAAaA,KAAK,WAAW;gBAC7B,eAAeA,KAAK,aAAa;gBACjCC;YACJ;YAEA,OAAOG;QACX,EAAE,OAAM;YACJ,OAAO;QACX,SAAU;YACNN,YAAY;gBACR,IAAI,CAAC,MAAM,GAAG;YAClB;QACJ;IACJ;IAEA,QAAc;QACV,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS;QAC1B,MAAMC,SAAS,IAAI,CAAC,WAAW,CAAC,QAAQ;QACxC,IAAIA,OAAO,MAAM,GAAG,GAChB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YAAE,OAAOA,MAAM,CAAC,EAAE,CAAC,IAAI;QAAC;IAElD;IAEQ,YAAwB;QAC5B,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAChC,QAAQM,CAAAA,SAAW;oBACf,MAAMA,OAAO,IAAI,GAAG,KAAK,CAAC,QAAQ,QAAQ,CAAC;oBAC3C,iBAAiBA,OACZ,IAAI,GACJ,KAAK,CAAC,qBACN,QAAQ,CAAC;oBACd,aAAaA,OAAO,OAAO,GAAG,KAAK,CAAC,sBAAsB,YAAY,CAAC;oBACvE,eAAeA,OAAO,IAAI,GAAG,KAAK,CAAC;oBACnC,OAAOA,OACF,IAAI,GACJ,KAAK,CAAC,uBACN,QAAQ,CAAC,sBAKT,OAAO,CAAC,IAAM,IAAI,CAAC,YAAY;oBACpC,MAAMA,OAAO,IAAI,GAAG,KAAK,CAAC,QAAQ,QAAQ,CAAC;oBAC3C,aAAaA,OAAO,IAAI,GAAG,KAAK,CAAC,eAAe,QAAQ,CAAC;oBACzD,eAAeA,OACV,OAAO,GACP,KAAK,CAAC,oCACN,YAAY,CAAC;gBACtB;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;oBACXA,OAAO,GAAG,CAAC;oBACXA,OAAO,GAAG,CAAC;iBACd;QACL;IACJ;AACJ;AAEO,MAAMC,oDAA2BC,yBAAAA,oBAAgC,CAAC;IACrE,gBAAgBnB;IAChB,cAAc;QACVoB;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
|