@webiny/app-headless-cms 6.5.0-beta.1 → 6.5.0-beta.11
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/ContentEntriesModule.js +14 -2
- package/ContentEntriesModule.js.map +1 -1
- package/admin/components/ContentEntries/BulkActions/ActionDelete.d.ts +2 -2
- package/admin/components/ContentEntries/BulkActions/ActionDelete.js.map +1 -1
- package/admin/components/ContentEntries/BulkActions/ActionMove.d.ts +2 -2
- package/admin/components/ContentEntries/BulkActions/ActionMove.js.map +1 -1
- package/admin/components/ContentEntries/BulkActions/ActionPublish.d.ts +2 -2
- package/admin/components/ContentEntries/BulkActions/ActionPublish.js.map +1 -1
- package/admin/components/ContentEntries/BulkActions/ActionUnpublish.d.ts +2 -2
- package/admin/components/ContentEntries/BulkActions/ActionUnpublish.js.map +1 -1
- package/admin/components/ContentEntries/Filters/RefFieldRenderer.d.ts +2 -0
- package/admin/components/ContentEntries/Filters/RefFieldRenderer.js +84 -0
- package/admin/components/ContentEntries/Filters/RefFieldRenderer.js.map +1 -0
- package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.d.ts +2 -0
- package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.js +34 -0
- package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.js.map +1 -0
- package/admin/components/ContentEntries/Table/Actions/index.d.ts +1 -0
- package/admin/components/ContentEntries/Table/Actions/index.js +1 -0
- package/admin/components/ContentModelEditor/ContentModelEditor.js +1 -1
- package/admin/components/ContentModelEditor/ContentModelEditor.js.map +1 -1
- package/admin/components/Dialogs/DuplicateEntryConfirmDialog.d.ts +2 -0
- package/admin/components/Dialogs/DuplicateEntryConfirmDialog.js +22 -0
- package/admin/components/Dialogs/DuplicateEntryConfirmDialog.js.map +1 -0
- package/admin/components/FieldEditor/EditFieldDialog.d.ts +2 -2
- package/admin/components/FieldEditor/Field.js +4 -4
- package/admin/components/FieldEditor/Field.js.map +1 -1
- package/features/contentEntry/CmsEntryError.d.ts +10 -0
- package/features/contentEntry/CmsEntryError.js +11 -0
- package/features/contentEntry/CmsEntryError.js.map +1 -0
- package/features/contentEntry/createEntry/CreateEntryGateway.d.ts +0 -1
- package/features/contentEntry/createEntry/CreateEntryGateway.js +3 -10
- package/features/contentEntry/createEntry/CreateEntryGateway.js.map +1 -1
- package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.d.ts +3 -1
- package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.js +8 -3
- package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.js.map +1 -1
- package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.d.ts +14 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.js +43 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.js.map +1 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.d.ts +15 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.js +34 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.js.map +1 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.d.ts +11 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.js +18 -0
- package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.js.map +1 -0
- package/features/contentEntry/duplicateEntry/abstractions.d.ts +26 -0
- package/features/contentEntry/duplicateEntry/abstractions.js +7 -0
- package/features/contentEntry/duplicateEntry/abstractions.js.map +1 -0
- package/features/contentEntry/duplicateEntry/feature.d.ts +3 -0
- package/features/contentEntry/duplicateEntry/feature.js +21 -0
- package/features/contentEntry/duplicateEntry/feature.js.map +1 -0
- package/features/contentEntry/entryValueGateways.test.d.ts +1 -0
- package/features/contentEntry/entryValueGateways.test.js +106 -0
- package/features/contentEntry/entryValueGateways.test.js.map +1 -0
- package/features/contentEntry/feature.js +2 -0
- package/features/contentEntry/feature.js.map +1 -1
- package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.d.ts +0 -1
- package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.js +3 -10
- package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.js.map +1 -1
- package/features/contentEntry/updateEntry/UpdateEntryGateway.d.ts +0 -1
- package/features/contentEntry/updateEntry/UpdateEntryGateway.js +3 -10
- package/features/contentEntry/updateEntry/UpdateEntryGateway.js.map +1 -1
- package/features/contentEntry/valueTransformers/EntryDataPreparer.d.ts +9 -0
- package/features/contentEntry/valueTransformers/EntryDataPreparer.js +8 -0
- package/features/contentEntry/valueTransformers/EntryDataPreparer.js.map +1 -1
- package/features/contentEntry/valueTransformers/EntryDataPreparer.test.d.ts +1 -0
- package/features/contentEntry/valueTransformers/EntryDataPreparer.test.js +113 -0
- package/features/contentEntry/valueTransformers/EntryDataPreparer.test.js.map +1 -0
- package/features/contentEntry/valueTransformers/entryValueFixtures.d.ts +146 -0
- package/features/contentEntry/valueTransformers/entryValueFixtures.js +171 -0
- package/features/contentEntry/valueTransformers/entryValueFixtures.js.map +1 -0
- package/features/formModel/CmsFormModelBuilder.d.ts +9 -1
- package/features/formModel/CmsFormModelBuilder.js +26 -15
- package/features/formModel/CmsFormModelBuilder.js.map +1 -1
- package/features/formModel/CmsFormModelBuilder.test.d.ts +1 -0
- package/features/formModel/CmsFormModelBuilder.test.js +252 -0
- package/features/formModel/CmsFormModelBuilder.test.js.map +1 -0
- package/features/formModel/CmsLayoutMapper.d.ts +8 -1
- package/features/formModel/CmsLayoutMapper.js +23 -1
- package/features/formModel/CmsLayoutMapper.js.map +1 -1
- package/features/formModel/mappers/DynamicZoneFieldMapper.js +4 -0
- package/features/formModel/mappers/DynamicZoneFieldMapper.js.map +1 -1
- package/features/formModel/mappers/ObjectFieldMapper.js +11 -6
- package/features/formModel/mappers/ObjectFieldMapper.js.map +1 -1
- package/features/model/exportModels/ExportModelsGateway.d.ts +1 -1
- package/features/model/exportModels/ExportModelsGateway.js.map +1 -1
- package/features/model/exportModels/ExportModelsUseCase.js +7 -1
- package/features/model/exportModels/ExportModelsUseCase.js.map +1 -1
- package/features/model/exportModels/abstractions.d.ts +8 -2
- package/features/model/exportModels/abstractions.js.map +1 -1
- package/package.json +26 -26
- package/presentation/contentEntries/form/ContentEntryFormPresenter.js +34 -29
- package/presentation/contentEntries/form/ContentEntryFormPresenter.js.map +1 -1
- package/presentation/contentEntries/form/ContentEntryFormPresenter.test.d.ts +1 -0
- package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js +210 -0
- package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js.map +1 -0
- package/presentation/contentEntries/form/toFormErrors.d.ts +7 -0
- package/presentation/contentEntries/form/toFormErrors.js +49 -0
- package/presentation/contentEntries/form/toFormErrors.js.map +1 -0
- package/presentation/contentEntries/form/toFormErrors.test.d.ts +1 -0
- package/presentation/contentEntries/form/toFormErrors.test.js +175 -0
- package/presentation/contentEntries/form/toFormErrors.test.js.map +1 -0
- package/presentation/contentEntries/list/ContentEntriesPresenter.d.ts +6 -2
- package/presentation/contentEntries/list/ContentEntriesPresenter.js +27 -2
- package/presentation/contentEntries/list/ContentEntriesPresenter.js.map +1 -1
- package/presentation/contentEntries/list/ContentEntriesPresenter.test.js +58 -1
- package/presentation/contentEntries/list/ContentEntriesPresenter.test.js.map +1 -1
- package/presentation/contentEntries/list/abstractions.d.ts +12 -0
- package/presentation/contentEntries/list/abstractions.js.map +1 -1
- package/presentation/contentEntries/preview/LivePreviewPresenter.d.ts +12 -1
- package/presentation/contentEntries/preview/LivePreviewPresenter.js +48 -5
- package/presentation/contentEntries/preview/LivePreviewPresenter.js.map +1 -1
- package/presentation/contentEntries/preview/LivePreviewPresenter.test.d.ts +1 -0
- package/presentation/contentEntries/preview/LivePreviewPresenter.test.js +81 -0
- package/presentation/contentEntries/preview/LivePreviewPresenter.test.js.map +1 -0
- package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js +1 -1
- package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js.map +1 -1
- package/presentation/contentEntries/preview/PreviewDecorator.js +25 -6
- package/presentation/contentEntries/preview/PreviewDecorator.js.map +1 -1
- package/presentation/contentEntries/preview/PreviewDomainStatus.d.ts +10 -0
- package/presentation/contentEntries/preview/PreviewDomainStatus.js +19 -0
- package/presentation/contentEntries/preview/PreviewDomainStatus.js.map +1 -0
- package/presentation/contentEntries/preview/PreviewPane.d.ts +10 -1
- package/presentation/contentEntries/preview/PreviewPane.js +81 -45
- package/presentation/contentEntries/preview/PreviewPane.js.map +1 -1
- package/presentation/contentEntries/preview/abstractions.d.ts +8 -0
- package/presentation/contentEntries/preview/abstractions.js.map +1 -1
- package/presentation/contentEntries/preview/resolvePreviewUrl.d.ts +21 -0
- package/presentation/contentEntries/preview/resolvePreviewUrl.js +50 -1
- package/presentation/contentEntries/preview/resolvePreviewUrl.js.map +1 -1
- package/presentation/contentEntries/preview/resolvePreviewUrl.test.d.ts +1 -0
- package/presentation/contentEntries/preview/resolvePreviewUrl.test.js +127 -0
- package/presentation/contentEntries/preview/resolvePreviewUrl.test.js.map +1 -0
- package/presentation/contentEntries/singleEntry/SingleEntryPresenter.js +9 -4
- package/presentation/contentEntries/singleEntry/SingleEntryPresenter.js.map +1 -1
- package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.d.ts +1 -0
- package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js +122 -0
- package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js.map +1 -0
- package/presentation/contentEntries/trashBin/CmsTrashBin.d.ts +2 -2
- package/presentation/contentEntries/views/CmsAdvancedSearch.d.ts +2 -2
- package/presentation/contentEntries/views/ContentEntriesListLayout.d.ts +2 -2
- package/presentation/contentEntries/views/ContentEntryFormView.d.ts +2 -2
- package/presentation/contentEntries/views/OlderRevisionAlert.d.ts +2 -2
- package/presentation/contentEntries/views/RevisionDrawer.d.ts +2 -2
- package/presentation/contentEntries/views/RevisionsList.d.ts +2 -2
- package/presentation/contentEntries/views/SingleEntryLayout.d.ts +2 -2
- package/presentation/contentEntries/views/Table/Table.d.ts +2 -2
- package/presentation/contentEntries/views/actions/CreateNewRevisionButton.d.ts +2 -2
- package/presentation/contentEntries/views/actions/DeleteEntryMenuItem.d.ts +2 -2
- package/presentation/contentEntries/views/actions/PublishOnlyButton.d.ts +2 -2
- package/presentation/contentEntries/views/actions/RevisionSelector.d.ts +2 -2
- package/presentation/contentEntries/views/actions/SaveAndPublishButton.d.ts +2 -2
- package/presentation/contentEntries/views/actions/SaveContentButton.d.ts +2 -2
- package/presentation/contentEntries/views/actions/ShowRevisionListMenuItem.d.ts +2 -2
- package/presentation/contentEntries/views/layout/ContentEntryForm.d.ts +12 -12
- package/presentation/contentModels/ContentModelsPresenter.d.ts +5 -5
- package/presentation/contentModels/ContentModelsPresenter.js +1 -1
- package/presentation/contentModels/ContentModelsPresenter.js.map +1 -1
- package/presentation/contentModels/abstractions.d.ts +7 -2
- package/presentation/contentModels/abstractions.js.map +1 -1
- package/presentation/contentModels/components/CloneContentModelDialog.d.ts +2 -2
- package/presentation/contentModels/components/ContentModels.d.ts +2 -2
- package/presentation/contentModels/components/ContentModelsDataList.d.ts +2 -2
- package/presentation/contentModels/components/ContentModelsDataList.js +6 -5
- package/presentation/contentModels/components/ContentModelsDataList.js.map +1 -1
- package/presentation/contentModels/components/NewContentModelDialog.d.ts +2 -2
- package/presentation/contentModels/components/fullDelete/dialog/Content.js +2 -2
- package/presentation/contentModels/components/fullDelete/dialog/Content.js.map +1 -1
- package/presentation/contentModels/components/fullDelete/types.js.map +1 -1
- package/presentation/fieldRenderers/ref/autocomplete/BaseAutocompletePresenter.d.ts +1 -0
- package/presentation/fieldRenderers/ref/autocomplete/BaseAutocompletePresenter.js +8 -2
- package/presentation/fieldRenderers/ref/autocomplete/BaseAutocompletePresenter.js.map +1 -1
- package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.d.ts +1 -0
- package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js +185 -0
- package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js.map +1 -0
- package/presentation/fieldRenderers/ref/autocomplete/multi/RefMultiAutocompletePresenter.js +1 -1
- package/presentation/fieldRenderers/ref/autocomplete/multi/RefMultiAutocompletePresenter.js.map +1 -1
- package/presentation/fieldRenderers/ref/autocomplete/single/RefSingleAutocompletePresenter.js +1 -1
- package/presentation/fieldRenderers/ref/autocomplete/single/RefSingleAutocompletePresenter.js.map +1 -1
- package/presentation/fieldRenderers/ref/components/RefFieldOptions.d.ts +2 -2
- package/presentation/fieldRenderers/ref/components/RefFieldOptions.js +3 -2
- package/presentation/fieldRenderers/ref/components/RefFieldOptions.js.map +1 -1
- package/presentation/importContentModels/ImportContentModelsDialog.d.ts +2 -2
- package/presentation/importContentModels/ImportContentModelsPresenter.js +1 -1
- package/presentation/importContentModels/ImportContentModelsPresenter.js.map +1 -1
- package/presentation/importContentModels/components/DataList.d.ts +2 -2
- package/presentation/importContentModels/components/FileUpload.d.ts +2 -2
- package/presentation/importContentModels/components/FileUpload.js +1 -1
- package/presentation/importContentModels/components/FileUpload.js.map +1 -1
- package/presentation/importContentModels/components/Model/DataListModelItem.js +3 -3
- package/presentation/importContentModels/components/Model/DataListModelItem.js.map +1 -1
- package/presentation/importContentModels/components/Model/DataListModelItemInfo.js +2 -2
- package/presentation/importContentModels/components/Model/DataListModelItemInfo.js.map +1 -1
- package/presentation/importContentModels/components/Model/DataListModels.d.ts +2 -2
- package/presentation/menus/ContentGroupsMenuItems.d.ts +2 -2
- package/presentation/modelGroup/ModelGroupPresenter.js +1 -2
- package/presentation/modelGroup/ModelGroupPresenter.js.map +1 -1
- package/presentation/modelGroup/components/ContentModelGroups.d.ts +2 -2
- package/presentation/modelGroup/components/ContentModelGroupsDataList.d.ts +6 -2
- package/presentation/modelGroup/components/ContentModelGroupsForm.d.ts +8 -2
- package/utils/normalizeIcon.d.ts +4 -0
- package/utils/normalizeIcon.js +9 -6
- package/utils/normalizeIcon.js.map +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { buildDisplayUrl, buildEditorUrl, getPatternRefFieldIds, getRefValues, resolveSlugPattern, withRefValues } from "./resolvePreviewUrl.js";
|
|
3
|
+
const fields = [
|
|
4
|
+
{
|
|
5
|
+
fieldId: "slug",
|
|
6
|
+
type: "text"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
fieldId: "location",
|
|
10
|
+
type: "ref"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
fieldId: "tags",
|
|
14
|
+
type: "ref"
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
const resolvePreviewUrl_test_location = {
|
|
18
|
+
id: "loc1#0001",
|
|
19
|
+
modelId: "location"
|
|
20
|
+
};
|
|
21
|
+
describe("resolvePreviewUrl", ()=>{
|
|
22
|
+
it("should resolve plain values and fall back to `new` for missing ones", ()=>{
|
|
23
|
+
expect(resolveSlugPattern("/articles/{values.slug}", {
|
|
24
|
+
values: {
|
|
25
|
+
slug: "hello"
|
|
26
|
+
}
|
|
27
|
+
})).toBe("/articles/hello");
|
|
28
|
+
expect(resolveSlugPattern("/articles/{values.slug}", {
|
|
29
|
+
values: {}
|
|
30
|
+
})).toBe("/articles/new");
|
|
31
|
+
});
|
|
32
|
+
it("should build the iframe url from the static prefix only", ()=>{
|
|
33
|
+
expect(buildEditorUrl("https://site.com/", "/articles/{values.slug}")).toBe("https://site.com/articles/preview");
|
|
34
|
+
expect(buildEditorUrl("https://site.com", "/{values.location.slug}/{values.slug}")).toBe("https://site.com/preview");
|
|
35
|
+
});
|
|
36
|
+
it("should find ref fields the pattern reads through", ()=>{
|
|
37
|
+
expect(getPatternRefFieldIds("/{values.location.slug}/{values.slug}/{values.tags}", fields)).toEqual([
|
|
38
|
+
"location"
|
|
39
|
+
]);
|
|
40
|
+
expect(getPatternRefFieldIds("/articles/{values.slug}", fields)).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
it("should collect ref values from single and multiple-value fields", ()=>{
|
|
43
|
+
const tag = {
|
|
44
|
+
id: "tag1#0001",
|
|
45
|
+
modelId: "tag"
|
|
46
|
+
};
|
|
47
|
+
expect(getRefValues({
|
|
48
|
+
location: resolvePreviewUrl_test_location,
|
|
49
|
+
tags: [
|
|
50
|
+
tag,
|
|
51
|
+
null
|
|
52
|
+
],
|
|
53
|
+
slug: "x"
|
|
54
|
+
}, [
|
|
55
|
+
"location",
|
|
56
|
+
"tags"
|
|
57
|
+
])).toEqual([
|
|
58
|
+
resolvePreviewUrl_test_location,
|
|
59
|
+
tag
|
|
60
|
+
]);
|
|
61
|
+
expect(getRefValues({
|
|
62
|
+
location: null
|
|
63
|
+
}, [
|
|
64
|
+
"location"
|
|
65
|
+
])).toEqual([]);
|
|
66
|
+
});
|
|
67
|
+
it("should resolve a ref field value once the referenced entry is loaded", ()=>{
|
|
68
|
+
const entry = {
|
|
69
|
+
id: "page1#0001",
|
|
70
|
+
values: {
|
|
71
|
+
slug: "climbing",
|
|
72
|
+
location: resolvePreviewUrl_test_location
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const pattern = "/{values.location.slug}/{values.slug}";
|
|
76
|
+
const notLoaded = withRefValues(entry, [
|
|
77
|
+
"location"
|
|
78
|
+
], {});
|
|
79
|
+
expect(buildDisplayUrl("https://site.com", pattern, notLoaded)).toBe("https://site.com/new/climbing");
|
|
80
|
+
const loaded = withRefValues(entry, [
|
|
81
|
+
"location"
|
|
82
|
+
], {
|
|
83
|
+
[resolvePreviewUrl_test_location.id]: {
|
|
84
|
+
slug: "baker",
|
|
85
|
+
id: "should-not-win"
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
expect(buildDisplayUrl("https://site.com", pattern, loaded)).toBe("https://site.com/baker/climbing");
|
|
89
|
+
expect(loaded.values.location.id).toBe(resolvePreviewUrl_test_location.id);
|
|
90
|
+
});
|
|
91
|
+
it("should support indexing into multiple-value ref fields", ()=>{
|
|
92
|
+
const tag = {
|
|
93
|
+
id: "tag1#0001",
|
|
94
|
+
modelId: "tag"
|
|
95
|
+
};
|
|
96
|
+
const entry = {
|
|
97
|
+
values: {
|
|
98
|
+
tags: [
|
|
99
|
+
tag
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const resolved = withRefValues(entry, [
|
|
104
|
+
"tags"
|
|
105
|
+
], {
|
|
106
|
+
[tag.id]: {
|
|
107
|
+
slug: "news"
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
expect(resolveSlugPattern("/{values.tags.0.slug}", resolved)).toBe("/news");
|
|
111
|
+
});
|
|
112
|
+
it("should leave the entry untouched when there are no ref fields to fill in", ()=>{
|
|
113
|
+
const entry = {
|
|
114
|
+
values: {
|
|
115
|
+
slug: "x",
|
|
116
|
+
location: resolvePreviewUrl_test_location
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
expect(withRefValues(entry, [], {
|
|
120
|
+
[resolvePreviewUrl_test_location.id]: {
|
|
121
|
+
slug: "baker"
|
|
122
|
+
}
|
|
123
|
+
})).toBe(entry);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
//# sourceMappingURL=resolvePreviewUrl.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/contentEntries/preview/resolvePreviewUrl.test.js","sources":["../../../../src/presentation/contentEntries/preview/resolvePreviewUrl.test.ts"],"sourcesContent":["import { describe, it, expect } from \"vitest\";\nimport {\n buildDisplayUrl,\n buildEditorUrl,\n getPatternRefFieldIds,\n getRefValues,\n resolveSlugPattern,\n withRefValues\n} from \"./resolvePreviewUrl.js\";\n\nconst fields = [\n { fieldId: \"slug\", type: \"text\" },\n { fieldId: \"location\", type: \"ref\" },\n { fieldId: \"tags\", type: \"ref\" }\n];\n\nconst location = { id: \"loc1#0001\", modelId: \"location\" };\n\ndescribe(\"resolvePreviewUrl\", () => {\n it(\"should resolve plain values and fall back to `new` for missing ones\", () => {\n expect(resolveSlugPattern(\"/articles/{values.slug}\", { values: { slug: \"hello\" } })).toBe(\n \"/articles/hello\"\n );\n expect(resolveSlugPattern(\"/articles/{values.slug}\", { values: {} })).toBe(\"/articles/new\");\n });\n\n it(\"should build the iframe url from the static prefix only\", () => {\n expect(buildEditorUrl(\"https://site.com/\", \"/articles/{values.slug}\")).toBe(\n \"https://site.com/articles/preview\"\n );\n expect(buildEditorUrl(\"https://site.com\", \"/{values.location.slug}/{values.slug}\")).toBe(\n \"https://site.com/preview\"\n );\n });\n\n it(\"should find ref fields the pattern reads through\", () => {\n expect(\n getPatternRefFieldIds(\"/{values.location.slug}/{values.slug}/{values.tags}\", fields)\n ).toEqual([\"location\"]);\n expect(getPatternRefFieldIds(\"/articles/{values.slug}\", fields)).toEqual([]);\n });\n\n it(\"should collect ref values from single and multiple-value fields\", () => {\n const tag = { id: \"tag1#0001\", modelId: \"tag\" };\n expect(\n getRefValues({ location, tags: [tag, null], slug: \"x\" }, [\"location\", \"tags\"])\n ).toEqual([location, tag]);\n expect(getRefValues({ location: null }, [\"location\"])).toEqual([]);\n });\n\n it(\"should resolve a ref field value once the referenced entry is loaded\", () => {\n const entry = { id: \"page1#0001\", values: { slug: \"climbing\", location } };\n const pattern = \"/{values.location.slug}/{values.slug}\";\n\n const notLoaded = withRefValues(entry, [\"location\"], {});\n expect(buildDisplayUrl(\"https://site.com\", pattern, notLoaded)).toBe(\n \"https://site.com/new/climbing\"\n );\n\n const loaded = withRefValues(entry, [\"location\"], {\n [location.id]: { slug: \"baker\", id: \"should-not-win\" }\n });\n expect(buildDisplayUrl(\"https://site.com\", pattern, loaded)).toBe(\n \"https://site.com/baker/climbing\"\n );\n expect((loaded.values as any).location.id).toBe(location.id);\n });\n\n it(\"should support indexing into multiple-value ref fields\", () => {\n const tag = { id: \"tag1#0001\", modelId: \"tag\" };\n const entry = { values: { tags: [tag] } };\n const resolved = withRefValues(entry, [\"tags\"], { [tag.id]: { slug: \"news\" } });\n expect(resolveSlugPattern(\"/{values.tags.0.slug}\", resolved)).toBe(\"/news\");\n });\n\n it(\"should leave the entry untouched when there are no ref fields to fill in\", () => {\n const entry = { values: { slug: \"x\", location } };\n expect(withRefValues(entry, [], { [location.id]: { slug: \"baker\" } })).toBe(entry);\n });\n});\n"],"names":["fields","location","describe","it","expect","resolveSlugPattern","buildEditorUrl","getPatternRefFieldIds","tag","getRefValues","entry","pattern","notLoaded","withRefValues","buildDisplayUrl","loaded","resolved"],"mappings":";;AAUA,MAAMA,SAAS;IACX;QAAE,SAAS;QAAQ,MAAM;IAAO;IAChC;QAAE,SAAS;QAAY,MAAM;IAAM;IACnC;QAAE,SAAS;QAAQ,MAAM;IAAM;CAClC;AAED,MAAMC,kCAAW;IAAE,IAAI;IAAa,SAAS;AAAW;AAExDC,SAAS,qBAAqB;IAC1BC,GAAG,uEAAuE;QACtEC,OAAOC,mBAAmB,2BAA2B;YAAE,QAAQ;gBAAE,MAAM;YAAQ;QAAE,IAAI,IAAI,CACrF;QAEJD,OAAOC,mBAAmB,2BAA2B;YAAE,QAAQ,CAAC;QAAE,IAAI,IAAI,CAAC;IAC/E;IAEAF,GAAG,2DAA2D;QAC1DC,OAAOE,eAAe,qBAAqB,4BAA4B,IAAI,CACvE;QAEJF,OAAOE,eAAe,oBAAoB,0CAA0C,IAAI,CACpF;IAER;IAEAH,GAAG,oDAAoD;QACnDC,OACIG,sBAAsB,uDAAuDP,SAC/E,OAAO,CAAC;YAAC;SAAW;QACtBI,OAAOG,sBAAsB,2BAA2BP,SAAS,OAAO,CAAC,EAAE;IAC/E;IAEAG,GAAG,mEAAmE;QAClE,MAAMK,MAAM;YAAE,IAAI;YAAa,SAAS;QAAM;QAC9CJ,OACIK,aAAa;YAAER,UAAAA;YAAU,MAAM;gBAACO;gBAAK;aAAK;YAAE,MAAM;QAAI,GAAG;YAAC;YAAY;SAAO,GAC/E,OAAO,CAAC;YAACP;YAAUO;SAAI;QACzBJ,OAAOK,aAAa;YAAE,UAAU;QAAK,GAAG;YAAC;SAAW,GAAG,OAAO,CAAC,EAAE;IACrE;IAEAN,GAAG,wEAAwE;QACvE,MAAMO,QAAQ;YAAE,IAAI;YAAc,QAAQ;gBAAE,MAAM;gBAAYT,UAAAA;YAAS;QAAE;QACzE,MAAMU,UAAU;QAEhB,MAAMC,YAAYC,cAAcH,OAAO;YAAC;SAAW,EAAE,CAAC;QACtDN,OAAOU,gBAAgB,oBAAoBH,SAASC,YAAY,IAAI,CAChE;QAGJ,MAAMG,SAASF,cAAcH,OAAO;YAAC;SAAW,EAAE;YAC9C,CAACT,gCAAS,EAAE,CAAC,EAAE;gBAAE,MAAM;gBAAS,IAAI;YAAiB;QACzD;QACAG,OAAOU,gBAAgB,oBAAoBH,SAASI,SAAS,IAAI,CAC7D;QAEJX,OAAQW,OAAO,MAAM,CAAS,QAAQ,CAAC,EAAE,EAAE,IAAI,CAACd,gCAAS,EAAE;IAC/D;IAEAE,GAAG,0DAA0D;QACzD,MAAMK,MAAM;YAAE,IAAI;YAAa,SAAS;QAAM;QAC9C,MAAME,QAAQ;YAAE,QAAQ;gBAAE,MAAM;oBAACF;iBAAI;YAAC;QAAE;QACxC,MAAMQ,WAAWH,cAAcH,OAAO;YAAC;SAAO,EAAE;YAAE,CAACF,IAAI,EAAE,CAAC,EAAE;gBAAE,MAAM;YAAO;QAAE;QAC7EJ,OAAOC,mBAAmB,yBAAyBW,WAAW,IAAI,CAAC;IACvE;IAEAb,GAAG,4EAA4E;QAC3E,MAAMO,QAAQ;YAAE,QAAQ;gBAAE,MAAM;gBAAKT,UAAAA;YAAS;QAAE;QAChDG,OAAOS,cAAcH,OAAO,EAAE,EAAE;YAAE,CAACT,gCAAS,EAAE,CAAC,EAAE;gBAAE,MAAM;YAAQ;QAAE,IAAI,IAAI,CAACS;IAChF;AACJ"}
|
|
@@ -4,6 +4,7 @@ import { GetSingletonEntryUseCase, UpdateSingletonEntryUseCase } from "../../../
|
|
|
4
4
|
import { CmsFormModelBuilder } from "../../../features/formModel/abstractions.js";
|
|
5
5
|
import { CmsModelContext } from "../../../features/contentEntry/abstractions.js";
|
|
6
6
|
import { SingleEntryPresenter } from "./abstractions.js";
|
|
7
|
+
import { toFormErrors } from "../form/toFormErrors.js";
|
|
7
8
|
class SingleEntryPresenterImpl {
|
|
8
9
|
constructor(formModelFactory, cmsFormModelBuilder, modelAccessor, getSingletonEntryUseCase, updateSingletonEntryUseCase){
|
|
9
10
|
this.formModelFactory = formModelFactory;
|
|
@@ -37,7 +38,9 @@ class SingleEntryPresenterImpl {
|
|
|
37
38
|
}
|
|
38
39
|
async save() {
|
|
39
40
|
if (!this.form) return false;
|
|
40
|
-
const
|
|
41
|
+
const form = this.form;
|
|
42
|
+
const model = this.model;
|
|
43
|
+
const data = await form.submit();
|
|
41
44
|
if (!data) return false;
|
|
42
45
|
this.loading = "Saving...";
|
|
43
46
|
try {
|
|
@@ -48,12 +51,14 @@ class SingleEntryPresenterImpl {
|
|
|
48
51
|
}
|
|
49
52
|
});
|
|
50
53
|
runInAction(()=>{
|
|
54
|
+
if (this.form !== form) return;
|
|
51
55
|
this.entry = entry;
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
form.setData(entry.values);
|
|
57
|
+
form.reset();
|
|
54
58
|
});
|
|
55
59
|
return true;
|
|
56
|
-
} catch
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (this.form === form) form.setErrors(toFormErrors(error, model));
|
|
57
62
|
return false;
|
|
58
63
|
} finally{
|
|
59
64
|
runInAction(()=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/contentEntries/singleEntry/SingleEntryPresenter.js","sources":["../../../../src/presentation/contentEntries/singleEntry/SingleEntryPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { GetSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { UpdateSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n SingleEntryPresenter as Abstraction,\n type ISingleEntryPresenter,\n type ISingleEntryViewModel\n} from \"./abstractions.js\";\n\nclass SingleEntryPresenterImpl implements ISingleEntryPresenter {\n private entry: CmsContentEntry | null = null;\n private form: IFormModel | null = null;\n private loading: string | null = null;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private cmsFormModelBuilder: CmsFormModelBuilder.Interface,\n private modelAccessor: CmsModelContext.Interface,\n private getSingletonEntryUseCase: GetSingletonEntryUseCase.Interface,\n private updateSingletonEntryUseCase: UpdateSingletonEntryUseCase.Interface\n ) {\n makeAutoObservable<\n SingleEntryPresenterImpl,\n | \"formModelFactory\"\n | \"cmsFormModelBuilder\"\n | \"modelAccessor\"\n | \"getSingletonEntryUseCase\"\n | \"updateSingletonEntryUseCase\"\n >(this, {\n formModelFactory: false,\n cmsFormModelBuilder: false,\n modelAccessor: false,\n getSingletonEntryUseCase: false,\n updateSingletonEntryUseCase: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): ISingleEntryViewModel {\n return {\n loading: this.loading,\n entry: this.entry,\n form: this.form?.vm ?? null,\n canSave: this.form !== null,\n isDirty: this.form?.isDirty ?? false\n };\n }\n\n async save(): Promise<boolean> {\n if (!this.form) {\n return false;\n }\n\n const data = await
|
|
1
|
+
{"version":3,"file":"presentation/contentEntries/singleEntry/SingleEntryPresenter.js","sources":["../../../../src/presentation/contentEntries/singleEntry/SingleEntryPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, runInAction } from \"mobx\";\nimport type { IFormModel } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { GetSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { UpdateSingletonEntryUseCase } from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n SingleEntryPresenter as Abstraction,\n type ISingleEntryPresenter,\n type ISingleEntryViewModel\n} from \"./abstractions.js\";\nimport { toFormErrors } from \"~/presentation/contentEntries/form/toFormErrors.js\";\n\nclass SingleEntryPresenterImpl implements ISingleEntryPresenter {\n private entry: CmsContentEntry | null = null;\n private form: IFormModel | null = null;\n private loading: string | null = null;\n\n constructor(\n private formModelFactory: FormModelFactory.Interface,\n private cmsFormModelBuilder: CmsFormModelBuilder.Interface,\n private modelAccessor: CmsModelContext.Interface,\n private getSingletonEntryUseCase: GetSingletonEntryUseCase.Interface,\n private updateSingletonEntryUseCase: UpdateSingletonEntryUseCase.Interface\n ) {\n makeAutoObservable<\n SingleEntryPresenterImpl,\n | \"formModelFactory\"\n | \"cmsFormModelBuilder\"\n | \"modelAccessor\"\n | \"getSingletonEntryUseCase\"\n | \"updateSingletonEntryUseCase\"\n >(this, {\n formModelFactory: false,\n cmsFormModelBuilder: false,\n modelAccessor: false,\n getSingletonEntryUseCase: false,\n updateSingletonEntryUseCase: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): ISingleEntryViewModel {\n return {\n loading: this.loading,\n entry: this.entry,\n form: this.form?.vm ?? null,\n canSave: this.form !== null,\n isDirty: this.form?.isDirty ?? false\n };\n }\n\n async save(): Promise<boolean> {\n if (!this.form) {\n return false;\n }\n\n // The form can be disposed or rebuilt while saving; only the form being saved gets the result.\n const form = this.form;\n const model = this.model;\n\n const data = await form.submit();\n if (!data) {\n return false;\n }\n\n this.loading = \"Saving...\";\n\n try {\n const entry = await this.updateSingletonEntryUseCase.execute({\n model: this.model,\n data: {\n values: data\n }\n });\n\n runInAction(() => {\n if (this.form !== form) {\n return;\n }\n this.entry = entry;\n form.setData(entry.values);\n form.reset();\n });\n\n return true;\n } catch (error) {\n if (this.form === form) {\n form.setErrors(toFormErrors(error, model));\n }\n return false;\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n async init(): Promise<void> {\n this.loading = \"Loading...\";\n\n try {\n const entry = await this.getSingletonEntryUseCase.execute({\n model: this.model\n });\n\n runInAction(() => {\n this.entry = entry;\n const formConfig = this.cmsFormModelBuilder.build(this.model);\n this.form = this.formModelFactory.create(formConfig);\n this.form.setData(entry.values);\n this.form.reset();\n });\n } finally {\n runInAction(() => {\n this.loading = null;\n });\n }\n }\n\n dispose(): void {\n this.form = null;\n this.entry = null;\n }\n}\n\nexport const SingleEntryPresenter = Abstraction.createImplementation({\n implementation: SingleEntryPresenterImpl,\n dependencies: [\n FormModelFactory,\n CmsFormModelBuilder,\n CmsModelContext,\n GetSingletonEntryUseCase,\n UpdateSingletonEntryUseCase\n ]\n});\n"],"names":["SingleEntryPresenterImpl","formModelFactory","cmsFormModelBuilder","modelAccessor","getSingletonEntryUseCase","updateSingletonEntryUseCase","makeAutoObservable","computed","form","model","data","entry","runInAction","error","toFormErrors","formConfig","SingleEntryPresenter","Abstraction","FormModelFactory","CmsFormModelBuilder","CmsModelContext","GetSingletonEntryUseCase","UpdateSingletonEntryUseCase"],"mappings":";;;;;;;AAeA,MAAMA;IAKF,YACYC,gBAA4C,EAC5CC,mBAAkD,EAClDC,aAAwC,EACxCC,wBAA4D,EAC5DC,2BAAkE,CAC5E;aALUJ,gBAAgB,GAAhBA;aACAC,mBAAmB,GAAnBA;aACAC,aAAa,GAAbA;aACAC,wBAAwB,GAAxBA;aACAC,2BAA2B,GAA3BA;aATJ,KAAK,GAA2B;aAChC,IAAI,GAAsB;aAC1B,OAAO,GAAkB;QAS7BC,mBAOE,IAAI,EAAE;YACJ,kBAAkB;YAClB,qBAAqB;YACrB,eAAe;YACf,0BAA0B;YAC1B,6BAA6B;YAC7B,IAAIC;QACR;IACJ;IAEA,IAAY,QAAQ;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ;IACtC;IAEA,IAAI,KAA4B;QAC5B,OAAO;YACH,SAAS,IAAI,CAAC,OAAO;YACrB,OAAO,IAAI,CAAC,KAAK;YACjB,MAAM,IAAI,CAAC,IAAI,EAAE,MAAM;YACvB,SAAS,AAAc,SAAd,IAAI,CAAC,IAAI;YAClB,SAAS,IAAI,CAAC,IAAI,EAAE,WAAW;QACnC;IACJ;IAEA,MAAM,OAAyB;QAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,EACV,OAAO;QAIX,MAAMC,OAAO,IAAI,CAAC,IAAI;QACtB,MAAMC,QAAQ,IAAI,CAAC,KAAK;QAExB,MAAMC,OAAO,MAAMF,KAAK,MAAM;QAC9B,IAAI,CAACE,MACD,OAAO;QAGX,IAAI,CAAC,OAAO,GAAG;QAEf,IAAI;YACA,MAAMC,QAAQ,MAAM,IAAI,CAAC,2BAA2B,CAAC,OAAO,CAAC;gBACzD,OAAO,IAAI,CAAC,KAAK;gBACjB,MAAM;oBACF,QAAQD;gBACZ;YACJ;YAEAE,YAAY;gBACR,IAAI,IAAI,CAAC,IAAI,KAAKJ,MACd;gBAEJ,IAAI,CAAC,KAAK,GAAGG;gBACbH,KAAK,OAAO,CAACG,MAAM,MAAM;gBACzBH,KAAK,KAAK;YACd;YAEA,OAAO;QACX,EAAE,OAAOK,OAAO;YACZ,IAAI,IAAI,CAAC,IAAI,KAAKL,MACdA,KAAK,SAAS,CAACM,aAAaD,OAAOJ;YAEvC,OAAO;QACX,SAAU;YACNG,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;YACnB;QACJ;IACJ;IAEA,MAAM,OAAsB;QACxB,IAAI,CAAC,OAAO,GAAG;QAEf,IAAI;YACA,MAAMD,QAAQ,MAAM,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC;gBACtD,OAAO,IAAI,CAAC,KAAK;YACrB;YAEAC,YAAY;gBACR,IAAI,CAAC,KAAK,GAAGD;gBACb,MAAMI,aAAa,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;gBAC5D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACA;gBACzC,IAAI,CAAC,IAAI,CAAC,OAAO,CAACJ,MAAM,MAAM;gBAC9B,IAAI,CAAC,IAAI,CAAC,KAAK;YACnB;QACJ,SAAU;YACNC,YAAY;gBACR,IAAI,CAAC,OAAO,GAAG;YACnB;QACJ;IACJ;IAEA,UAAgB;QACZ,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,KAAK,GAAG;IACjB;AACJ;AAEO,MAAMI,4CAAuBC,qBAAAA,oBAAgC,CAAC;IACjE,gBAAgBjB;IAChB,cAAc;QACVkB;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { Container } from "@webiny/di";
|
|
3
|
+
import { FormModelFactory } from "@webiny/app-admin/features/formModel/abstractions.js";
|
|
4
|
+
import { CmsFormModelBuilder } from "../../../features/formModel/abstractions.js";
|
|
5
|
+
import { CmsModelContext } from "../../../features/contentEntry/abstractions.js";
|
|
6
|
+
import { GetSingletonEntryUseCase, UpdateSingletonEntryUseCase } from "../../../features/contentEntry/singletonEntry/abstractions.js";
|
|
7
|
+
import { SingleEntryPresenter } from "./abstractions.js";
|
|
8
|
+
import { SingleEntryPresenter as external_SingleEntryPresenter_js_SingleEntryPresenter } from "./SingleEntryPresenter.js";
|
|
9
|
+
const createFakeForm = ()=>({
|
|
10
|
+
vm: {},
|
|
11
|
+
isDirty: false,
|
|
12
|
+
submit: vi.fn(async ()=>({
|
|
13
|
+
title: "Draft"
|
|
14
|
+
})),
|
|
15
|
+
setData: vi.fn(),
|
|
16
|
+
reset: vi.fn(),
|
|
17
|
+
setErrors: vi.fn()
|
|
18
|
+
});
|
|
19
|
+
const deferred = ()=>{
|
|
20
|
+
let resolve;
|
|
21
|
+
let reject;
|
|
22
|
+
const promise = new Promise((res, rej)=>{
|
|
23
|
+
resolve = res;
|
|
24
|
+
reject = rej;
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
promise,
|
|
28
|
+
resolve,
|
|
29
|
+
reject
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
const setup = ()=>{
|
|
33
|
+
const forms = [];
|
|
34
|
+
let pendingUpdate = deferred();
|
|
35
|
+
const container = new Container();
|
|
36
|
+
container.registerInstance(FormModelFactory, {
|
|
37
|
+
create: ()=>{
|
|
38
|
+
const form = createFakeForm();
|
|
39
|
+
forms.push(form);
|
|
40
|
+
return form;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
container.registerInstance(CmsFormModelBuilder, {
|
|
44
|
+
build: ()=>({})
|
|
45
|
+
});
|
|
46
|
+
container.registerInstance(CmsModelContext, {
|
|
47
|
+
getModel: ()=>({
|
|
48
|
+
modelId: "settings",
|
|
49
|
+
fields: []
|
|
50
|
+
})
|
|
51
|
+
});
|
|
52
|
+
container.registerInstance(GetSingletonEntryUseCase, {
|
|
53
|
+
execute: async ()=>({
|
|
54
|
+
id: "settings#0001",
|
|
55
|
+
values: {
|
|
56
|
+
title: "Saved"
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
container.registerInstance(UpdateSingletonEntryUseCase, {
|
|
61
|
+
execute: ()=>pendingUpdate.promise
|
|
62
|
+
});
|
|
63
|
+
container.register(external_SingleEntryPresenter_js_SingleEntryPresenter);
|
|
64
|
+
return {
|
|
65
|
+
presenter: container.resolve(SingleEntryPresenter),
|
|
66
|
+
forms,
|
|
67
|
+
nextUpdate: ()=>{
|
|
68
|
+
pendingUpdate = deferred();
|
|
69
|
+
return pendingUpdate;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
describe("SingleEntryPresenter.save", ()=>{
|
|
74
|
+
it("puts a rejected save's errors on the form", async ()=>{
|
|
75
|
+
const { presenter, forms, nextUpdate } = setup();
|
|
76
|
+
await presenter.init();
|
|
77
|
+
const update = nextUpdate();
|
|
78
|
+
const saving = presenter.save();
|
|
79
|
+
update.reject(new Error("Value must be unique."));
|
|
80
|
+
await expect(saving).resolves.toBe(false);
|
|
81
|
+
expect(forms[0].setErrors).toHaveBeenCalledTimes(1);
|
|
82
|
+
});
|
|
83
|
+
it("returns false instead of throwing when the form was disposed mid-save", async ()=>{
|
|
84
|
+
const { presenter, nextUpdate } = setup();
|
|
85
|
+
await presenter.init();
|
|
86
|
+
const update = nextUpdate();
|
|
87
|
+
const saving = presenter.save();
|
|
88
|
+
presenter.dispose();
|
|
89
|
+
update.reject(new Error("Value must be unique."));
|
|
90
|
+
await expect(saving).resolves.toBe(false);
|
|
91
|
+
});
|
|
92
|
+
it("doesn't put a rejected save's errors on a form built after it started", async ()=>{
|
|
93
|
+
const { presenter, forms, nextUpdate } = setup();
|
|
94
|
+
await presenter.init();
|
|
95
|
+
const update = nextUpdate();
|
|
96
|
+
const saving = presenter.save();
|
|
97
|
+
await presenter.init();
|
|
98
|
+
update.reject(new Error("Value must be unique."));
|
|
99
|
+
await expect(saving).resolves.toBe(false);
|
|
100
|
+
expect(forms).toHaveLength(2);
|
|
101
|
+
expect(forms[0].setErrors).not.toHaveBeenCalled();
|
|
102
|
+
expect(forms[1].setErrors).not.toHaveBeenCalled();
|
|
103
|
+
});
|
|
104
|
+
it("doesn't overwrite a form built after a successful save started", async ()=>{
|
|
105
|
+
const { presenter, forms, nextUpdate } = setup();
|
|
106
|
+
await presenter.init();
|
|
107
|
+
const update = nextUpdate();
|
|
108
|
+
const saving = presenter.save();
|
|
109
|
+
await presenter.init();
|
|
110
|
+
const setDataCallsBefore = forms[1].setData.mock.calls.length;
|
|
111
|
+
update.resolve({
|
|
112
|
+
id: "settings#0002",
|
|
113
|
+
values: {
|
|
114
|
+
title: "From the old save"
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
await expect(saving).resolves.toBe(true);
|
|
118
|
+
expect(forms[1].setData).toHaveBeenCalledTimes(setDataCallsBefore);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=SingleEntryPresenter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js","sources":["../../../../src/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.ts"],"sourcesContent":["import { describe, it, expect, vi } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport { CmsFormModelBuilder } from \"~/features/formModel/abstractions.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport {\n GetSingletonEntryUseCase,\n UpdateSingletonEntryUseCase\n} from \"~/features/contentEntry/singletonEntry/abstractions.js\";\nimport { SingleEntryPresenter as Abstraction } from \"./abstractions.js\";\nimport { SingleEntryPresenter } from \"./SingleEntryPresenter.js\";\n\nconst createFakeForm = () => ({\n vm: {},\n isDirty: false,\n submit: vi.fn(async () => ({ title: \"Draft\" })),\n setData: vi.fn(),\n reset: vi.fn(),\n setErrors: vi.fn()\n});\n\n/** A promise the test settles by hand, so it can act while a save is still in flight. */\nconst deferred = <T>() => {\n let resolve!: (value: T) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst setup = () => {\n const forms: ReturnType<typeof createFakeForm>[] = [];\n let pendingUpdate = deferred<any>();\n\n const container = new Container();\n container.registerInstance(FormModelFactory, {\n create: () => {\n const form = createFakeForm();\n forms.push(form);\n return form;\n }\n } as unknown as FormModelFactory.Interface);\n container.registerInstance(CmsFormModelBuilder, {\n build: () => ({})\n } as unknown as CmsFormModelBuilder.Interface);\n container.registerInstance(CmsModelContext, {\n getModel: () => ({ modelId: \"settings\", fields: [] })\n } as unknown as CmsModelContext.Interface);\n container.registerInstance(GetSingletonEntryUseCase, {\n execute: async () => ({ id: \"settings#0001\", values: { title: \"Saved\" } })\n } as unknown as GetSingletonEntryUseCase.Interface);\n container.registerInstance(UpdateSingletonEntryUseCase, {\n execute: () => pendingUpdate.promise\n } as unknown as UpdateSingletonEntryUseCase.Interface);\n container.register(SingleEntryPresenter);\n\n return {\n presenter: container.resolve(Abstraction),\n forms,\n nextUpdate: () => {\n pendingUpdate = deferred<any>();\n return pendingUpdate;\n }\n };\n};\n\ndescribe(\"SingleEntryPresenter.save\", () => {\n it(\"puts a rejected save's errors on the form\", async () => {\n const { presenter, forms, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n update.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n expect(forms[0].setErrors).toHaveBeenCalledTimes(1);\n });\n\n it(\"returns false instead of throwing when the form was disposed mid-save\", async () => {\n const { presenter, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n presenter.dispose();\n update.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n });\n\n it(\"doesn't put a rejected save's errors on a form built after it started\", async () => {\n const { presenter, forms, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n await presenter.init();\n update.reject(new Error(\"Value must be unique.\"));\n\n await expect(saving).resolves.toBe(false);\n expect(forms).toHaveLength(2);\n expect(forms[0].setErrors).not.toHaveBeenCalled();\n expect(forms[1].setErrors).not.toHaveBeenCalled();\n });\n\n it(\"doesn't overwrite a form built after a successful save started\", async () => {\n const { presenter, forms, nextUpdate } = setup();\n await presenter.init();\n const update = nextUpdate();\n\n const saving = presenter.save();\n await presenter.init();\n const setDataCallsBefore = forms[1].setData.mock.calls.length;\n update.resolve({ id: \"settings#0002\", values: { title: \"From the old save\" } });\n\n await expect(saving).resolves.toBe(true);\n expect(forms[1].setData).toHaveBeenCalledTimes(setDataCallsBefore);\n });\n});\n"],"names":["createFakeForm","vi","deferred","resolve","reject","promise","Promise","res","rej","setup","forms","pendingUpdate","container","Container","FormModelFactory","form","CmsFormModelBuilder","CmsModelContext","GetSingletonEntryUseCase","UpdateSingletonEntryUseCase","SingleEntryPresenter","Abstraction","describe","it","presenter","nextUpdate","update","saving","Error","expect","setDataCallsBefore"],"mappings":";;;;;;;;AAYA,MAAMA,iBAAiB,IAAO;QAC1B,IAAI,CAAC;QACL,SAAS;QACT,QAAQC,GAAG,EAAE,CAAC,UAAa;gBAAE,OAAO;YAAQ;QAC5C,SAASA,GAAG,EAAE;QACd,OAAOA,GAAG,EAAE;QACZ,WAAWA,GAAG,EAAE;IACpB;AAGA,MAAMC,WAAW;IACb,IAAIC;IACJ,IAAIC;IACJ,MAAMC,UAAU,IAAIC,QAAW,CAACC,KAAKC;QACjCL,UAAUI;QACVH,SAASI;IACb;IACA,OAAO;QAAEH;QAASF;QAASC;IAAO;AACtC;AAEA,MAAMK,QAAQ;IACV,MAAMC,QAA6C,EAAE;IACrD,IAAIC,gBAAgBT;IAEpB,MAAMU,YAAY,IAAIC;IACtBD,UAAU,gBAAgB,CAACE,kBAAkB;QACzC,QAAQ;YACJ,MAAMC,OAAOf;YACbU,MAAM,IAAI,CAACK;YACX,OAAOA;QACX;IACJ;IACAH,UAAU,gBAAgB,CAACI,qBAAqB;QAC5C,OAAO,IAAO,EAAC;IACnB;IACAJ,UAAU,gBAAgB,CAACK,iBAAiB;QACxC,UAAU,IAAO;gBAAE,SAAS;gBAAY,QAAQ,EAAE;YAAC;IACvD;IACAL,UAAU,gBAAgB,CAACM,0BAA0B;QACjD,SAAS,UAAa;gBAAE,IAAI;gBAAiB,QAAQ;oBAAE,OAAO;gBAAQ;YAAE;IAC5E;IACAN,UAAU,gBAAgB,CAACO,6BAA6B;QACpD,SAAS,IAAMR,cAAc,OAAO;IACxC;IACAC,UAAU,QAAQ,CAACQ;IAEnB,OAAO;QACH,WAAWR,UAAU,OAAO,CAACS;QAC7BX;QACA,YAAY;YACRC,gBAAgBT;YAChB,OAAOS;QACX;IACJ;AACJ;AAEAW,SAAS,6BAA6B;IAClCC,GAAG,6CAA6C;QAC5C,MAAM,EAAEC,SAAS,EAAEd,KAAK,EAAEe,UAAU,EAAE,GAAGhB;QACzC,MAAMe,UAAU,IAAI;QACpB,MAAME,SAASD;QAEf,MAAME,SAASH,UAAU,IAAI;QAC7BE,OAAO,MAAM,CAAC,IAAIE,MAAM;QAExB,MAAMC,OAAOF,QAAQ,QAAQ,CAAC,IAAI,CAAC;QACnCE,OAAOnB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,qBAAqB,CAAC;IACrD;IAEAa,GAAG,yEAAyE;QACxE,MAAM,EAAEC,SAAS,EAAEC,UAAU,EAAE,GAAGhB;QAClC,MAAMe,UAAU,IAAI;QACpB,MAAME,SAASD;QAEf,MAAME,SAASH,UAAU,IAAI;QAC7BA,UAAU,OAAO;QACjBE,OAAO,MAAM,CAAC,IAAIE,MAAM;QAExB,MAAMC,OAAOF,QAAQ,QAAQ,CAAC,IAAI,CAAC;IACvC;IAEAJ,GAAG,yEAAyE;QACxE,MAAM,EAAEC,SAAS,EAAEd,KAAK,EAAEe,UAAU,EAAE,GAAGhB;QACzC,MAAMe,UAAU,IAAI;QACpB,MAAME,SAASD;QAEf,MAAME,SAASH,UAAU,IAAI;QAC7B,MAAMA,UAAU,IAAI;QACpBE,OAAO,MAAM,CAAC,IAAIE,MAAM;QAExB,MAAMC,OAAOF,QAAQ,QAAQ,CAAC,IAAI,CAAC;QACnCE,OAAOnB,OAAO,YAAY,CAAC;QAC3BmB,OAAOnB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,gBAAgB;QAC/CmB,OAAOnB,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,gBAAgB;IACnD;IAEAa,GAAG,kEAAkE;QACjE,MAAM,EAAEC,SAAS,EAAEd,KAAK,EAAEe,UAAU,EAAE,GAAGhB;QACzC,MAAMe,UAAU,IAAI;QACpB,MAAME,SAASD;QAEf,MAAME,SAASH,UAAU,IAAI;QAC7B,MAAMA,UAAU,IAAI;QACpB,MAAMM,qBAAqBpB,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;QAC7DgB,OAAO,OAAO,CAAC;YAAE,IAAI;YAAiB,QAAQ;gBAAE,OAAO;YAAoB;QAAE;QAE7E,MAAMG,OAAOF,QAAQ,QAAQ,CAAC,IAAI,CAAC;QACnCE,OAAOnB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,CAACoB;IACnD;AACJ"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const CmsAdvancedSearch: (() => React.JSX.Element) & {
|
|
3
|
-
|
|
2
|
+
export declare const CmsAdvancedSearch: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const ContentEntriesListLayout: (() => React.JSX.Element) & {
|
|
3
|
-
|
|
2
|
+
export declare const ContentEntriesListLayout: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const ContentEntryFormView: (() => React.JSX.Element) & {
|
|
3
|
-
|
|
2
|
+
export declare const ContentEntryFormView: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const OlderRevisionAlert: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const OlderRevisionAlert: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const RevisionDrawer: (() => React.JSX.Element) & {
|
|
3
|
-
|
|
2
|
+
export declare const RevisionDrawer: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const RevisionsList: (() => React.JSX.Element) & {
|
|
3
|
-
|
|
2
|
+
export declare const RevisionsList: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element;
|
|
4
4
|
};
|
|
@@ -4,7 +4,7 @@ interface SingleEntryLayoutProps {
|
|
|
4
4
|
presenter: ISingleEntryPresenter;
|
|
5
5
|
modelName: string;
|
|
6
6
|
}
|
|
7
|
-
export declare const SingleEntryLayout: (({ presenter, modelName }: SingleEntryLayoutProps) => React.JSX.Element | null) & {
|
|
8
|
-
|
|
7
|
+
export declare const SingleEntryLayout: (({ presenter, modelName }: SingleEntryLayoutProps) => React.JSX.Element | null) & React.NamedExoticComponent<SingleEntryLayoutProps> & {
|
|
8
|
+
readonly type: ({ presenter, modelName }: SingleEntryLayoutProps) => React.JSX.Element | null;
|
|
9
9
|
};
|
|
10
10
|
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const CreateNewRevisionButton: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const CreateNewRevisionButton: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const DeleteEntryMenuItem: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const DeleteEntryMenuItem: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const PublishOnlyButton: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const PublishOnlyButton: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const RevisionSelector: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const RevisionSelector: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const SaveAndPublishButton: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const SaveAndPublishButton: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const SaveContentButton: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const SaveContentButton: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const ShowRevisionListMenuItem: (() => React.JSX.Element) & {
|
|
3
|
-
|
|
2
|
+
export declare const ShowRevisionListMenuItem: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element;
|
|
4
4
|
};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare const ContentEntryForm: (() => React.JSX.Element | null) & {
|
|
3
|
-
|
|
2
|
+
export declare const ContentEntryForm: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
3
|
+
readonly type: () => React.JSX.Element | null;
|
|
4
4
|
} & {
|
|
5
|
-
original: (() => React.JSX.Element | null) & {
|
|
6
|
-
|
|
5
|
+
original: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
6
|
+
readonly type: () => React.JSX.Element | null;
|
|
7
7
|
};
|
|
8
8
|
originalName: string;
|
|
9
9
|
displayName: string;
|
|
10
10
|
} & {
|
|
11
|
-
original: (() => React.JSX.Element | null) & {
|
|
12
|
-
|
|
11
|
+
original: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
12
|
+
readonly type: () => React.JSX.Element | null;
|
|
13
13
|
} & {
|
|
14
|
-
original: (() => React.JSX.Element | null) & {
|
|
15
|
-
|
|
14
|
+
original: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
15
|
+
readonly type: () => React.JSX.Element | null;
|
|
16
16
|
};
|
|
17
17
|
originalName: string;
|
|
18
18
|
displayName: string;
|
|
@@ -20,11 +20,11 @@ export declare const ContentEntryForm: (() => React.JSX.Element | null) & {
|
|
|
20
20
|
originalName: string;
|
|
21
21
|
displayName: string;
|
|
22
22
|
} & {
|
|
23
|
-
createDecorator: (decorator: import("@webiny/react-composition").ComponentDecorator<(() => React.JSX.Element | null) & {
|
|
24
|
-
|
|
23
|
+
createDecorator: (decorator: import("@webiny/react-composition").ComponentDecorator<(() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
24
|
+
readonly type: () => React.JSX.Element | null;
|
|
25
25
|
} & {
|
|
26
|
-
original: (() => React.JSX.Element | null) & {
|
|
27
|
-
|
|
26
|
+
original: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
|
|
27
|
+
readonly type: () => React.JSX.Element | null;
|
|
28
28
|
};
|
|
29
29
|
originalName: string;
|
|
30
30
|
displayName: string;
|
|
@@ -5,8 +5,8 @@ import { DeleteModelUseCase } from "../../features/model/deleteModel/abstraction
|
|
|
5
5
|
import { CancelDeleteModelUseCase } from "../../features/model/cancelDeleteModel/abstractions.js";
|
|
6
6
|
import { ExportModelsUseCase } from "../../features/model/exportModels/abstractions.js";
|
|
7
7
|
import { ModelsCache } from "../../features/model/abstractions.js";
|
|
8
|
-
import {
|
|
9
|
-
declare class ContentModelsPresenterImpl implements
|
|
8
|
+
import { ContentModelsPresenter as Abstraction } from "./abstractions.js";
|
|
9
|
+
declare class ContentModelsPresenterImpl implements Abstraction.Interface {
|
|
10
10
|
private listPresenter;
|
|
11
11
|
private listModelsUseCase;
|
|
12
12
|
private deleteModelUseCase;
|
|
@@ -15,14 +15,14 @@ declare class ContentModelsPresenterImpl implements IContentModelsPresenter {
|
|
|
15
15
|
private cache;
|
|
16
16
|
private loading;
|
|
17
17
|
constructor(listPresenter: ListPresenter.Interface<CmsModel>, listModelsUseCase: ListModelsUseCase.Interface, deleteModelUseCase: DeleteModelUseCase.Interface, cancelDeleteModelUseCase: CancelDeleteModelUseCase.Interface, exportModelsUseCase: ExportModelsUseCase.Interface, cache: ModelsCache.Interface);
|
|
18
|
-
get vm():
|
|
18
|
+
get vm(): Abstraction.ViewModel;
|
|
19
19
|
get list(): ListPresenter.Interface<CmsModel>;
|
|
20
20
|
init(): void;
|
|
21
21
|
deleteModel(modelId: string, confirmation: string): Promise<import("~/features/model/deleteModel/abstractions.js").DeleteModelResult>;
|
|
22
22
|
cancelDelete(modelId: string): Promise<void>;
|
|
23
|
-
exportModels(modelIds?: string[]): Promise<
|
|
23
|
+
exportModels(modelIds?: string[]): Promise<Abstraction.ExportModelResponse | null>;
|
|
24
24
|
}
|
|
25
25
|
export declare const ContentModelsPresenter: typeof ContentModelsPresenterImpl & {
|
|
26
|
-
__abstraction: import("@webiny/di").Abstraction<IContentModelsPresenter>;
|
|
26
|
+
__abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IContentModelsPresenter>;
|
|
27
27
|
};
|
|
28
28
|
export {};
|
|
@@ -59,7 +59,7 @@ class ContentModelsPresenterImpl {
|
|
|
59
59
|
return this.cancelDeleteModelUseCase.execute(modelId);
|
|
60
60
|
}
|
|
61
61
|
async exportModels(modelIds) {
|
|
62
|
-
return this.exportModelsUseCase.execute(modelIds);
|
|
62
|
+
return await this.exportModelsUseCase.execute(modelIds);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
const ContentModelsPresenter_ContentModelsPresenter = ContentModelsPresenter.createImplementation({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation/contentModels/ContentModelsPresenter.js","sources":["../../../src/presentation/contentModels/ContentModelsPresenter.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport type { CmsModel } from \"~/types.js\";\nimport { ListModelsUseCase } from \"~/features/model/listModels/abstractions.js\";\nimport { DeleteModelUseCase } from \"~/features/model/deleteModel/abstractions.js\";\nimport { CancelDeleteModelUseCase } from \"~/features/model/cancelDeleteModel/abstractions.js\";\nimport { ExportModelsUseCase } from \"~/features/model/exportModels/abstractions.js\";\nimport { ModelsCache } from \"~/features/model/abstractions.js\";\nimport {
|
|
1
|
+
{"version":3,"file":"presentation/contentModels/ContentModelsPresenter.js","sources":["../../../src/presentation/contentModels/ContentModelsPresenter.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport type { CmsModel } from \"~/types.js\";\nimport { ListModelsUseCase } from \"~/features/model/listModels/abstractions.js\";\nimport { DeleteModelUseCase } from \"~/features/model/deleteModel/abstractions.js\";\nimport { CancelDeleteModelUseCase } from \"~/features/model/cancelDeleteModel/abstractions.js\";\nimport { ExportModelsUseCase } from \"~/features/model/exportModels/abstractions.js\";\nimport { ModelsCache } from \"~/features/model/abstractions.js\";\nimport { ContentModelsPresenter as Abstraction } from \"./abstractions.js\";\nimport { ContentModelsDataSource } from \"./ContentModelsDataSource.js\";\n\nclass ContentModelsPresenterImpl implements Abstraction.Interface {\n private loading = true;\n\n constructor(\n private listPresenter: ListPresenter.Interface<CmsModel>,\n private listModelsUseCase: ListModelsUseCase.Interface,\n private deleteModelUseCase: DeleteModelUseCase.Interface,\n private cancelDeleteModelUseCase: CancelDeleteModelUseCase.Interface,\n private exportModelsUseCase: ExportModelsUseCase.Interface,\n private cache: ModelsCache.Interface\n ) {\n makeAutoObservable<\n ContentModelsPresenterImpl,\n | \"listModelsUseCase\"\n | \"deleteModelUseCase\"\n | \"cancelDeleteModelUseCase\"\n | \"exportModelsUseCase\"\n | \"cache\"\n >(this, {\n listModelsUseCase: false,\n deleteModelUseCase: false,\n cancelDeleteModelUseCase: false,\n exportModelsUseCase: false,\n cache: false,\n vm: computed\n });\n }\n\n get vm(): Abstraction.ViewModel {\n const models = this.cache.getItems().filter(model => {\n if (!model.tags || model.tags.length === 0) {\n return true;\n }\n return !model.tags.includes(\"$hidden:true\");\n });\n\n return {\n loading: this.loading,\n models\n };\n }\n\n get list(): ListPresenter.Interface<CmsModel> {\n return this.listPresenter;\n }\n\n init(): void {\n const dataSource = new ContentModelsDataSource(this.listModelsUseCase, this.cache);\n\n this.listPresenter.init({\n dataSource,\n initialSort: { field: \"savedOn\", direction: \"DESC\" },\n limit: 1000\n });\n\n runInAction(() => {\n this.loading = false;\n });\n }\n\n async deleteModel(modelId: string, confirmation: string) {\n return this.deleteModelUseCase.execute(modelId, confirmation);\n }\n\n async cancelDelete(modelId: string) {\n return this.cancelDeleteModelUseCase.execute(modelId);\n }\n\n async exportModels(modelIds?: string[]): Promise<Abstraction.ExportModelResponse | null> {\n return await this.exportModelsUseCase.execute(modelIds);\n }\n}\n\nexport const ContentModelsPresenter = Abstraction.createImplementation({\n implementation: ContentModelsPresenterImpl,\n dependencies: [\n ListPresenter,\n ListModelsUseCase,\n DeleteModelUseCase,\n CancelDeleteModelUseCase,\n ExportModelsUseCase,\n ModelsCache\n ]\n});\n"],"names":["ContentModelsPresenterImpl","listPresenter","listModelsUseCase","deleteModelUseCase","cancelDeleteModelUseCase","exportModelsUseCase","cache","makeAutoObservable","computed","models","model","dataSource","ContentModelsDataSource","runInAction","modelId","confirmation","modelIds","ContentModelsPresenter","Abstraction","ListPresenter","ListModelsUseCase","DeleteModelUseCase","CancelDeleteModelUseCase","ExportModelsUseCase","ModelsCache"],"mappings":";;;;;;;;;AAWA,MAAMA;IAGF,YACYC,aAAgD,EAChDC,iBAA8C,EAC9CC,kBAAgD,EAChDC,wBAA4D,EAC5DC,mBAAkD,EAClDC,KAA4B,CACtC;aANUL,aAAa,GAAbA;aACAC,iBAAiB,GAAjBA;aACAC,kBAAkB,GAAlBA;aACAC,wBAAwB,GAAxBA;aACAC,mBAAmB,GAAnBA;aACAC,KAAK,GAALA;aARJ,OAAO,GAAG;QAUdC,mBAOE,IAAI,EAAE;YACJ,mBAAmB;YACnB,oBAAoB;YACpB,0BAA0B;YAC1B,qBAAqB;YACrB,OAAO;YACP,IAAIC;QACR;IACJ;IAEA,IAAI,KAA4B;QAC5B,MAAMC,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAACC,CAAAA;YACxC,IAAI,CAACA,MAAM,IAAI,IAAIA,AAAsB,MAAtBA,MAAM,IAAI,CAAC,MAAM,EAChC,OAAO;YAEX,OAAO,CAACA,MAAM,IAAI,CAAC,QAAQ,CAAC;QAChC;QAEA,OAAO;YACH,SAAS,IAAI,CAAC,OAAO;YACrBD;QACJ;IACJ;IAEA,IAAI,OAA0C;QAC1C,OAAO,IAAI,CAAC,aAAa;IAC7B;IAEA,OAAa;QACT,MAAME,aAAa,IAAIC,wBAAwB,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAAK;QAEjF,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YACpBD;YACA,aAAa;gBAAE,OAAO;gBAAW,WAAW;YAAO;YACnD,OAAO;QACX;QAEAE,YAAY;YACR,IAAI,CAAC,OAAO,GAAG;QACnB;IACJ;IAEA,MAAM,YAAYC,OAAe,EAAEC,YAAoB,EAAE;QACrD,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAACD,SAASC;IACpD;IAEA,MAAM,aAAaD,OAAe,EAAE;QAChC,OAAO,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAACA;IACjD;IAEA,MAAM,aAAaE,QAAmB,EAAmD;QACrF,OAAO,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAACA;IAClD;AACJ;AAEO,MAAMC,gDAAyBC,uBAAAA,oBAAgC,CAAC;IACnE,gBAAgBlB;IAChB,cAAc;QACVmB;QACAC;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
|