@unchainedshop/core-assortments 1.1.3
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/.npm/package/README +7 -0
- package/.npm/package/npm-shrinkwrap.json +200 -0
- package/.versions +53 -0
- package/README.md +3 -0
- package/package.js +36 -0
- package/package.json +46 -0
- package/src/assortments-index.ts +3 -0
- package/src/assortments-settings.ts +27 -0
- package/src/db/AssortmentMediasCollection.ts +26 -0
- package/src/db/AssortmentMediasSchema.js +31 -0
- package/src/db/AssortmentsCollection.ts +84 -0
- package/src/db/AssortmentsSchema.js +75 -0
- package/src/migrations/addMigrations.ts +41 -0
- package/src/module/configureAssortmentFiltersModule.ts +153 -0
- package/src/module/configureAssortmentLinksModule.ts +212 -0
- package/src/module/configureAssortmentMediaModule.ts +259 -0
- package/src/module/configureAssortmentProductsModule.ts +234 -0
- package/src/module/configureAssortmentTextsModule.ts +179 -0
- package/src/module/configureAssortmentsModule.ts +438 -0
- package/src/product-cache/mongodb.ts +40 -0
- package/src/utils/breadcrumbs/build-paths.ts +58 -0
- package/src/utils/breadcrumbs/makeAssortmentBreadcrumbsBuilder.ts +20 -0
- package/src/utils/breadcrumbs/resolveAssortmentLinkFromDatabase.ts +25 -0
- package/src/utils/breadcrumbs/resolveAssortmentProductFromDatabase.ts +19 -0
- package/src/utils/tree-zipper/zipTreeByDeepness.ts +60 -0
- package/src/utils/tree-zipper/zipTreeBySimplyFlattening.ts +7 -0
- package/tests/assortments-index.test.ts +39 -0
- package/tsconfig.build.json +26 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { AssortmentFilter, AssortmentsModule } from '@unchainedshop/types/assortments';
|
|
2
|
+
import { Collection, Query } from '@unchainedshop/types/common';
|
|
3
|
+
import { emit, registerEvents } from '@unchainedshop/events';
|
|
4
|
+
import { generateDbFilterById, generateDbObjectId } from '@unchainedshop/utils';
|
|
5
|
+
|
|
6
|
+
const ASSORTMENT_FILTER_EVENTS = [
|
|
7
|
+
'ASSORTMENT_ADD_FILTER',
|
|
8
|
+
'ASSORTMENT_REMOVE_FILTER',
|
|
9
|
+
'ASSORTMENT_REORDER_FILTERS',
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export const configureAssortmentFiltersModule = ({
|
|
13
|
+
AssortmentFilters,
|
|
14
|
+
}: {
|
|
15
|
+
AssortmentFilters: Collection<AssortmentFilter>;
|
|
16
|
+
}): AssortmentsModule['filters'] => {
|
|
17
|
+
registerEvents(ASSORTMENT_FILTER_EVENTS);
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
findFilter: async ({ assortmentFilterId }) => {
|
|
21
|
+
return AssortmentFilters.findOne(generateDbFilterById(assortmentFilterId), {});
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
findFilters: async ({ assortmentId }, options) => {
|
|
25
|
+
const filters = AssortmentFilters.find({ assortmentId }, options);
|
|
26
|
+
return filters.toArray();
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
findFilterIds: async ({ assortmentId }) => {
|
|
30
|
+
const filters = AssortmentFilters.find(
|
|
31
|
+
{ assortmentId },
|
|
32
|
+
{
|
|
33
|
+
sort: { sortKey: 1 },
|
|
34
|
+
projection: { filterId: 1 },
|
|
35
|
+
},
|
|
36
|
+
).map((filter) => filter.filterId);
|
|
37
|
+
|
|
38
|
+
return filters.toArray();
|
|
39
|
+
},
|
|
40
|
+
create: async (doc: AssortmentFilter, userId) => {
|
|
41
|
+
const { _id, assortmentId, filterId, sortKey, ...rest } = doc;
|
|
42
|
+
|
|
43
|
+
const selector = {
|
|
44
|
+
...(_id ? generateDbFilterById(_id) : {}),
|
|
45
|
+
filterId,
|
|
46
|
+
assortmentId,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const $set: any = {
|
|
50
|
+
updated: new Date(),
|
|
51
|
+
updatedBy: userId,
|
|
52
|
+
...rest,
|
|
53
|
+
};
|
|
54
|
+
const $setOnInsert: any = {
|
|
55
|
+
_id: _id || generateDbObjectId(),
|
|
56
|
+
filterId,
|
|
57
|
+
assortmentId,
|
|
58
|
+
created: new Date(),
|
|
59
|
+
createdBy: userId,
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (!doc.sortKey) {
|
|
63
|
+
// Get next sort key
|
|
64
|
+
const lastAssortmentFilter = (await AssortmentFilters.findOne(
|
|
65
|
+
{ assortmentId },
|
|
66
|
+
{ sort: { sortKey: -1 } },
|
|
67
|
+
)) || { sortKey: 0 };
|
|
68
|
+
$setOnInsert.sortKey = lastAssortmentFilter.sortKey + 1;
|
|
69
|
+
} else {
|
|
70
|
+
$set.sortKey = sortKey;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await AssortmentFilters.updateOne(
|
|
74
|
+
selector,
|
|
75
|
+
{
|
|
76
|
+
$set,
|
|
77
|
+
$setOnInsert,
|
|
78
|
+
},
|
|
79
|
+
{ upsert: true },
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const assortmentFilter = await AssortmentFilters.findOne(selector, {});
|
|
83
|
+
|
|
84
|
+
emit('ASSORTMENT_ADD_FILTER', { assortmentFilter });
|
|
85
|
+
|
|
86
|
+
return assortmentFilter;
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
delete: async (assortmentFilterId) => {
|
|
90
|
+
const selector: Query = generateDbFilterById(assortmentFilterId);
|
|
91
|
+
|
|
92
|
+
const assortmentFilter = await AssortmentFilters.findOne(selector, {
|
|
93
|
+
projection: { _id: 1 },
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
await AssortmentFilters.deleteOne(selector);
|
|
97
|
+
|
|
98
|
+
emit('ASSORTMENT_REMOVE_FILTER', {
|
|
99
|
+
assortmentFilterId: assortmentFilter._id,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return [assortmentFilter];
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
deleteMany: async (selector) => {
|
|
106
|
+
const assortmentFilters = await AssortmentFilters.find(selector, {
|
|
107
|
+
projection: { _id: 1 },
|
|
108
|
+
}).toArray();
|
|
109
|
+
|
|
110
|
+
await AssortmentFilters.deleteMany(selector);
|
|
111
|
+
|
|
112
|
+
assortmentFilters.forEach((assortmentFilter) => {
|
|
113
|
+
emit('ASSORTMENT_REMOVE_FILTER', {
|
|
114
|
+
assortmentFilterId: assortmentFilter._id,
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return assortmentFilters;
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
// This action is specifically used for the bulk migration scripts in the platform package
|
|
122
|
+
update: async (assortmentFilterId, doc) => {
|
|
123
|
+
const selector = generateDbFilterById(assortmentFilterId);
|
|
124
|
+
const modifier = { $set: doc };
|
|
125
|
+
await AssortmentFilters.updateOne(selector, modifier);
|
|
126
|
+
return AssortmentFilters.findOne(selector, {});
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
updateManualOrder: async ({ sortKeys }, userId) => {
|
|
130
|
+
const changedAssortmentFilterIds = await Promise.all(
|
|
131
|
+
sortKeys.map(async ({ assortmentFilterId, sortKey }) => {
|
|
132
|
+
await AssortmentFilters.updateOne(generateDbFilterById(assortmentFilterId), {
|
|
133
|
+
$set: {
|
|
134
|
+
sortKey: sortKey + 1,
|
|
135
|
+
updated: new Date(),
|
|
136
|
+
updatedBy: userId,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
return assortmentFilterId;
|
|
141
|
+
}),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const assortmentFilters = await AssortmentFilters.find({
|
|
145
|
+
_id: { $in: changedAssortmentFilterIds },
|
|
146
|
+
}).toArray();
|
|
147
|
+
|
|
148
|
+
emit('ASSORTMENT_REORDER_FILTERS', { assortmentFilters });
|
|
149
|
+
|
|
150
|
+
return assortmentFilters;
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { AssortmentLink, AssortmentsModule } from '@unchainedshop/types/assortments';
|
|
2
|
+
import { Collection } from '@unchainedshop/types/common';
|
|
3
|
+
import { emit, registerEvents } from '@unchainedshop/events';
|
|
4
|
+
import { generateDbFilterById, generateDbObjectId } from '@unchainedshop/utils';
|
|
5
|
+
|
|
6
|
+
const ASSORTMENT_LINK_EVENTS = [
|
|
7
|
+
'ASSORTMENT_ADD_LINK',
|
|
8
|
+
'ASSORTMENT_REMOVE_LINK',
|
|
9
|
+
'ASSORTMENT_REORDER_LINKS',
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export const configureAssortmentLinksModule = ({
|
|
13
|
+
AssortmentLinks,
|
|
14
|
+
invalidateCache,
|
|
15
|
+
}: {
|
|
16
|
+
AssortmentLinks: Collection<AssortmentLink>;
|
|
17
|
+
invalidateCache: AssortmentsModule['invalidateCache'];
|
|
18
|
+
}): AssortmentsModule['links'] => {
|
|
19
|
+
registerEvents(ASSORTMENT_LINK_EVENTS);
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
// Queries
|
|
23
|
+
findLink: async ({ assortmentLinkId, parentAssortmentId, childAssortmentId }) => {
|
|
24
|
+
return AssortmentLinks.findOne(
|
|
25
|
+
assortmentLinkId
|
|
26
|
+
? generateDbFilterById(assortmentLinkId)
|
|
27
|
+
: { parentAssortmentId, childAssortmentId },
|
|
28
|
+
{},
|
|
29
|
+
);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
findLinks: async ({ assortmentId, parentAssortmentId }, options) => {
|
|
33
|
+
const selector = parentAssortmentId
|
|
34
|
+
? {
|
|
35
|
+
parentAssortmentId,
|
|
36
|
+
}
|
|
37
|
+
: {
|
|
38
|
+
$or: [{ parentAssortmentId: assortmentId }, { childAssortmentId: assortmentId }],
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const links = AssortmentLinks.find(
|
|
42
|
+
selector,
|
|
43
|
+
options || {
|
|
44
|
+
sort: { sortKey: 1 },
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return links.toArray();
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// Mutations
|
|
52
|
+
create: async (doc, options, userId) => {
|
|
53
|
+
const { _id: assortmentLinkId, parentAssortmentId, childAssortmentId, sortKey, ...rest } = doc;
|
|
54
|
+
|
|
55
|
+
const selector = {
|
|
56
|
+
...(assortmentLinkId ? generateDbFilterById(assortmentLinkId) : {}),
|
|
57
|
+
parentAssortmentId,
|
|
58
|
+
childAssortmentId,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const $set: any = {
|
|
62
|
+
updated: new Date(),
|
|
63
|
+
updatedBy: userId,
|
|
64
|
+
...rest,
|
|
65
|
+
};
|
|
66
|
+
const $setOnInsert: any = {
|
|
67
|
+
_id: assortmentLinkId || generateDbObjectId(),
|
|
68
|
+
parentAssortmentId,
|
|
69
|
+
childAssortmentId,
|
|
70
|
+
created: new Date(),
|
|
71
|
+
createdBy: userId,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
if (!sortKey) {
|
|
75
|
+
// Get next sort key
|
|
76
|
+
const lastAssortmentLink = (await AssortmentLinks.findOne(
|
|
77
|
+
{ parentAssortmentId },
|
|
78
|
+
{ sort: { sortKey: -1 } },
|
|
79
|
+
)) || { sortKey: 0 };
|
|
80
|
+
$setOnInsert.sortKey = lastAssortmentLink.sortKey + 1;
|
|
81
|
+
} else {
|
|
82
|
+
$set.sortKey = sortKey;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
await AssortmentLinks.updateOne(
|
|
86
|
+
selector,
|
|
87
|
+
{
|
|
88
|
+
$set,
|
|
89
|
+
$setOnInsert,
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
upsert: true,
|
|
93
|
+
},
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const assortmentLink = await AssortmentLinks.findOne(selector, {});
|
|
97
|
+
|
|
98
|
+
emit('ASSORTMENT_ADD_LINK', { assortmentLink });
|
|
99
|
+
|
|
100
|
+
if (!options.skipInvalidation) {
|
|
101
|
+
await invalidateCache({ assortmentIds: [parentAssortmentId] });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return assortmentLink;
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
// This action is specifically used for the bulk migration scripts in the platform package
|
|
108
|
+
update: async (assortmentLinkId, doc, options, userId) => {
|
|
109
|
+
const selector = generateDbFilterById(assortmentLinkId);
|
|
110
|
+
const modifier = {
|
|
111
|
+
$set: {
|
|
112
|
+
...doc,
|
|
113
|
+
updated: new Date(),
|
|
114
|
+
updatedBy: userId,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
await AssortmentLinks.updateOne(selector, modifier);
|
|
118
|
+
|
|
119
|
+
const assortmentLink = await AssortmentLinks.findOne(selector, {});
|
|
120
|
+
if (!options.skipInvalidation) {
|
|
121
|
+
await invalidateCache(
|
|
122
|
+
{ assortmentIds: [assortmentLink.childAssortmentId] },
|
|
123
|
+
{
|
|
124
|
+
skipUpstreamTraversal: false,
|
|
125
|
+
},
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return assortmentLink;
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
delete: async (assortmentLinkId, options) => {
|
|
132
|
+
const selector = generateDbFilterById(assortmentLinkId);
|
|
133
|
+
|
|
134
|
+
const assortmentLink = await AssortmentLinks.findOne(selector, {});
|
|
135
|
+
|
|
136
|
+
await AssortmentLinks.deleteOne(selector);
|
|
137
|
+
|
|
138
|
+
emit('ASSORTMENT_REMOVE_LINK', {
|
|
139
|
+
assortmentLinkId: assortmentLink._id,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
if (!options.skipInvalidation) {
|
|
143
|
+
await invalidateCache(
|
|
144
|
+
{
|
|
145
|
+
assortmentIds: [assortmentLink.childAssortmentId, assortmentLink.parentAssortmentId],
|
|
146
|
+
},
|
|
147
|
+
{ skipUpstreamTraversal: false },
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return assortmentLink;
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
deleteMany: async (selector, options) => {
|
|
155
|
+
const assortmentLinks = await AssortmentLinks.find(selector, {}).toArray();
|
|
156
|
+
|
|
157
|
+
await AssortmentLinks.deleteMany(selector);
|
|
158
|
+
assortmentLinks.forEach((assortmentLink) => {
|
|
159
|
+
emit('ASSORTMENT_REMOVE_LINK', {
|
|
160
|
+
assortmentLinkId: assortmentLink._id,
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (!options.skipInvalidation && assortmentLinks.length) {
|
|
165
|
+
await invalidateCache(
|
|
166
|
+
{
|
|
167
|
+
assortmentIds: assortmentLinks.flatMap((link) => [
|
|
168
|
+
link.childAssortmentId,
|
|
169
|
+
link.parentAssortmentId,
|
|
170
|
+
]),
|
|
171
|
+
},
|
|
172
|
+
{ skipUpstreamTraversal: false },
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return assortmentLinks;
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
updateManualOrder: async ({ sortKeys }, options, userId) => {
|
|
180
|
+
const changedAssortmentLinkIds = await Promise.all(
|
|
181
|
+
sortKeys.map(async ({ assortmentLinkId, sortKey }) => {
|
|
182
|
+
await AssortmentLinks.updateOne(generateDbFilterById(assortmentLinkId), {
|
|
183
|
+
$set: {
|
|
184
|
+
sortKey: sortKey + 1,
|
|
185
|
+
updated: new Date(),
|
|
186
|
+
updatedBy: userId,
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
return assortmentLinkId;
|
|
191
|
+
}),
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const assortmentLinks = await AssortmentLinks.find({
|
|
195
|
+
_id: { $in: changedAssortmentLinkIds },
|
|
196
|
+
}).toArray();
|
|
197
|
+
|
|
198
|
+
if (!options.skipInvalidation && assortmentLinks.length) {
|
|
199
|
+
await invalidateCache(
|
|
200
|
+
{ assortmentIds: assortmentLinks.map((link) => link.childAssortmentId) },
|
|
201
|
+
{
|
|
202
|
+
skipUpstreamTraversal: false,
|
|
203
|
+
},
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
emit('ASSORTMENT_REORDER_LINKS', { assortmentLinks });
|
|
208
|
+
|
|
209
|
+
return assortmentLinks;
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
};
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AssortmentMedia,
|
|
3
|
+
AssortmentMediaModule,
|
|
4
|
+
AssortmentMediaText,
|
|
5
|
+
} from '@unchainedshop/types/assortments.media';
|
|
6
|
+
import { ModuleInput, ModuleMutations, Query } from '@unchainedshop/types/common';
|
|
7
|
+
import { Locale } from 'locale';
|
|
8
|
+
import { emit, registerEvents } from '@unchainedshop/events';
|
|
9
|
+
import {
|
|
10
|
+
findLocalizedText,
|
|
11
|
+
generateDbFilterById,
|
|
12
|
+
generateDbMutations,
|
|
13
|
+
generateDbObjectId,
|
|
14
|
+
} from '@unchainedshop/utils';
|
|
15
|
+
import { FileDirector } from '@unchainedshop/file-upload';
|
|
16
|
+
import { AssortmentMediaCollection } from '../db/AssortmentMediasCollection';
|
|
17
|
+
import { AssortmentMediasSchema } from '../db/AssortmentMediasSchema';
|
|
18
|
+
|
|
19
|
+
const ASSORTMENT_MEDIA_EVENTS = [
|
|
20
|
+
'ASSORTMENT_ADD_MEDIA',
|
|
21
|
+
'ASSORTMENT_REMOVE_MEDIA',
|
|
22
|
+
'ASSORTMENT_REORDER_MEDIA',
|
|
23
|
+
'ASSORTMENT_UPDATE_MEDIA_TEXT',
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
FileDirector.registerFileUploadCallback('assortment-media', async (file, { modules, userId }) => {
|
|
27
|
+
await modules.assortments.media.create(
|
|
28
|
+
{
|
|
29
|
+
assortmentId: file.meta.assortmentId,
|
|
30
|
+
mediaId: file._id,
|
|
31
|
+
},
|
|
32
|
+
file.updatedBy || file.createdBy || userId,
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const configureAssortmentMediaModule = async ({
|
|
37
|
+
db,
|
|
38
|
+
}: ModuleInput<Record<string, never>>): Promise<AssortmentMediaModule> => {
|
|
39
|
+
registerEvents(ASSORTMENT_MEDIA_EVENTS);
|
|
40
|
+
|
|
41
|
+
const { AssortmentMedias, AssortmentMediaTexts } = await AssortmentMediaCollection(db);
|
|
42
|
+
|
|
43
|
+
const mutations = generateDbMutations<AssortmentMedia>(
|
|
44
|
+
AssortmentMedias,
|
|
45
|
+
AssortmentMediasSchema,
|
|
46
|
+
) as ModuleMutations<AssortmentMedia>;
|
|
47
|
+
|
|
48
|
+
const upsertLocalizedText: AssortmentMediaModule['texts']['upsertLocalizedText'] = async (
|
|
49
|
+
assortmentMediaId,
|
|
50
|
+
locale,
|
|
51
|
+
text,
|
|
52
|
+
userId,
|
|
53
|
+
) => {
|
|
54
|
+
const selector = {
|
|
55
|
+
assortmentMediaId,
|
|
56
|
+
locale,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const updsertResult = await AssortmentMediaTexts.updateOne(
|
|
60
|
+
selector,
|
|
61
|
+
{
|
|
62
|
+
$set: {
|
|
63
|
+
updated: new Date(),
|
|
64
|
+
updatedBy: userId,
|
|
65
|
+
authorId: userId,
|
|
66
|
+
...text,
|
|
67
|
+
},
|
|
68
|
+
$setOnInsert: {
|
|
69
|
+
_id: generateDbObjectId(),
|
|
70
|
+
created: new Date(),
|
|
71
|
+
createdBy: userId,
|
|
72
|
+
assortmentMediaId,
|
|
73
|
+
locale,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
upsert: true,
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return AssortmentMediaTexts.findOne(
|
|
82
|
+
updsertResult.upsertedId ? generateDbFilterById(updsertResult.upsertedId) : selector,
|
|
83
|
+
{},
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
// Queries
|
|
89
|
+
findAssortmentMedia: async ({ assortmentMediaId }) => {
|
|
90
|
+
return AssortmentMedias.findOne(generateDbFilterById(assortmentMediaId), {});
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
findAssortmentMedias: async ({ assortmentId, tags, offset, limit }, options) => {
|
|
94
|
+
const selector: Query = assortmentId ? { assortmentId } : {};
|
|
95
|
+
if (tags && tags.length > 0) {
|
|
96
|
+
selector.tags = { $all: tags };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const mediaList = AssortmentMedias.find(selector, {
|
|
100
|
+
skip: offset,
|
|
101
|
+
limit,
|
|
102
|
+
sort: { sortKey: 1 },
|
|
103
|
+
...options,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return mediaList.toArray();
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
// Mutations
|
|
110
|
+
create: async (doc: AssortmentMedia, userId) => {
|
|
111
|
+
let { sortKey } = doc;
|
|
112
|
+
|
|
113
|
+
if (!sortKey) {
|
|
114
|
+
// Get next sort key
|
|
115
|
+
const lastAssortmentMedia = (await AssortmentMedias.findOne(
|
|
116
|
+
{
|
|
117
|
+
assortmentId: doc.assortmentId,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
sort: { sortKey: -1 },
|
|
121
|
+
},
|
|
122
|
+
)) || { sortKey: 0 };
|
|
123
|
+
sortKey = lastAssortmentMedia.sortKey + 1;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const assortmentMediaId = await mutations.create(
|
|
127
|
+
{
|
|
128
|
+
tags: [],
|
|
129
|
+
authorId: userId,
|
|
130
|
+
...doc,
|
|
131
|
+
sortKey,
|
|
132
|
+
},
|
|
133
|
+
userId,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const assortmentMedia = await AssortmentMedias.findOne(
|
|
137
|
+
generateDbFilterById(assortmentMediaId),
|
|
138
|
+
{},
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
emit('ASSORTMENT_ADD_MEDIA', {
|
|
142
|
+
assortmentMedia,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return assortmentMedia;
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
delete: async (assortmentMediaId) => {
|
|
149
|
+
const selector = generateDbFilterById(assortmentMediaId);
|
|
150
|
+
|
|
151
|
+
const deletedResult = await AssortmentMedias.deleteOne(selector);
|
|
152
|
+
|
|
153
|
+
emit('ASSORTMENT_REMOVE_MEDIA', {
|
|
154
|
+
assortmentMediaId,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
return deletedResult.deletedCount;
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
deleteMediaFiles: async ({ assortmentId, excludedAssortmentIds, excludedAssortmentMediaIds }) => {
|
|
161
|
+
const selector: Query = assortmentId ? { assortmentId } : {};
|
|
162
|
+
|
|
163
|
+
if (!assortmentId && excludedAssortmentIds) {
|
|
164
|
+
selector.assortmentId = { $nin: excludedAssortmentIds };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (excludedAssortmentMediaIds) {
|
|
168
|
+
selector._id = { $nin: excludedAssortmentMediaIds };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const ids = await AssortmentMedias.find(selector, { projection: { _id: true } })
|
|
172
|
+
.map((m) => m._id)
|
|
173
|
+
.toArray();
|
|
174
|
+
|
|
175
|
+
const deletedResult = await AssortmentMedias.deleteMany(selector);
|
|
176
|
+
|
|
177
|
+
ids.forEach((assortmentMediaId) => {
|
|
178
|
+
emit('ASSORTMENT_REMOVE_MEDIA', {
|
|
179
|
+
assortmentMediaId,
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return deletedResult.deletedCount;
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
// This action is specifically used for the bulk migration scripts in the platform package
|
|
187
|
+
update: async (assortmentMediaId, doc) => {
|
|
188
|
+
const selector = generateDbFilterById(assortmentMediaId);
|
|
189
|
+
const modifier = { $set: doc };
|
|
190
|
+
await AssortmentMedias.updateOne(selector, modifier);
|
|
191
|
+
return AssortmentMedias.findOne(selector, {});
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
updateManualOrder: async ({ sortKeys }, userId) => {
|
|
195
|
+
const changedAssortmentMediaIds = await Promise.all(
|
|
196
|
+
sortKeys.map(async ({ assortmentMediaId, sortKey }) => {
|
|
197
|
+
await AssortmentMedias.updateOne(generateDbFilterById(assortmentMediaId), {
|
|
198
|
+
$set: {
|
|
199
|
+
sortKey: sortKey + 1,
|
|
200
|
+
updated: new Date(),
|
|
201
|
+
updatedBy: userId,
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
return assortmentMediaId;
|
|
206
|
+
}),
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
const assortmentMedias = await AssortmentMedias.find({
|
|
210
|
+
_id: { $in: changedAssortmentMediaIds },
|
|
211
|
+
}).toArray();
|
|
212
|
+
|
|
213
|
+
emit('ASSORTMENT_REORDER_MEDIA', { assortmentMedias });
|
|
214
|
+
|
|
215
|
+
return assortmentMedias;
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
/*
|
|
219
|
+
* Assortment Media Texts
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
texts: {
|
|
223
|
+
// Queries
|
|
224
|
+
findMediaTexts: async ({ assortmentMediaId }) => {
|
|
225
|
+
return AssortmentMediaTexts.find({ assortmentMediaId }).toArray();
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
findLocalizedMediaText: async ({ assortmentMediaId, locale }) => {
|
|
229
|
+
const parsedLocale = new Locale(locale);
|
|
230
|
+
|
|
231
|
+
const text = await findLocalizedText<AssortmentMediaText>(
|
|
232
|
+
AssortmentMediaTexts,
|
|
233
|
+
{ assortmentMediaId },
|
|
234
|
+
parsedLocale,
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
return text;
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
// Mutations
|
|
241
|
+
updateMediaTexts: async (assortmentMediaId, texts, userId) => {
|
|
242
|
+
const mediaTexts = await Promise.all(
|
|
243
|
+
texts.map(({ locale, ...text }) =>
|
|
244
|
+
upsertLocalizedText(assortmentMediaId, locale, text, userId),
|
|
245
|
+
),
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
emit('ASSORTMENT_UPDATE_MEDIA_TEXT', {
|
|
249
|
+
assortmentMediaId,
|
|
250
|
+
mediaTexts,
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
return mediaTexts;
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
upsertLocalizedText,
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
};
|