@primershop/strapi-plugin-status-manager 0.0.16 → 0.0.18

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.
@@ -1,752 +1,650 @@
1
- 'use strict';
2
-
3
- var utils = require('@strapi/utils');
4
-
5
- var permissions = [
6
- {
7
- section: "plugins",
8
- displayName: "Access Status Manager",
9
- uid: "main",
10
- pluginName: "primershop-status-manager"
11
- },
12
- {
13
- section: "plugins",
14
- displayName: "Create",
15
- uid: "status.create",
16
- subCategory: "status",
17
- pluginName: "primershop-status-manager"
18
- },
19
- {
20
- section: "plugins",
21
- displayName: "Read",
22
- uid: "status.read",
23
- subCategory: "status",
24
- pluginName: "primershop-status-manager",
25
- aliases: [
26
- {
27
- actionId: "plugin::content-manager.explorer.read",
28
- subjects: [
29
- "plugin::primershop-status-manager.status"
30
- ]
31
- }
32
- ]
33
- },
34
- {
35
- section: "plugins",
36
- displayName: "Update",
37
- uid: "status.update",
38
- subCategory: "status",
39
- pluginName: "primershop-status-manager"
40
- },
41
- {
42
- section: "plugins",
43
- displayName: "Delete",
44
- uid: "status.delete",
45
- subCategory: "status",
46
- pluginName: "primershop-status-manager"
47
- }
1
+ "use strict";
2
+ const utils = require("@strapi/utils");
3
+ const permissions = [
4
+ {
5
+ section: "plugins",
6
+ displayName: "Access Status Manager",
7
+ uid: "main",
8
+ pluginName: "primershop-status-manager"
9
+ },
10
+ {
11
+ section: "plugins",
12
+ displayName: "Create",
13
+ uid: "status.create",
14
+ subCategory: "status",
15
+ pluginName: "primershop-status-manager"
16
+ },
17
+ {
18
+ section: "plugins",
19
+ displayName: "Read",
20
+ uid: "status.read",
21
+ subCategory: "status",
22
+ pluginName: "primershop-status-manager",
23
+ aliases: [
24
+ {
25
+ actionId: "plugin::content-manager.explorer.read",
26
+ subjects: ["plugin::primershop-status-manager.status"]
27
+ }
28
+ ]
29
+ },
30
+ {
31
+ section: "plugins",
32
+ displayName: "Update",
33
+ uid: "status.update",
34
+ subCategory: "status",
35
+ pluginName: "primershop-status-manager"
36
+ },
37
+ {
38
+ section: "plugins",
39
+ displayName: "Delete",
40
+ uid: "status.delete",
41
+ subCategory: "status",
42
+ pluginName: "primershop-status-manager"
43
+ }
48
44
  ];
49
-
50
- const bootstrap = async ({ strapi })=>{
51
- try {
52
- strapi.admin.services.permission.actionProvider.registerMany(permissions);
53
- strapi.log.info(`[primershop-status-manager] Registered ${permissions.length} permission actions`);
54
- } catch (error) {
55
- strapi.log.error("[primershop-status-manager] Failed to register permissions:", error);
56
- throw error;
45
+ const bootstrap = async ({ strapi: strapi2 }) => {
46
+ try {
47
+ strapi2.admin.services.permission.actionProvider.registerMany(
48
+ permissions
49
+ );
50
+ strapi2.log.info(
51
+ `[primershop-status-manager] Registered ${permissions.length} permission actions`
52
+ );
53
+ } catch (error) {
54
+ strapi2.log.error(
55
+ "[primershop-status-manager] Failed to register permissions:",
56
+ error
57
+ );
58
+ throw error;
59
+ }
60
+ strapi2.db?.lifecycles?.subscribe?.({
61
+ // catch all models
62
+ models: ["*"],
63
+ async afterDelete(event) {
64
+ const modelUid = event?.model?.uid;
65
+ const deleted = event?.result;
66
+ const documentId = deleted?.documentId;
67
+ if (!modelUid || !documentId) return;
68
+ await strapi2.db.query("plugin::primershop-status-manager.status-link").deleteMany({
69
+ where: { targetUid: modelUid, targetDocumentId: documentId }
70
+ });
57
71
  }
58
- // Register lifecycle hooks for status filtering
59
- strapi.db?.lifecycles?.subscribe?.({
60
- // catch all models
61
- models: [
62
- "*"
63
- ],
64
- async afterDelete (event) {
65
- const modelUid = event?.model?.uid;
66
- const deleted = event?.result;
67
- const documentId = deleted?.documentId;
68
- if (!modelUid || !documentId) return;
69
- await strapi.db.query("plugin::primershop-status-manager.status-link").deleteMany({
70
- where: {
71
- targetUid: modelUid,
72
- targetDocumentId: documentId
73
- }
74
- });
75
- }
76
- });
72
+ });
77
73
  };
78
-
79
- var status$1 = {
80
- kind: "collectionType",
81
- collectionName: "status",
82
- info: {
83
- singularName: "status",
84
- pluralName: "statuses",
85
- displayName: "Status",
86
- description: "Status for products"
74
+ const status$1 = {
75
+ kind: "collectionType",
76
+ collectionName: "status",
77
+ info: {
78
+ singularName: "status",
79
+ pluralName: "statuses",
80
+ displayName: "Status",
81
+ description: "Status for products"
82
+ },
83
+ options: {
84
+ draftAndPublish: false
85
+ },
86
+ pluginOptions: {
87
+ "content-manager": {
88
+ visible: false
87
89
  },
88
- options: {
89
- draftAndPublish: false
90
+ "content-type-builder": {
91
+ visible: false
92
+ }
93
+ },
94
+ attributes: {
95
+ name: {
96
+ type: "string",
97
+ minLength: 1,
98
+ maxLength: 50,
99
+ required: true,
100
+ configurable: false
90
101
  },
91
- pluginOptions: {
92
- "content-manager": {
93
- visible: false
94
- },
95
- "content-type-builder": {
96
- visible: false
97
- }
102
+ published: {
103
+ type: "boolean",
104
+ default: false
98
105
  },
99
- attributes: {
100
- name: {
101
- type: "string",
102
- minLength: 1,
103
- maxLength: 50,
104
- required: true,
105
- configurable: false
106
- },
107
- published: {
108
- type: "boolean",
109
- default: false
110
- },
111
- order: {
112
- type: "integer",
113
- default: 0
114
- },
115
- links: {
116
- type: "relation",
117
- relation: "oneToMany",
118
- target: "plugin::primershop-status-manager.status-link",
119
- mappedBy: "status",
120
- configurable: false
121
- }
106
+ order: {
107
+ type: "integer",
108
+ default: 0
109
+ },
110
+ links: {
111
+ type: "relation",
112
+ relation: "oneToMany",
113
+ target: "plugin::primershop-status-manager.status-link",
114
+ mappedBy: "status",
115
+ configurable: false
122
116
  }
117
+ }
123
118
  };
124
-
125
- var statusLink = {
126
- kind: "collectionType",
127
- collectionName: "status_links",
128
- info: {
129
- singularName: "status-link",
130
- pluralName: "status-links",
131
- displayName: "Status Link",
132
- description: "Association between any content type document and a single status"
119
+ const statusLink = {
120
+ kind: "collectionType",
121
+ collectionName: "status_links",
122
+ info: {
123
+ singularName: "status-link",
124
+ pluralName: "status-links",
125
+ displayName: "Status Link",
126
+ description: "Association between any content type document and a single status"
127
+ },
128
+ options: {
129
+ draftAndPublish: false
130
+ },
131
+ pluginOptions: {
132
+ "content-manager": {
133
+ visible: false
133
134
  },
134
- options: {
135
- draftAndPublish: false
135
+ "content-type-builder": {
136
+ visible: false
137
+ }
138
+ },
139
+ attributes: {
140
+ targetUid: {
141
+ type: "string",
142
+ required: true
136
143
  },
137
- pluginOptions: {
138
- "content-manager": {
139
- visible: false
140
- },
141
- "content-type-builder": {
142
- visible: false
143
- }
144
+ targetDocumentId: {
145
+ type: "string",
146
+ required: true
144
147
  },
145
- attributes: {
146
- targetUid: {
147
- type: "string",
148
- required: true
149
- },
150
- targetDocumentId: {
151
- type: "string",
152
- required: true
153
- },
154
- status: {
155
- type: "relation",
156
- relation: "manyToOne",
157
- target: "plugin::primershop-status-manager.status",
158
- required: false,
159
- configurable: false
160
- }
161
- }
162
- };
163
-
164
- var contentTypes = {
165
148
  status: {
166
- schema: status$1
167
- },
168
- "status-link": {
169
- schema: statusLink
149
+ type: "relation",
150
+ relation: "manyToOne",
151
+ target: "plugin::primershop-status-manager.status",
152
+ required: false,
153
+ configurable: false
170
154
  }
155
+ }
171
156
  };
172
-
173
- const content = ({ strapi })=>({
174
- async getStatusForTarget (ctx) {
175
- const requestParams = ctx.request.URL.searchParams;
176
- const contentTypeUid = requestParams.get("contentTypeUid");
177
- if (!strapi.getModel(contentTypeUid)) return ctx.notFound("Unknown contentTypeUid");
178
- const contentDocumentId = requestParams.get("contentDocumentId");
179
- const exists = await strapi.documents(contentTypeUid).findOne({
180
- documentId: contentDocumentId
181
- });
182
- if (!exists) return ctx.notFound("Target document not found");
183
- const link = await strapi.plugin("primershop-status-manager").service("statusLink").getForTarget(contentTypeUid, contentDocumentId);
184
- return ctx.send({
185
- status: link?.status ?? null
186
- });
187
- },
188
- async setStatusForTarget (ctx) {
189
- const { contentTypeUid, contentDocumentId, statusId } = ctx.request.body;
190
- if (!strapi.getModel(contentTypeUid)) return ctx.notFound("Unknown contentTypeUid");
191
- const exists = await strapi.documents(contentTypeUid).findOne({
192
- documentId: contentDocumentId
193
- });
194
- if (!exists) return ctx.notFound("Target document not found");
195
- const link = await strapi.plugin("primershop-status-manager").service("statusLink").setForTarget(contentTypeUid, contentDocumentId, statusId);
196
- return ctx.send({
197
- status: link.status
198
- });
199
- }
157
+ const contentTypes = {
158
+ status: {
159
+ schema: status$1
160
+ },
161
+ "status-link": {
162
+ schema: statusLink
163
+ }
164
+ };
165
+ const content = ({ strapi: strapi2 }) => ({
166
+ async getStatusForTarget(ctx) {
167
+ const requestParams = ctx.request.URL.searchParams;
168
+ const contentTypeUid = requestParams.get("contentTypeUid");
169
+ if (!strapi2.getModel(contentTypeUid))
170
+ return ctx.notFound("Unknown contentTypeUid");
171
+ const contentDocumentId = requestParams.get("contentDocumentId");
172
+ const exists = await strapi2.documents(contentTypeUid).findOne({
173
+ documentId: contentDocumentId
200
174
  });
201
-
202
- const status = ({ strapi })=>({
203
- async listStatuses (ctx) {
204
- try {
205
- const statuses = await strapi.documents("plugin::primershop-status-manager.status").findMany({
206
- sort: {
207
- order: "asc"
208
- }
209
- });
210
- return ctx.send(statuses);
211
- } catch (err) {
212
- console.error("❌ Status controller: find error:", err);
213
- ctx.throw(500, err);
214
- }
215
- },
216
- async create (ctx) {
217
- try {
218
- const { name, published = false } = ctx.request.body;
219
- // Validate name (only Latin characters)
220
- if (!/^[a-zA-Z\s]+$/.test(name)) {
221
- return ctx.badRequest("Status name must contain only Latin characters.");
222
- }
223
- // Get the highest order value
224
- const existingStatuses = await strapi.documents("plugin::primershop-status-manager.status").findMany({
225
- orderBy: {
226
- order: "desc"
227
- },
228
- limit: 1
229
- });
230
- const newOrder = existingStatuses.length > 0 ? existingStatuses[0].order + 1 : 0;
231
- // Create status
232
- const newStatus = await strapi.documents("plugin::primershop-status-manager.status").create({
233
- data: {
234
- name,
235
- published,
236
- order: newOrder
237
- }
238
- });
239
- return ctx.send(newStatus);
240
- } catch (error) {
241
- console.error("Status controller: create error:", error);
242
- ctx.internalServerError(`Error adding status: ${error}`);
243
- }
244
- },
245
- async reorder (ctx) {
246
- try {
247
- const { statuses } = ctx.request.body;
248
- if (!Array.isArray(statuses)) {
249
- return ctx.badRequest("Invalid data format");
250
- }
251
- // Update each status with new order
252
- await Promise.all(statuses.map(({ documentId, order })=>strapi.documents("plugin::primershop-status-manager.status").update({
253
- documentId,
254
- data: {
255
- order
256
- }
257
- })));
258
- ctx.send({
259
- message: "Order updated successfully"
260
- });
261
- } catch (error) {
262
- console.error("Status controller: reorder error:", error);
263
- ctx.internalServerError(`Error updating order: ${error}`);
264
- }
265
- },
266
- async publish (ctx) {
267
- try {
268
- const { id } = ctx.params;
269
- const { published } = ctx.request.body;
270
- await strapi.documents("plugin::primershop-status-manager.status").update({
271
- documentId: id,
272
- data: {
273
- published
274
- }
275
- });
276
- ctx.send({
277
- message: "Status updated successfully"
278
- });
279
- } catch (error) {
280
- console.error("Status controller: publish error:", error);
281
- ctx.internalServerError(`Error updating status: ${error}`);
282
- }
283
- },
284
- async delete (ctx) {
285
- try {
286
- const { statusId } = ctx.request.body;
287
- if (!statusId) {
288
- return ctx.badRequest("Status ID is required.");
289
- }
290
- // Delete the status
291
- await strapi.documents("plugin::primershop-status-manager.status").delete({
292
- documentId: statusId
293
- });
294
- return ctx.send({
295
- message: "Status deleted successfully"
296
- });
297
- } catch (error) {
298
- console.error("Status controller: delete error:", error);
299
- ctx.internalServerError(`Error deleting status: ${error}`);
300
- }
301
- }
175
+ if (!exists) return ctx.notFound("Target document not found");
176
+ const link = await strapi2.plugin("primershop-status-manager").service("statusLink").getForTarget(contentTypeUid, contentDocumentId);
177
+ return ctx.send({ status: link?.status ?? null });
178
+ },
179
+ async setStatusForTarget(ctx) {
180
+ const { contentTypeUid, contentDocumentId, statusId } = ctx.request.body;
181
+ if (!strapi2.getModel(contentTypeUid))
182
+ return ctx.notFound("Unknown contentTypeUid");
183
+ const exists = await strapi2.documents(contentTypeUid).findOne({
184
+ documentId: contentDocumentId
302
185
  });
303
-
304
- var controllers = {
305
- status_controller: status,
306
- content_controller: content
307
- };
308
-
309
- const PLUGIN_ID = "primershop-status-manager";
310
-
311
- var addStatusField = (async (context, next)=>{
312
- const uid = context.uid;
313
- if (!uid.includes("api::")) {
314
- return next();
315
- }
316
- const result = await next();
317
- let documentIds = [];
318
- if (Array.isArray(result)) {
319
- documentIds = result.map((doc)=>doc.documentId).filter(Boolean);
320
- } else if (result && typeof result === "object" && "documentId" in result) {
321
- documentIds = [
322
- result.documentId
323
- ].filter(Boolean);
324
- }
325
- if (documentIds.length === 0) {
326
- return result;
186
+ if (!exists) return ctx.notFound("Target document not found");
187
+ const link = await strapi2.plugin("primershop-status-manager").service("statusLink").setForTarget(contentTypeUid, contentDocumentId, statusId);
188
+ return ctx.send({ status: link.status });
189
+ }
190
+ });
191
+ const status = ({ strapi: strapi2 }) => ({
192
+ async listStatuses(ctx) {
193
+ try {
194
+ const statuses = await strapi2.documents("plugin::primershop-status-manager.status").findMany({
195
+ sort: { order: "asc" }
196
+ });
197
+ return ctx.send(statuses);
198
+ } catch (err) {
199
+ console.error("❌ Status controller: find error:", err);
200
+ ctx.throw(500, err);
327
201
  }
202
+ },
203
+ async create(ctx) {
328
204
  try {
329
- const statusLinks = await strapi.db.query("plugin::primershop-status-manager.status-link").findMany({
330
- populate: {
331
- status: true
332
- },
333
- where: {
334
- targetUid: uid,
335
- targetDocumentId: {
336
- $in: documentIds
337
- }
338
- }
339
- });
340
- if (Array.isArray(result)) {
341
- result.forEach((doc)=>{
342
- doc.statusField = statusLinks.find((link)=>link.targetDocumentId === doc.documentId)?.status || undefined;
343
- });
344
- }
345
- if (result && typeof result === "object") {
346
- result.statusField = statusLinks.find((link)=>link.targetDocumentId === result.documentId)?.status || undefined;
205
+ const { name, published = false } = ctx.request.body;
206
+ if (!/^[a-zA-Z\s]+$/.test(name)) {
207
+ return ctx.badRequest(
208
+ "Status name must contain only Latin characters."
209
+ );
210
+ }
211
+ const existingStatuses = await strapi2.documents("plugin::primershop-status-manager.status").findMany({
212
+ orderBy: { order: "desc" },
213
+ limit: 1
214
+ });
215
+ const newOrder = existingStatuses.length > 0 ? existingStatuses[0].order + 1 : 0;
216
+ const newStatus = await strapi2.documents("plugin::primershop-status-manager.status").create({
217
+ data: {
218
+ name,
219
+ published,
220
+ order: newOrder
347
221
  }
222
+ });
223
+ return ctx.send(newStatus);
348
224
  } catch (error) {
349
- // If status enrichment fails, just return original result
350
- console.error("primershop-status-manager: status enrichment error", error);
225
+ console.error("Status controller: create error:", error);
226
+ ctx.internalServerError(`Error adding status: ${error}`);
351
227
  }
352
- return result;
353
- });
354
-
355
- var filterByStatus = (async (context, next)=>{
356
- const uid = context.uid;
357
- if (!uid.includes("api::")) {
358
- return next();
228
+ },
229
+ async reorder(ctx) {
230
+ try {
231
+ const { statuses } = ctx.request.body;
232
+ if (!Array.isArray(statuses)) {
233
+ return ctx.badRequest("Invalid data format");
234
+ }
235
+ await Promise.all(
236
+ statuses.map(
237
+ ({ documentId, order }) => strapi2.documents("plugin::primershop-status-manager.status").update({
238
+ documentId,
239
+ data: { order }
240
+ })
241
+ )
242
+ );
243
+ ctx.send({ message: "Order updated successfully" });
244
+ } catch (error) {
245
+ console.error("Status controller: reorder error:", error);
246
+ ctx.internalServerError(`Error updating order: ${error}`);
359
247
  }
360
- const paramKeys = Object.keys(context.params || {});
361
- if (!paramKeys.includes("statusName")) {
362
- return next();
248
+ },
249
+ async publish(ctx) {
250
+ try {
251
+ const { id } = ctx.params;
252
+ const { published } = ctx.request.body;
253
+ await strapi2.documents("plugin::primershop-status-manager.status").update({
254
+ documentId: id,
255
+ data: { published }
256
+ });
257
+ ctx.send({ message: "Status updated successfully" });
258
+ } catch (error) {
259
+ console.error("Status controller: publish error:", error);
260
+ ctx.internalServerError(`Error updating status: ${error}`);
363
261
  }
364
- const desiredStatus = context.params["statusName"];
365
- if (!desiredStatus || desiredStatus === "all") return next();
366
- const isValid = await strapi.plugin("primershop-status-manager").service("status").isValidStatus(desiredStatus);
367
- if (!isValid) throw new utils.errors.ValidationError(`Invalid status: ${desiredStatus}`);
368
- const status = await strapi.plugin("primershop-status-manager").service("status").getStatusByName(desiredStatus);
369
- if (!status) {
370
- throw new utils.errors.ValidationError(`Status not found: ${desiredStatus}`);
262
+ },
263
+ async delete(ctx) {
264
+ try {
265
+ const { statusId } = ctx.request.body;
266
+ if (!statusId) {
267
+ return ctx.badRequest("Status ID is required.");
268
+ }
269
+ await strapi2.documents("plugin::primershop-status-manager.status").delete({
270
+ documentId: statusId
271
+ });
272
+ return ctx.send({ message: "Status deleted successfully" });
273
+ } catch (error) {
274
+ console.error("Status controller: delete error:", error);
275
+ ctx.internalServerError(`Error deleting status: ${error}`);
371
276
  }
277
+ }
278
+ });
279
+ const controllers = {
280
+ status_controller: status,
281
+ content_controller: content
282
+ };
283
+ const PLUGIN_ID = "primershop-status-manager";
284
+ const addStatusField = async (context, next) => {
285
+ const uid = context.uid;
286
+ if (!uid.includes("api::")) {
287
+ return next();
288
+ }
289
+ const result = await next();
290
+ let documentIds = [];
291
+ if (Array.isArray(result)) {
292
+ documentIds = result.map((doc) => doc.documentId).filter(Boolean);
293
+ } else if (result && typeof result === "object" && "documentId" in result) {
294
+ documentIds = [result.documentId].filter(Boolean);
295
+ }
296
+ if (documentIds.length === 0) {
297
+ return result;
298
+ }
299
+ try {
372
300
  const statusLinks = await strapi.db.query("plugin::primershop-status-manager.status-link").findMany({
373
- where: {
374
- targetUid: uid,
375
- status: status.id
376
- },
377
- select: [
378
- "targetDocumentId"
379
- ]
301
+ populate: {
302
+ status: true
303
+ },
304
+ where: {
305
+ targetUid: uid,
306
+ targetDocumentId: { $in: documentIds }
307
+ }
380
308
  });
381
- const allowedDocumentIds = statusLinks.map((link)=>link.targetDocumentId);
382
- context.params["filters"] = {
383
- ...context.params["filters"],
384
- documentId: {
385
- $in: allowedDocumentIds
386
- }
387
- };
388
- return next();
389
- });
390
-
391
- var filterPublished = (async (context, next)=>{
392
- const uid = context.uid;
393
- if (!uid.includes("api::")) {
394
- return next();
309
+ if (Array.isArray(result)) {
310
+ result.forEach((doc) => {
311
+ doc.statusField = statusLinks.find((link) => link.targetDocumentId === doc.documentId)?.status || void 0;
312
+ });
395
313
  }
396
- const params = context.params;
397
- if (!params && !params["status"] || params["statusName"]) return next();
398
- const unpublishedStatusLinks = await strapi.db.query("plugin::primershop-status-manager.status-link").findMany({
399
- populate: {
400
- status: true
401
- },
402
- where: {
403
- targetUid: uid,
404
- status: {
405
- published: false
406
- }
407
- },
408
- select: [
409
- "targetDocumentId"
410
- ]
411
- });
412
- const unpublishedDocumentIds = unpublishedStatusLinks.map((link)=>link.targetDocumentId);
413
- context.params["filters"] = {
414
- ...context.params["filters"],
415
- documentId: {
416
- $notIn: unpublishedDocumentIds
417
- }
418
- };
314
+ if (result && typeof result === "object") {
315
+ result.statusField = statusLinks.find(
316
+ (link) => link.targetDocumentId === result.documentId
317
+ )?.status || void 0;
318
+ }
319
+ } catch (error) {
320
+ console.error("primershop-status-manager: status enrichment error", error);
321
+ }
322
+ return result;
323
+ };
324
+ const filterByStatus = async (context, next) => {
325
+ const uid = context.uid;
326
+ if (!uid.includes("api::")) {
419
327
  return next();
420
- });
421
-
422
- const register = ({ strapi })=>{
423
- strapi.customFields.register({
424
- name: "statusName",
425
- plugin: PLUGIN_ID,
426
- type: "string"
427
- });
428
- strapi.documents.use(filterByStatus);
429
- strapi.documents.use(addStatusField);
430
- strapi.documents.use(filterPublished);
328
+ }
329
+ const paramKeys = Object.keys(context.params || {});
330
+ if (!paramKeys.includes("statusName")) {
331
+ return next();
332
+ }
333
+ const desiredStatus = context.params["statusName"];
334
+ if (!desiredStatus || desiredStatus === "all") return next();
335
+ const isValid = await strapi.plugin("primershop-status-manager").service("status").isValidStatus(desiredStatus);
336
+ if (!isValid)
337
+ throw new utils.errors.ValidationError(`Invalid status: ${desiredStatus}`);
338
+ const status2 = await strapi.plugin("primershop-status-manager").service("status").getStatusByName(desiredStatus);
339
+ if (!status2) {
340
+ throw new utils.errors.ValidationError(`Status not found: ${desiredStatus}`);
341
+ }
342
+ const statusLinks = await strapi.db.query("plugin::primershop-status-manager.status-link").findMany({
343
+ where: {
344
+ targetUid: uid,
345
+ status: status2.id
346
+ },
347
+ select: ["targetDocumentId"]
348
+ });
349
+ const allowedDocumentIds = statusLinks.map((link) => link.targetDocumentId);
350
+ context.params["filters"] = {
351
+ ...context.params["filters"],
352
+ documentId: { $in: allowedDocumentIds }
353
+ };
354
+ return next();
431
355
  };
432
-
433
- var statusManagement = [
434
- {
435
- method: "GET",
436
- path: "/statuses",
437
- handler: "status_controller.listStatuses",
438
- config: {
439
- policies: [
440
- {
441
- name: "admin::hasPermissions",
442
- config: {
443
- actions: [
444
- "plugin::primershop-status-manager.status.read"
445
- ]
446
- }
447
- }
448
- ]
449
- },
450
- description: "Get all statuses",
451
- tag: {
452
- plugin: "primershop-status-manager",
453
- name: "statuses",
454
- actionType: "findMany"
455
- }
356
+ const filterPublished = async (context, next) => {
357
+ const uid = context.uid;
358
+ if (!uid.includes("api::")) {
359
+ return next();
360
+ }
361
+ const params = context.params;
362
+ if (!params && !params["status"] || params["statusName"]) return next();
363
+ const unpublishedStatusLinks = await strapi.db.query("plugin::primershop-status-manager.status-link").findMany({
364
+ populate: {
365
+ status: true
456
366
  },
457
- {
458
- method: "POST",
459
- path: "/status",
460
- handler: "status_controller.create",
461
- config: {
462
- policies: [
463
- {
464
- name: "admin::hasPermissions",
465
- config: {
466
- actions: [
467
- "plugin::primershop-status-manager.status.create"
468
- ]
469
- }
470
- }
471
- ]
472
- },
473
- description: "Create a new status",
474
- tag: {
475
- plugin: "primershop-status-manager",
476
- name: "Status",
477
- actionType: "create"
478
- }
367
+ where: {
368
+ targetUid: uid,
369
+ status: {
370
+ published: false
371
+ }
479
372
  },
480
- {
481
- method: "PUT",
482
- path: "/statuses/reorder",
483
- handler: "status_controller.reorder",
484
- config: {
485
- policies: [
486
- {
487
- name: "admin::hasPermissions",
488
- config: {
489
- actions: [
490
- "plugin::primershop-status-manager.status.update"
491
- ]
492
- }
493
- }
494
- ],
495
- description: "Reorder statuses",
496
- tag: {
497
- plugin: "primershop-status-manager",
498
- name: "Status",
499
- actionType: "update"
500
- }
373
+ select: ["targetDocumentId"]
374
+ });
375
+ const unpublishedDocumentIds = unpublishedStatusLinks.map(
376
+ (link) => link.targetDocumentId
377
+ );
378
+ context.params["filters"] = {
379
+ ...context.params["filters"],
380
+ documentId: { $notIn: unpublishedDocumentIds }
381
+ };
382
+ return next();
383
+ };
384
+ const register = ({ strapi: strapi2 }) => {
385
+ strapi2.customFields.register({
386
+ name: "statusName",
387
+ plugin: PLUGIN_ID,
388
+ type: "string"
389
+ });
390
+ strapi2.documents.use(filterByStatus);
391
+ strapi2.documents.use(addStatusField);
392
+ strapi2.documents.use(filterPublished);
393
+ };
394
+ const statusManagement = [
395
+ {
396
+ method: "GET",
397
+ path: "/statuses",
398
+ handler: "status_controller.listStatuses",
399
+ config: {
400
+ policies: [
401
+ {
402
+ name: "admin::hasPermissions",
403
+ config: {
404
+ actions: ["plugin::primershop-status-manager.status.read"]
405
+ }
501
406
  }
407
+ ]
502
408
  },
503
- {
504
- method: "PUT",
505
- path: "/statuses/delete",
506
- handler: "status_controller.delete",
507
- config: {
508
- policies: [
509
- {
510
- name: "admin::hasPermissions",
511
- config: {
512
- actions: [
513
- "plugin::primershop-status-manager.status.delete"
514
- ]
515
- }
516
- }
517
- ],
518
- description: "Delete a status",
519
- tag: {
520
- plugin: "primershop-status-manager",
521
- name: "Status",
522
- actionType: "delete"
523
- }
409
+ description: "Get all statuses",
410
+ tag: {
411
+ plugin: "primershop-status-manager",
412
+ name: "statuses",
413
+ actionType: "findMany"
414
+ }
415
+ },
416
+ {
417
+ method: "POST",
418
+ path: "/status",
419
+ handler: "status_controller.create",
420
+ config: {
421
+ policies: [
422
+ {
423
+ name: "admin::hasPermissions",
424
+ config: {
425
+ actions: ["plugin::primershop-status-manager.status.create"]
426
+ }
524
427
  }
428
+ ]
525
429
  },
526
- {
527
- method: "PUT",
528
- path: "/statuses/:id",
529
- handler: "status_controller.publish",
530
- config: {
531
- policies: [
532
- {
533
- name: "admin::hasPermissions",
534
- config: {
535
- actions: [
536
- "plugin::primershop-status-manager.status.update"
537
- ]
538
- }
539
- }
540
- ],
541
- description: "Update status publish state",
542
- tag: {
543
- plugin: "primershop-status-manager",
544
- name: "Status",
545
- actionType: "update"
546
- }
430
+ description: "Create a new status",
431
+ tag: {
432
+ plugin: "primershop-status-manager",
433
+ name: "Status",
434
+ actionType: "create"
435
+ }
436
+ },
437
+ {
438
+ method: "PUT",
439
+ path: "/statuses/reorder",
440
+ handler: "status_controller.reorder",
441
+ config: {
442
+ policies: [
443
+ {
444
+ name: "admin::hasPermissions",
445
+ config: {
446
+ actions: ["plugin::primershop-status-manager.status.update"]
447
+ }
547
448
  }
449
+ ],
450
+ description: "Reorder statuses",
451
+ tag: {
452
+ plugin: "primershop-status-manager",
453
+ name: "Status",
454
+ actionType: "update"
455
+ }
548
456
  }
549
- ];
550
-
551
- var contentManagement = [
552
- {
553
- method: "GET",
554
- path: "/content-status",
555
- handler: "content_controller.getStatusForTarget",
556
- config: {
557
- policies: [
558
- {
559
- name: "admin::hasPermissions",
560
- config: {
561
- actions: [
562
- "plugin::primershop-status-manager.status.read"
563
- ]
564
- }
565
- }
566
- ]
457
+ },
458
+ {
459
+ method: "PUT",
460
+ path: "/statuses/delete",
461
+ handler: "status_controller.delete",
462
+ config: {
463
+ policies: [
464
+ {
465
+ name: "admin::hasPermissions",
466
+ config: {
467
+ actions: ["plugin::primershop-status-manager.status.delete"]
468
+ }
567
469
  }
568
- },
569
- {
570
- method: "PUT",
571
- path: "/content-status",
572
- handler: "content_controller.setStatusForTarget",
573
- config: {
574
- policies: [
575
- {
576
- name: "admin::hasPermissions",
577
- config: {
578
- actions: [
579
- "plugin::primershop-status-manager.status.update"
580
- ]
581
- }
582
- }
583
- ]
470
+ ],
471
+ description: "Delete a status",
472
+ tag: {
473
+ plugin: "primershop-status-manager",
474
+ name: "Status",
475
+ actionType: "delete"
476
+ }
477
+ }
478
+ },
479
+ {
480
+ method: "PUT",
481
+ path: "/statuses/:id",
482
+ handler: "status_controller.publish",
483
+ config: {
484
+ policies: [
485
+ {
486
+ name: "admin::hasPermissions",
487
+ config: {
488
+ actions: ["plugin::primershop-status-manager.status.update"]
489
+ }
584
490
  }
491
+ ],
492
+ description: "Update status publish state",
493
+ tag: {
494
+ plugin: "primershop-status-manager",
495
+ name: "Status",
496
+ actionType: "update"
497
+ }
585
498
  }
499
+ }
586
500
  ];
587
-
588
- var routes = {
589
- admin: {
590
- type: "admin",
591
- routes: [
592
- ...statusManagement,
593
- ...contentManagement
594
- ]
501
+ const contentManagement = [
502
+ {
503
+ method: "GET",
504
+ path: "/content-status",
505
+ handler: "content_controller.getStatusForTarget",
506
+ config: {
507
+ policies: [
508
+ {
509
+ name: "admin::hasPermissions",
510
+ config: {
511
+ actions: ["plugin::primershop-status-manager.status.read"]
512
+ }
513
+ }
514
+ ]
595
515
  }
596
- };
597
-
598
- const statusService = ({ strapi })=>({
599
- async isValidStatus (code) {
600
- try {
601
- const row = await strapi.db.query("plugin::primershop-status-manager.status").findOne({
602
- where: {
603
- name: code
604
- },
605
- select: [
606
- "id"
607
- ]
608
- });
609
- return !!row;
610
- } catch {
611
- return false;
612
- }
613
- },
614
- async getStatusByName (name) {
615
- return strapi.db.query("plugin::primershop-status-manager.status").findOne({
616
- where: {
617
- name
618
- }
619
- });
620
- },
621
- isStatusEnabledFor (uid) {
622
- return !!strapi.getModel(uid);
623
- },
624
- async find () {
625
- const result = await strapi.db.query("plugin::primershop-status-manager.status").findMany({
626
- orderBy: {
627
- order: "asc"
628
- }
629
- });
630
- return result;
631
- },
632
- async findOne (id) {
633
- const result = await strapi.db.query("plugin::primershop-status-manager.status").findOne({
634
- where: {
635
- id
636
- }
637
- });
638
- return result;
639
- },
640
- async createStatus (data) {
641
- const result = await strapi.db.query("plugin::primershop-status-manager.status").create({
642
- data: {
643
- name: data.name,
644
- published: data.published ?? false,
645
- order: data.order ?? 0
646
- }
647
- });
648
- return result;
649
- },
650
- async findProductsByStatus (statusId) {
651
- return strapi.db.query("api::product.product").findMany({
652
- where: {
653
- status: statusId
654
- }
655
- });
656
- },
657
- async updateProductStatus (productId, statusId) {
658
- return strapi.db.query("api::product.product").update({
659
- where: {
660
- id: productId
661
- },
662
- data: {
663
- status: statusId
664
- }
665
- });
666
- },
667
- async delete (id) {
668
- return strapi.db.query("plugin::primershop-status-manager.status").delete({
669
- where: {
670
- id
671
- }
672
- });
673
- },
674
- async deleteStatus (statusId, replacementId) {
675
- // Find status by documentId
676
- const status = await strapi.db.query("plugin::primershop-status-manager.status").findOne({
677
- where: {
678
- documentId: statusId
679
- }
680
- });
681
- if (!status) {
682
- throw new Error("Status not found");
683
- }
684
- if (replacementId) {
685
- const replacementStatus = await strapi.db.query("plugin::primershop-status-manager.status").findOne({
686
- where: {
687
- documentId: replacementId
688
- }
689
- });
690
- if (!replacementStatus) {
691
- throw new Error("Replacement status not found");
692
- }
693
- }
694
- // Delete the status
695
- await strapi.db.query("plugin::primershop-status-manager.status").delete({
696
- where: {
697
- documentId: statusId
698
- }
699
- });
700
- return true;
516
+ },
517
+ {
518
+ method: "PUT",
519
+ path: "/content-status",
520
+ handler: "content_controller.setStatusForTarget",
521
+ config: {
522
+ policies: [
523
+ {
524
+ name: "admin::hasPermissions",
525
+ config: {
526
+ actions: ["plugin::primershop-status-manager.status.update"]
527
+ }
701
528
  }
529
+ ]
530
+ }
531
+ }
532
+ ];
533
+ const routes = {
534
+ admin: {
535
+ type: "admin",
536
+ routes: [...statusManagement, ...contentManagement]
537
+ }
538
+ };
539
+ const statusService = ({ strapi: strapi2 }) => ({
540
+ async isValidStatus(code) {
541
+ try {
542
+ const row = await strapi2.db.query("plugin::primershop-status-manager.status").findOne({ where: { name: code }, select: ["id"] });
543
+ return !!row;
544
+ } catch {
545
+ return false;
546
+ }
547
+ },
548
+ async getStatusByName(name) {
549
+ return strapi2.db.query("plugin::primershop-status-manager.status").findOne({ where: { name } });
550
+ },
551
+ isStatusEnabledFor(uid) {
552
+ return !!strapi2.getModel(uid);
553
+ },
554
+ async find() {
555
+ const result = await strapi2.db.query("plugin::primershop-status-manager.status").findMany({
556
+ orderBy: { order: "asc" }
557
+ });
558
+ return result;
559
+ },
560
+ async findOne(id) {
561
+ const result = await strapi2.db.query("plugin::primershop-status-manager.status").findOne({
562
+ where: { id }
563
+ });
564
+ return result;
565
+ },
566
+ async createStatus(data) {
567
+ const result = await strapi2.db.query("plugin::primershop-status-manager.status").create({
568
+ data: {
569
+ name: data.name,
570
+ published: data.published ?? false,
571
+ order: data.order ?? 0
572
+ }
573
+ });
574
+ return result;
575
+ },
576
+ async findProductsByStatus(statusId) {
577
+ return strapi2.db.query("api::product.product").findMany({
578
+ where: { status: statusId }
702
579
  });
703
-
704
- const statusLinkService = ({ strapi })=>({
705
- async getForTarget (targetUid, targetDocumentId) {
706
- const link = await strapi.db.query("plugin::primershop-status-manager.status-link").findOne({
707
- where: {
708
- targetUid,
709
- targetDocumentId
710
- },
711
- populate: {
712
- status: true
713
- }
714
- });
715
- return link ?? null;
716
- },
717
- async setForTarget (targetUid, targetDocumentId, statusDocumentId) {
718
- // Create status link
719
- await strapi.db.query("plugin::primershop-status-manager.status-link").deleteMany({
720
- where: {
721
- targetUid,
722
- targetDocumentId
723
- }
724
- });
725
- const created = await strapi.documents("plugin::primershop-status-manager.status-link").create({
726
- data: {
727
- targetUid,
728
- targetDocumentId,
729
- status: {
730
- set: statusDocumentId
731
- }
732
- }
733
- });
734
- return created;
580
+ },
581
+ async updateProductStatus(productId, statusId) {
582
+ return strapi2.db.query("api::product.product").update({
583
+ where: { id: productId },
584
+ data: { status: statusId }
585
+ });
586
+ },
587
+ async delete(id) {
588
+ return strapi2.db.query("plugin::primershop-status-manager.status").delete({
589
+ where: { id }
590
+ });
591
+ },
592
+ async deleteStatus(statusId, replacementId) {
593
+ const status2 = await strapi2.db.query("plugin::primershop-status-manager.status").findOne({
594
+ where: { documentId: statusId }
595
+ });
596
+ if (!status2) {
597
+ throw new Error("Status not found");
598
+ }
599
+ if (replacementId) {
600
+ const replacementStatus = await strapi2.db.query("plugin::primershop-status-manager.status").findOne({
601
+ where: { documentId: replacementId }
602
+ });
603
+ if (!replacementStatus) {
604
+ throw new Error("Replacement status not found");
605
+ }
606
+ }
607
+ await strapi2.db.query("plugin::primershop-status-manager.status").delete({
608
+ where: { documentId: statusId }
609
+ });
610
+ return true;
611
+ }
612
+ });
613
+ const statusLinkService = ({ strapi: strapi2 }) => ({
614
+ async getForTarget(targetUid, targetDocumentId) {
615
+ const link = await strapi2.db.query("plugin::primershop-status-manager.status-link").findOne({
616
+ where: { targetUid, targetDocumentId },
617
+ populate: { status: true }
618
+ });
619
+ return link ?? null;
620
+ },
621
+ async setForTarget(targetUid, targetDocumentId, statusDocumentId) {
622
+ await strapi2.db.query("plugin::primershop-status-manager.status-link").deleteMany({ where: { targetUid, targetDocumentId } });
623
+ const created = await strapi2.documents("plugin::primershop-status-manager.status-link").create({
624
+ data: {
625
+ targetUid,
626
+ targetDocumentId,
627
+ status: {
628
+ set: statusDocumentId
735
629
  }
630
+ }
736
631
  });
737
-
738
- var services = {
739
- status: statusService,
740
- statusLink: statusLinkService
632
+ return created;
633
+ }
634
+ });
635
+ const services = {
636
+ status: statusService,
637
+ statusLink: statusLinkService
638
+ };
639
+ const destroy = ({ strapi: strapi2 }) => {
741
640
  };
742
-
743
- var index = {
744
- register,
745
- controllers,
746
- contentTypes,
747
- routes,
748
- services,
749
- bootstrap
641
+ const index = {
642
+ register,
643
+ bootstrap,
644
+ destroy,
645
+ controllers,
646
+ contentTypes,
647
+ routes,
648
+ services
750
649
  };
751
-
752
650
  module.exports = index;