@stackbit/cms-core 1.0.10-develop.1 → 1.0.10-develop.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/consts.d.ts +1 -0
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +2 -1
- package/dist/consts.js.map +1 -1
- package/dist/content-store.d.ts +25 -12
- package/dist/content-store.d.ts.map +1 -1
- package/dist/content-store.js +259 -40
- package/dist/content-store.js.map +1 -1
- package/dist/types/content-store-documents.d.ts +2 -0
- package/dist/types/content-store-documents.d.ts.map +1 -1
- package/dist/types/content-store-types.d.ts +2 -1
- package/dist/types/content-store-types.d.ts.map +1 -1
- package/dist/types/search-filter.d.ts +6 -3
- package/dist/types/search-filter.d.ts.map +1 -1
- package/dist/utils/csi-to-api-docs-converter.d.ts +2 -1
- package/dist/utils/csi-to-api-docs-converter.d.ts.map +1 -1
- package/dist/utils/csi-to-api-docs-converter.js +2 -2
- package/dist/utils/csi-to-api-docs-converter.js.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.d.ts.map +1 -1
- package/dist/utils/csi-to-store-docs-converter.js +3 -1
- package/dist/utils/csi-to-store-docs-converter.js.map +1 -1
- package/dist/utils/document-utils.d.ts +5 -0
- package/dist/utils/document-utils.d.ts.map +1 -0
- package/dist/utils/document-utils.js +46 -0
- package/dist/utils/document-utils.js.map +1 -0
- package/dist/utils/filtered-entities.d.ts +34 -0
- package/dist/utils/filtered-entities.d.ts.map +1 -0
- package/dist/utils/filtered-entities.js +177 -0
- package/dist/utils/filtered-entities.js.map +1 -0
- package/dist/utils/model-utils.d.ts +3 -0
- package/dist/utils/model-utils.d.ts.map +1 -1
- package/dist/utils/model-utils.js +8 -1
- package/dist/utils/model-utils.js.map +1 -1
- package/dist/utils/remove-hidden.d.ts +29 -0
- package/dist/utils/remove-hidden.d.ts.map +1 -0
- package/dist/utils/remove-hidden.js +199 -0
- package/dist/utils/remove-hidden.js.map +1 -0
- package/dist/utils/search-utils.d.ts.map +1 -1
- package/dist/utils/search-utils.js +72 -20
- package/dist/utils/search-utils.js.map +1 -1
- package/dist/utils/site-map.d.ts.map +1 -1
- package/dist/utils/site-map.js.map +1 -1
- package/dist/utils/store-to-csi-docs-converter.d.ts.map +1 -1
- package/dist/utils/store-to-csi-docs-converter.js +1 -0
- package/dist/utils/store-to-csi-docs-converter.js.map +1 -1
- package/dist/utils/tree-views.d.ts +8 -0
- package/dist/utils/tree-views.d.ts.map +1 -1
- package/dist/utils/tree-views.js +32 -1
- package/dist/utils/tree-views.js.map +1 -1
- package/package.json +5 -5
- package/src/consts.ts +2 -0
- package/src/content-store.ts +278 -39
- package/src/types/content-store-documents.ts +2 -0
- package/src/types/content-store-types.ts +3 -1
- package/src/types/search-filter.ts +7 -3
- package/src/utils/csi-to-api-docs-converter.ts +4 -2
- package/src/utils/csi-to-store-docs-converter.ts +3 -2
- package/src/utils/document-utils.ts +39 -0
- package/src/utils/filtered-entities.ts +247 -0
- package/src/utils/model-utils.ts +7 -0
- package/src/utils/search-utils.ts +94 -21
- package/src/utils/site-map.ts +0 -1
- package/src/utils/store-to-csi-docs-converter.ts +1 -0
- package/src/utils/tree-views.ts +43 -0
- package/dist/utils/custom-search-filters.d.ts +0 -12
- package/dist/utils/custom-search-filters.d.ts.map +0 -1
- package/dist/utils/custom-search-filters.js +0 -46
- package/dist/utils/custom-search-filters.js.map +0 -1
|
@@ -52,6 +52,7 @@ function sourceAssetToStoreAsset({
|
|
|
52
52
|
updatedAt: csiAsset.updatedAt,
|
|
53
53
|
updatedBy: csiAsset.updatedBy,
|
|
54
54
|
locale: csiAsset.locale,
|
|
55
|
+
hidden: csiAsset.hidden,
|
|
55
56
|
fields: {
|
|
56
57
|
title: {
|
|
57
58
|
label: 'Title',
|
|
@@ -166,6 +167,7 @@ function mapCSIDocumentToStoreDocument({
|
|
|
166
167
|
createdBy: csiDocument.createdBy,
|
|
167
168
|
updatedAt: csiDocument.updatedAt,
|
|
168
169
|
updatedBy: csiDocument.updatedBy,
|
|
170
|
+
hidden: typeof csiDocument.hidden === 'boolean' ? csiDocument.hidden : model.hidden,
|
|
169
171
|
locale: getDocumentLocale({ csiDocument, model }),
|
|
170
172
|
fields: mapCSIFieldsToStoreFields({
|
|
171
173
|
csiDocumentFields: csiDocument.fields,
|
|
@@ -825,8 +827,7 @@ function getObjectTitleFromLabelField({
|
|
|
825
827
|
document,
|
|
826
828
|
documentField,
|
|
827
829
|
modelOrObjectField,
|
|
828
|
-
delegate
|
|
829
|
-
locale
|
|
830
|
+
delegate
|
|
830
831
|
}: {
|
|
831
832
|
document: StackbitTypes.DocumentWithSource;
|
|
832
833
|
documentField?: StackbitTypes.DocumentModelField | StackbitTypes.DocumentObjectField;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as StackbitTypes from '@stackbit/types';
|
|
2
|
+
|
|
3
|
+
const getModelsFromFields = (fields: StackbitTypes.DocumentField[], foundModels: Set<string>) => {
|
|
4
|
+
fields.forEach((field) => {
|
|
5
|
+
if (field.type === 'model') {
|
|
6
|
+
if (field.localized) {
|
|
7
|
+
for (const localeObject of Object.values(field.locales)) {
|
|
8
|
+
foundModels.add(localeObject.modelName);
|
|
9
|
+
getModelsFromFields(Object.values(localeObject.fields), foundModels);
|
|
10
|
+
}
|
|
11
|
+
} else {
|
|
12
|
+
foundModels.add(field.modelName);
|
|
13
|
+
getModelsFromFields(Object.values(field.fields), foundModels);
|
|
14
|
+
}
|
|
15
|
+
} else if (field.type === 'object') {
|
|
16
|
+
if (field.localized) {
|
|
17
|
+
for (const localeObject of Object.values(field.locales)) {
|
|
18
|
+
getModelsFromFields(Object.values(localeObject.fields), foundModels);
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
getModelsFromFields(Object.values(field.fields), foundModels);
|
|
22
|
+
}
|
|
23
|
+
} else if (field.type === 'list') {
|
|
24
|
+
if (field.localized) {
|
|
25
|
+
for (const localeObject of Object.values(field.locales)) {
|
|
26
|
+
getModelsFromFields(localeObject.items, foundModels);
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
getModelsFromFields(field.items, foundModels);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export function getAllModelsFromCSIDocument({ document }: { document: StackbitTypes.Document }): string[] {
|
|
36
|
+
const models = new Set<string>([document.modelName]);
|
|
37
|
+
getModelsFromFields(Object.values(document.fields), models);
|
|
38
|
+
return Array.from(models);
|
|
39
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import * as CSITypes from '@stackbit/types';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { ContentStoreTypes } from '../';
|
|
4
|
+
import { STACKBIT_PRESET_MODEL_NAME } from '../consts';
|
|
5
|
+
import { getContentSourceDataByIdOrThrow, getContentSourceId } from '../content-store-utils';
|
|
6
|
+
import { mapCSIAssetsToStoreAssets, mapCSIDocumentsToStoreDocuments } from './csi-to-store-docs-converter';
|
|
7
|
+
import { getAllModelsFromCSIDocument } from './document-utils';
|
|
8
|
+
|
|
9
|
+
export const getFilteredDocumentsForUser = ({
|
|
10
|
+
user,
|
|
11
|
+
documents,
|
|
12
|
+
filterModel,
|
|
13
|
+
filterDocument,
|
|
14
|
+
contentSourceDataById,
|
|
15
|
+
assetSources,
|
|
16
|
+
createConfigDelegate,
|
|
17
|
+
customActionRunStateMap,
|
|
18
|
+
logger
|
|
19
|
+
}: {
|
|
20
|
+
user?: ContentStoreTypes.User;
|
|
21
|
+
filterModel: CSITypes.StackbitConfig['filterModel'];
|
|
22
|
+
filterDocument: CSITypes.StackbitConfig['filterDocument'];
|
|
23
|
+
documents: ContentStoreTypes.Document[];
|
|
24
|
+
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
25
|
+
assetSources: CSITypes.AssetSource[];
|
|
26
|
+
createConfigDelegate: () => CSITypes.ConfigDelegate;
|
|
27
|
+
customActionRunStateMap: ContentStoreTypes.CustomActionRunStateMap;
|
|
28
|
+
logger: CSITypes.Logger;
|
|
29
|
+
}): ContentStoreTypes.Document[] => {
|
|
30
|
+
if (!user || (!filterDocument && !filterModel)) {
|
|
31
|
+
return documents;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const documentsBySourceId = _.groupBy(documents, (object) => getContentSourceId(object.srcType, object.srcProjectId));
|
|
35
|
+
|
|
36
|
+
const transformedCsiDocuments: CSITypes.DocumentWithSource[] = [];
|
|
37
|
+
|
|
38
|
+
const resultDocuments: ContentStoreTypes.Document[] = [];
|
|
39
|
+
|
|
40
|
+
const configDelegate = createConfigDelegate();
|
|
41
|
+
|
|
42
|
+
for (const [contentSourceId, contentSourceDocuments] of Object.entries(documentsBySourceId)) {
|
|
43
|
+
const contentSourceData = getContentSourceDataByIdOrThrow(contentSourceId, contentSourceDataById);
|
|
44
|
+
const filteredModelsMap: Record<string, CSITypes.Model> = {};
|
|
45
|
+
|
|
46
|
+
contentSourceDocuments.forEach((document) => {
|
|
47
|
+
const csiDoc = contentSourceData.csiDocumentMap[document.srcObjectId];
|
|
48
|
+
if (!csiDoc) {
|
|
49
|
+
throw new Error(`Document with id '${document.srcObjectId}' not found in content source '${contentSourceId}'`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getAllModelsFromCSIDocument({ document: csiDoc }).forEach((modelName) => {
|
|
53
|
+
if (!filteredModelsMap[modelName]) {
|
|
54
|
+
const filteredModel = getFilteredModelForUser({
|
|
55
|
+
user,
|
|
56
|
+
name: modelName,
|
|
57
|
+
contentSourceData,
|
|
58
|
+
configDelegate,
|
|
59
|
+
filterModel
|
|
60
|
+
});
|
|
61
|
+
filteredModelsMap[modelName] = filteredModel;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const documentModel = filteredModelsMap[document.srcModelName];
|
|
65
|
+
if (!documentModel) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Can't find model with name '${document.srcModelName}' for object with id '${document.srcObjectId}' in content source '${contentSourceId}'`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
if (documentModel.hidden) {
|
|
71
|
+
// model is hidden - return csiDocument right away as hidden
|
|
72
|
+
resultDocuments.push({
|
|
73
|
+
...document,
|
|
74
|
+
hidden: true
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!filterDocument) {
|
|
80
|
+
// no filter function is defined, but the model is not hidden - just add this document as is
|
|
81
|
+
resultDocuments.push(document);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const csiDocWithSource: CSITypes.DocumentWithSource = {
|
|
86
|
+
..._.cloneDeep(csiDoc),
|
|
87
|
+
srcType: contentSourceData.srcType,
|
|
88
|
+
srcProjectId: contentSourceData.srcProjectId
|
|
89
|
+
};
|
|
90
|
+
const shouldIncludeDoc = filterDocument({
|
|
91
|
+
...configDelegate,
|
|
92
|
+
document: csiDocWithSource,
|
|
93
|
+
userContext: user
|
|
94
|
+
});
|
|
95
|
+
if (typeof shouldIncludeDoc === 'undefined') {
|
|
96
|
+
transformedCsiDocuments.push(csiDocWithSource);
|
|
97
|
+
} else {
|
|
98
|
+
transformedCsiDocuments.push({
|
|
99
|
+
...csiDocWithSource,
|
|
100
|
+
hidden: !shouldIncludeDoc
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (transformedCsiDocuments.length) {
|
|
106
|
+
const csResultDocuments = mapCSIDocumentsToStoreDocuments({
|
|
107
|
+
csiDocuments: transformedCsiDocuments,
|
|
108
|
+
contentSourceInstance: contentSourceData.instance,
|
|
109
|
+
modelMap: filteredModelsMap,
|
|
110
|
+
defaultLocaleCode: contentSourceData.defaultLocaleCode,
|
|
111
|
+
assetSources,
|
|
112
|
+
customActionRunStateMap,
|
|
113
|
+
createConfigDelegate,
|
|
114
|
+
logger
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
resultDocuments.push(...(csResultDocuments ?? []));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return resultDocuments;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const getFilteredAssetsForUser = ({
|
|
125
|
+
user,
|
|
126
|
+
assets,
|
|
127
|
+
filterAsset,
|
|
128
|
+
configDelegate,
|
|
129
|
+
contentSourceDataById
|
|
130
|
+
}: {
|
|
131
|
+
user?: ContentStoreTypes.User;
|
|
132
|
+
assets: ContentStoreTypes.Asset[];
|
|
133
|
+
filterAsset: CSITypes.StackbitConfig['filterAsset'];
|
|
134
|
+
configDelegate: CSITypes.ConfigDelegate;
|
|
135
|
+
contentSourceDataById: Record<string, ContentStoreTypes.ContentSourceData>;
|
|
136
|
+
}): ContentStoreTypes.Asset[] => {
|
|
137
|
+
if (!user || !filterAsset) {
|
|
138
|
+
return assets;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const assetsBySourceId = _.groupBy(assets, (object) => getContentSourceId(object.srcType, object.srcProjectId));
|
|
142
|
+
|
|
143
|
+
const transformedCsiAssets: CSITypes.AssetWithSource[] = [];
|
|
144
|
+
|
|
145
|
+
const resultAssets: ContentStoreTypes.Asset[] = [];
|
|
146
|
+
|
|
147
|
+
for (const [contentSourceId, contentSourceAssets] of Object.entries(assetsBySourceId)) {
|
|
148
|
+
const contentSourceData = getContentSourceDataByIdOrThrow(contentSourceId, contentSourceDataById);
|
|
149
|
+
|
|
150
|
+
contentSourceAssets.forEach((asset) => {
|
|
151
|
+
const csiAsset = contentSourceData.csiAssetMap[asset.srcObjectId];
|
|
152
|
+
if (!csiAsset) {
|
|
153
|
+
throw new Error(`Asset with id '${asset.srcObjectId}' not found in content source '${contentSourceId}'`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const csiAssetWithSource: CSITypes.AssetWithSource = {
|
|
157
|
+
..._.cloneDeep(csiAsset),
|
|
158
|
+
srcType: contentSourceData.srcType,
|
|
159
|
+
srcProjectId: contentSourceData.srcProjectId
|
|
160
|
+
};
|
|
161
|
+
const shouldIncludeAsset = filterAsset({
|
|
162
|
+
...configDelegate,
|
|
163
|
+
asset: csiAssetWithSource,
|
|
164
|
+
userContext: user
|
|
165
|
+
});
|
|
166
|
+
if (typeof shouldIncludeAsset === 'undefined') {
|
|
167
|
+
transformedCsiAssets.push(csiAssetWithSource);
|
|
168
|
+
} else {
|
|
169
|
+
transformedCsiAssets.push({
|
|
170
|
+
...csiAssetWithSource,
|
|
171
|
+
hidden: !shouldIncludeAsset
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (transformedCsiAssets.length) {
|
|
177
|
+
const csResultAssets = mapCSIAssetsToStoreAssets({
|
|
178
|
+
csiAssets: transformedCsiAssets,
|
|
179
|
+
contentSourceInstance: contentSourceData.instance,
|
|
180
|
+
defaultLocaleCode: contentSourceData.defaultLocaleCode
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
resultAssets.push(...csResultAssets);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return resultAssets;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
export const getContentSourceFilteredModelsForUser = ({
|
|
191
|
+
user,
|
|
192
|
+
configDelegate,
|
|
193
|
+
contentSourceData,
|
|
194
|
+
filterModel
|
|
195
|
+
}: {
|
|
196
|
+
user?: ContentStoreTypes.User;
|
|
197
|
+
configDelegate: CSITypes.ConfigDelegate;
|
|
198
|
+
contentSourceData: ContentStoreTypes.ContentSourceData;
|
|
199
|
+
filterModel: CSITypes.StackbitConfig['filterModel'];
|
|
200
|
+
}): CSITypes.Model[] => {
|
|
201
|
+
const filteredModels = contentSourceData.models.map((model) => {
|
|
202
|
+
return getFilteredModelForUser({
|
|
203
|
+
user,
|
|
204
|
+
configDelegate,
|
|
205
|
+
name: model.name,
|
|
206
|
+
contentSourceData,
|
|
207
|
+
filterModel
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
const cleanModels = filteredModels.filter((model) => model.name !== STACKBIT_PRESET_MODEL_NAME);
|
|
211
|
+
return cleanModels;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export const getFilteredModelForUser = ({
|
|
215
|
+
user,
|
|
216
|
+
name,
|
|
217
|
+
configDelegate,
|
|
218
|
+
contentSourceData,
|
|
219
|
+
filterModel
|
|
220
|
+
}: {
|
|
221
|
+
user?: ContentStoreTypes.User;
|
|
222
|
+
name: string;
|
|
223
|
+
configDelegate: CSITypes.ConfigDelegate;
|
|
224
|
+
contentSourceData: ContentStoreTypes.ContentSourceData;
|
|
225
|
+
filterModel: CSITypes.StackbitConfig['filterModel'];
|
|
226
|
+
}): CSITypes.Model => {
|
|
227
|
+
const model = contentSourceData.modelMap[name];
|
|
228
|
+
if (!model) {
|
|
229
|
+
throw new Error(`Model with name ${name} not found in source`);
|
|
230
|
+
}
|
|
231
|
+
if (!user || !filterModel) {
|
|
232
|
+
return model;
|
|
233
|
+
}
|
|
234
|
+
const modelWithSource = {
|
|
235
|
+
..._.cloneDeep(model),
|
|
236
|
+
srcType: contentSourceData.srcType,
|
|
237
|
+
srcProjectId: contentSourceData.srcProjectId
|
|
238
|
+
};
|
|
239
|
+
const shouldIncludeModel = filterModel({ ...configDelegate, model: modelWithSource, userContext: user });
|
|
240
|
+
if (typeof shouldIncludeModel === 'undefined') {
|
|
241
|
+
return model;
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
...model,
|
|
245
|
+
hidden: !shouldIncludeModel
|
|
246
|
+
};
|
|
247
|
+
};
|
package/src/utils/model-utils.ts
CHANGED
|
@@ -176,3 +176,10 @@ export function validateModels<T extends Model>({ models, logger }: { models: T[
|
|
|
176
176
|
|
|
177
177
|
return config.models as T[];
|
|
178
178
|
}
|
|
179
|
+
|
|
180
|
+
export function getModelMap<T extends Model>({ models }: { models: T[] }): Record<string, T> {
|
|
181
|
+
return models.reduce((res, model) => {
|
|
182
|
+
res[model.name] = model;
|
|
183
|
+
return res;
|
|
184
|
+
}, {} as Record<string, T>);
|
|
185
|
+
}
|
|
@@ -4,7 +4,7 @@ import { ScheduledAction } from '@stackbit/types';
|
|
|
4
4
|
import { append } from '@stackbit/utils';
|
|
5
5
|
|
|
6
6
|
import * as ContentStoreTypes from '../types';
|
|
7
|
-
import { ReferenceValueType, SearchFilter, SearchFilterItem } from '../types';
|
|
7
|
+
import { ReferenceValueType, SearchFilter, SearchFilterItem, SearchFilterItemGrouped } from '../types';
|
|
8
8
|
import { getContentSourceId, getDocumentFieldForLocale } from '../content-store-utils';
|
|
9
9
|
import { META_FIELDS, MetaFieldMethod } from './meta-fields-filters';
|
|
10
10
|
|
|
@@ -55,25 +55,13 @@ export const searchDocuments = (data: {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
if (data.filter
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
activeScheduledActionsByDocumentId,
|
|
66
|
-
locale: data.locale ?? data.defaultLocales?.[contentSourceId],
|
|
67
|
-
schema
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
if ('result' in filterFieldResult) {
|
|
72
|
-
return filterFieldResult.result;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const { field, model } = filterFieldResult;
|
|
76
|
-
return isFieldMatchesFilter({ field, filter, document, model, locale: data.locale ?? data.defaultLocales?.[contentSourceId] });
|
|
58
|
+
if (data.filter) {
|
|
59
|
+
const matches = isFilterMatches({
|
|
60
|
+
filter: data.filter,
|
|
61
|
+
document,
|
|
62
|
+
locale: data.locale ?? data.defaultLocales?.[contentSourceId],
|
|
63
|
+
schema,
|
|
64
|
+
activeScheduledActionsByDocumentId
|
|
77
65
|
});
|
|
78
66
|
|
|
79
67
|
if (!matches) {
|
|
@@ -95,8 +83,13 @@ const isDocumentMatchesPattern = (document: ContentStoreTypes.Document, query: s
|
|
|
95
83
|
return true;
|
|
96
84
|
}
|
|
97
85
|
|
|
98
|
-
return
|
|
86
|
+
return areFieldsMatchingPattern(Object.values(document.fields), query, locale);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const areFieldsMatchingPattern = (fields: ContentStoreTypes.DocumentField[], query: string, locale?: string): boolean => {
|
|
90
|
+
return fields.some((field) => {
|
|
99
91
|
let value;
|
|
92
|
+
|
|
100
93
|
switch (field.type) {
|
|
101
94
|
case 'string':
|
|
102
95
|
case 'slug':
|
|
@@ -106,6 +99,27 @@ const isDocumentMatchesPattern = (document: ContentStoreTypes.Document, query: s
|
|
|
106
99
|
case 'html':
|
|
107
100
|
value = getDocumentFieldForLocale(field, locale)?.value;
|
|
108
101
|
break;
|
|
102
|
+
|
|
103
|
+
case 'list': {
|
|
104
|
+
const list = getDocumentFieldForLocale(field, locale);
|
|
105
|
+
const result = list ? areFieldsMatchingPattern(list.items, query, locale) : false;
|
|
106
|
+
if (result) {
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
case 'model':
|
|
113
|
+
case 'object': {
|
|
114
|
+
const object = getDocumentFieldForLocale(field, locale);
|
|
115
|
+
if (object && !object.isUnset) {
|
|
116
|
+
const result = areFieldsMatchingPattern(Object.values(object.fields), query, locale);
|
|
117
|
+
if (result) {
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
109
123
|
}
|
|
110
124
|
|
|
111
125
|
if (value) {
|
|
@@ -116,6 +130,65 @@ const isDocumentMatchesPattern = (document: ContentStoreTypes.Document, query: s
|
|
|
116
130
|
});
|
|
117
131
|
};
|
|
118
132
|
|
|
133
|
+
const isFilterMatches = ({
|
|
134
|
+
filter,
|
|
135
|
+
document,
|
|
136
|
+
locale,
|
|
137
|
+
schema,
|
|
138
|
+
activeScheduledActionsByDocumentId
|
|
139
|
+
}: {
|
|
140
|
+
filter: SearchFilterItemGrouped;
|
|
141
|
+
document: ContentStoreTypes.Document;
|
|
142
|
+
locale?: string;
|
|
143
|
+
schema: SearchSchema;
|
|
144
|
+
activeScheduledActionsByDocumentId: Record<string, ScheduledAction[]>;
|
|
145
|
+
}): boolean => {
|
|
146
|
+
if (_.intersection(Object.keys(filter), ['and', 'or', 'field']).length > 1) {
|
|
147
|
+
throw new Error(`Unsupported filter - 'and', 'or' and 'field' are mutually exclusive.`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if ('field' in filter) {
|
|
151
|
+
const filterFieldResult = getFieldForFilter({
|
|
152
|
+
document,
|
|
153
|
+
filter,
|
|
154
|
+
context: {
|
|
155
|
+
activeScheduledActionsByDocumentId,
|
|
156
|
+
locale,
|
|
157
|
+
schema
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
if ('result' in filterFieldResult) {
|
|
162
|
+
return filterFieldResult.result;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const { field, model } = filterFieldResult;
|
|
166
|
+
return isFieldMatchesFilter({ field, filter, document, model, locale });
|
|
167
|
+
} else {
|
|
168
|
+
if (!('and' in filter) && !('or' in filter)) {
|
|
169
|
+
throw new Error(`Unsupported filter - neither 'and' nor 'or' provided`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const comparisonMethod = 'and' in filter ? 'every' : 'some';
|
|
173
|
+
const root = 'and' in filter ? filter.and : filter.or;
|
|
174
|
+
|
|
175
|
+
if (!root.length) {
|
|
176
|
+
// for empty search groups - match
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return root[comparisonMethod]((childFilter) => {
|
|
181
|
+
return isFilterMatches({
|
|
182
|
+
filter: childFilter,
|
|
183
|
+
document,
|
|
184
|
+
locale,
|
|
185
|
+
schema,
|
|
186
|
+
activeScheduledActionsByDocumentId
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
119
192
|
const getFieldForFilter: MetaFieldMethod = ({ document, filter, context }) => {
|
|
120
193
|
if (filter.isMeta) {
|
|
121
194
|
const filterField = filter.field;
|
package/src/utils/site-map.ts
CHANGED
|
@@ -6,7 +6,6 @@ import * as CSITypes from '@stackbit/types';
|
|
|
6
6
|
import * as ContentStoreTypes from '../types';
|
|
7
7
|
import { mapStoreDocumentsToCSIDocumentsWithSource } from './store-to-csi-docs-converter';
|
|
8
8
|
import { getContentSourceId, getDocumentFieldForLocale } from '../content-store-utils';
|
|
9
|
-
import { createConfigDelegate } from './config-delegate';
|
|
10
9
|
|
|
11
10
|
export const SiteMapStaticEntriesKey = Symbol.for('SiteMapStaticEntriesKey');
|
|
12
11
|
export type SiteMapEntriesSourceKeys = string | symbol;
|
package/src/utils/tree-views.ts
CHANGED
|
@@ -70,3 +70,46 @@ export async function getSanitizedTreeViews({
|
|
|
70
70
|
|
|
71
71
|
return mapTreeViews(treeViews);
|
|
72
72
|
}
|
|
73
|
+
|
|
74
|
+
export function removeHiddenTreeViews({
|
|
75
|
+
treeViews,
|
|
76
|
+
getDocumentForUser
|
|
77
|
+
}: {
|
|
78
|
+
treeViews: CSITypes.TreeViewNode[];
|
|
79
|
+
getDocumentForUser: (opts: { srcDocumentId: string; srcType: string; srcProjectId: string }) => ContentStoreTypes.Document | undefined;
|
|
80
|
+
}) {
|
|
81
|
+
const mapTreeViews = (treeViews: CSITypes.TreeViewNode[]): CSITypes.TreeViewNode[] => {
|
|
82
|
+
return treeViews.map((treeView) => {
|
|
83
|
+
let resultTreeView = treeView;
|
|
84
|
+
|
|
85
|
+
if ('document' in treeView && treeView.document) {
|
|
86
|
+
const document = getDocumentForUser({
|
|
87
|
+
srcDocumentId: treeView.document.id,
|
|
88
|
+
srcType: treeView.document.srcType,
|
|
89
|
+
srcProjectId: treeView.document.srcProjectId
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (!document) {
|
|
93
|
+
throw new Error(`Could not found a document with id ${treeView.document.id} when iterating tree views`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (document.hidden) {
|
|
97
|
+
resultTreeView = _.omit(treeView, ['document']) as CSITypes.TreeViewBaseNode;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if ('children' in treeView && treeView.children) {
|
|
102
|
+
if (treeView.stableId && treeView.label) {
|
|
103
|
+
resultTreeView = {
|
|
104
|
+
...resultTreeView,
|
|
105
|
+
children: mapTreeViews(treeView.children)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return resultTreeView;
|
|
111
|
+
});
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
return mapTreeViews(treeViews);
|
|
115
|
+
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import * as ContentStoreTypes from '../types';
|
|
2
|
-
import { SearchFilterItem } from '../types';
|
|
3
|
-
import { ScheduledAction } from '@stackbit/types';
|
|
4
|
-
import { SchemaForSearch } from './search-utils';
|
|
5
|
-
declare type CustomFilterMethod = (filter: SearchFilterItem, document: ContentStoreTypes.Document, opts: {
|
|
6
|
-
locale?: string;
|
|
7
|
-
schema: SchemaForSearch;
|
|
8
|
-
activeScheduledActionsByDocumentId: Record<string, ScheduledAction[]>;
|
|
9
|
-
}) => boolean;
|
|
10
|
-
export declare const CUSTOM_FILTERS: Record<string, CustomFilterMethod>;
|
|
11
|
-
export {};
|
|
12
|
-
//# sourceMappingURL=custom-search-filters.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"custom-search-filters.d.ts","sourceRoot":"","sources":["../../src/utils/custom-search-filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,iBAAiB,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAqB,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAiE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEhH,aAAK,kBAAkB,GAAG,CACtB,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,EACpC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,kCAAkC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;CAAE,KACxH,OAAO,CAAC;AAEb,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAwC7D,CAAC"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CUSTOM_FILTERS = void 0;
|
|
4
|
-
const search_utils_1 = require("./search-utils");
|
|
5
|
-
exports.CUSTOM_FILTERS = {
|
|
6
|
-
hasSchedules: (filter, document, opts) => {
|
|
7
|
-
var _a;
|
|
8
|
-
const field = {
|
|
9
|
-
type: 'boolean',
|
|
10
|
-
value: !!((_a = opts.activeScheduledActionsByDocumentId[document.srcObjectId]) === null || _a === void 0 ? void 0 : _a.length)
|
|
11
|
-
};
|
|
12
|
-
return (0, search_utils_1.isBooleanFieldMatches)({ field, filter, locale: opts.locale });
|
|
13
|
-
},
|
|
14
|
-
scheduledActionId: (filter, document, opts) => {
|
|
15
|
-
var _a, _b;
|
|
16
|
-
const field = {
|
|
17
|
-
type: 'list',
|
|
18
|
-
items: (_b = (_a = opts.activeScheduledActionsByDocumentId[document.srcObjectId]) === null || _a === void 0 ? void 0 : _a.map((scheduledAction) => ({
|
|
19
|
-
type: 'string',
|
|
20
|
-
value: scheduledAction.id
|
|
21
|
-
}))) !== null && _b !== void 0 ? _b : []
|
|
22
|
-
};
|
|
23
|
-
const model = {
|
|
24
|
-
type: 'object',
|
|
25
|
-
name: '',
|
|
26
|
-
fields: [
|
|
27
|
-
{
|
|
28
|
-
name: '',
|
|
29
|
-
type: 'list',
|
|
30
|
-
items: {
|
|
31
|
-
type: 'string'
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
};
|
|
36
|
-
return (0, search_utils_1.isListFieldMatches)({ field, filter, model, locale: opts.locale, document });
|
|
37
|
-
},
|
|
38
|
-
scheduledActionDate: (filter, document, opts) => {
|
|
39
|
-
var _a, _b;
|
|
40
|
-
return ((_b = (_a = opts.activeScheduledActionsByDocumentId[document.srcObjectId]) === null || _a === void 0 ? void 0 : _a.some((scheduledAction) => {
|
|
41
|
-
const field = { type: 'date', value: scheduledAction.executeAt };
|
|
42
|
-
return (0, search_utils_1.isDateFieldMatches)({ field, filter, locale: opts.locale });
|
|
43
|
-
})) !== null && _b !== void 0 ? _b : false);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
//# sourceMappingURL=custom-search-filters.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"custom-search-filters.js","sourceRoot":"","sources":["../../src/utils/custom-search-filters.ts"],"names":[],"mappings":";;;AAIA,iDAAgH;AAQnG,QAAA,cAAc,GAAuC;IAC9D,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;;QACrC,MAAM,KAAK,GAAG;YACV,IAAI,EAAE,SAAkB;YACxB,KAAK,EAAE,CAAC,CAAC,CAAA,MAAA,IAAI,CAAC,kCAAkC,CAAC,QAAQ,CAAC,WAAW,CAAC,0CAAE,MAAM,CAAA;SACjF,CAAC;QACF,OAAO,IAAA,oCAAqB,EAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,iBAAiB,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;;QAC1C,MAAM,KAAK,GAAsB;YAC7B,IAAI,EAAE,MAAM;YACZ,KAAK,EACD,MAAA,MAAA,IAAI,CAAC,kCAAkC,CAAC,QAAQ,CAAC,WAAW,CAAC,0CAAE,GAAG,CAAC,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;gBACrF,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,eAAe,CAAC,EAAE;aAC5B,CAAC,CAAC,mCAAI,EAAE;SAChB,CAAC;QACF,MAAM,KAAK,GAAU;YACjB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,EAAE;YACR,MAAM,EAAE;gBACJ;oBACI,IAAI,EAAE,EAAE;oBACR,IAAI,EAAE,MAAM;oBACZ,KAAK,EAAE;wBACH,IAAI,EAAE,QAAQ;qBACjB;iBACJ;aACJ;SACJ,CAAC;QACF,OAAO,IAAA,iCAAkB,EAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvF,CAAC;IACD,mBAAmB,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;;QAC5C,OAAO,CACH,MAAA,MAAA,IAAI,CAAC,kCAAkC,CAAC,QAAQ,CAAC,WAAW,CAAC,0CAAE,IAAI,CAAC,CAAC,eAAe,EAAE,EAAE;YACpF,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,MAAe,EAAE,KAAK,EAAE,eAAe,CAAC,SAAS,EAAE,CAAC;YAC1E,OAAO,IAAA,iCAAkB,EAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,CAAC,CAAC,mCAAI,KAAK,CACd,CAAC;IACN,CAAC;CACJ,CAAC"}
|