@raketa-cloud/admin 1.8.9 → 1.8.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.
Files changed (106) hide show
  1. package/dist/application.css +113 -24
  2. package/package.json +5 -3
  3. package/src/HonoAdapter.js +23 -23
  4. package/src/Logger.js +7 -8
  5. package/src/RaketaContext.js +1 -0
  6. package/src/cipher.js +2 -2
  7. package/src/cloud/ContentTasks.js +31 -0
  8. package/src/cloud/RaketaClient.js +1 -1
  9. package/src/cloud/Redirects.js +2 -2
  10. package/src/cloud/ResourceChanges.js +1 -1
  11. package/src/cloud/ResourceRevisions.js +2 -2
  12. package/src/cloud/Resources.js +28 -12
  13. package/src/cloud/Tags.js +4 -4
  14. package/src/cloud/documents/common.js +16 -0
  15. package/src/cloud/documents/contentTasksDocuments.js +59 -0
  16. package/src/cloud/documents/resourcesDocuments.js +12 -0
  17. package/src/filters.js +3 -3
  18. package/src/handlers/TagsHandler.js +2 -2
  19. package/src/handlers/_shared/getResourceUpdateDestination.js +1 -1
  20. package/src/handlers/categories/index.js +3 -3
  21. package/src/handlers/content_tasks/ContentTasksHandler.js +32 -0
  22. package/src/handlers/resource_revisions/LocksHandler.js +4 -1
  23. package/src/handlers/resources/ClonesHandler.js +1 -3
  24. package/src/handlers/resources/ExportsHandler.js +1 -5
  25. package/src/handlers/resources/ResourcesHandler.js +1 -1
  26. package/src/handlers/resources/TranslationsHandler.js +28 -19
  27. package/src/handlers/resources/URLsHandler.js +3 -1
  28. package/src/helpers/AuthHelper.js +1 -1
  29. package/src/helpers/FormBuilder.js +14 -14
  30. package/src/helpers/Pagination.js +5 -5
  31. package/src/helpers/historyUtils.js +3 -3
  32. package/src/helpers/utils.js +6 -1
  33. package/src/index.js +2 -1
  34. package/src/routeMember.js +9 -4
  35. package/src/routeNestedCollection.js +14 -29
  36. package/src/routeNestedMember.js +17 -6
  37. package/src/{routeResource.js → routeResourceModule.js} +25 -20
  38. package/src/routeStandard.js +8 -4
  39. package/src/setupAuthentication.js +1 -1
  40. package/src/setupCloud.js +5 -0
  41. package/src/tests/Adapter.test.js +2 -2
  42. package/src/tests/HonoAdapter.coverage.test.js +47 -25
  43. package/src/tests/HonoAdapter.filter.test.js +28 -18
  44. package/src/tests/HonoAdapter.test.js +3 -3
  45. package/src/tests/RaketaClient.test.js +427 -413
  46. package/src/tests/RaketaContext.test.js +1 -1
  47. package/src/tests/buildResourcePath.test.js +1 -1
  48. package/src/tests/cipher.test.js +16 -16
  49. package/src/tests/filters.test.js +24 -24
  50. package/src/tests/handlers/RedirectsHandler.test/destroy.test.js +1 -1
  51. package/src/tests/handlers/TagsHandler.test/create.test.js +2 -2
  52. package/src/tests/handlers/TagsHandler.test/destroy.test.js +1 -1
  53. package/src/tests/handlers/TagsHandler.test/update.test.js +2 -2
  54. package/src/tests/handlers/categories/create.test.js +2 -2
  55. package/src/tests/handlers/categories/destroy.test.js +1 -1
  56. package/src/tests/handlers/content_tasks/ContentTasksHandler.test/index.test.js +161 -0
  57. package/src/tests/handlers/resource_revisions/CancelSchedulesHandler.test/create.test.js +2 -2
  58. package/src/tests/handlers/resource_revisions/CodeHandler.test/update.test.js +1 -1
  59. package/src/tests/handlers/resource_revisions/GeneralHandler.test/update.test.js +1 -1
  60. package/src/tests/handlers/resource_revisions/LocksHandler.test/create.test.js +5 -5
  61. package/src/tests/handlers/resource_revisions/LocksHandler.test/create_form.test.js +6 -2
  62. package/src/tests/handlers/resource_revisions/MetaHandler.test/update.test.js +1 -1
  63. package/src/tests/handlers/resource_revisions/PublishesHandler.test/create.test.js +5 -5
  64. package/src/tests/handlers/resource_revisions/ResourceRevisionsHandler.test/create.test.js +2 -2
  65. package/src/tests/handlers/resource_revisions/ResourceRevisionsHandler.test/destroy.test.js +1 -1
  66. package/src/tests/handlers/resource_revisions/RevertsHandler.test/create.test.js +18 -3
  67. package/src/tests/handlers/resource_revisions/TagHandler.test/update.test.js +1 -1
  68. package/src/tests/handlers/resource_revisions/UnlocksHandler.test/create.test.js +2 -2
  69. package/src/tests/handlers/resource_revisions/VisualHandler.test/update.test.js +1 -1
  70. package/src/tests/handlers/resource_revisions/WidgetHandler.test/update.test.js +2 -2
  71. package/src/tests/handlers/resources/ChangeHandler.test/show.test.js +7 -2
  72. package/src/tests/handlers/resources/ClonesHandler.test/create.test.js +1 -3
  73. package/src/tests/handlers/resources/ExportsHandler.test/index.test.js +8 -8
  74. package/src/tests/handlers/resources/HistoryHandler.test/index.test.js +1 -1
  75. package/src/tests/handlers/resources/ResourcesAPIHandler.test/index.test.js +1 -5
  76. package/src/tests/handlers/resources/ResourcesHandler.test/create.test.js +2 -2
  77. package/src/tests/handlers/resources/ResourcesHandler.test/show.test.js +1 -1
  78. package/src/tests/handlers/resources/TranslationsHandler.test/create.test.js +24 -14
  79. package/src/tests/handlers/resources/TranslationsHandler.test/create_form.test.js +1 -1
  80. package/src/tests/handlers/resources/TranslationsHandler.test/index.test.js +3 -3
  81. package/src/tests/handlers/resources/URLsHandler.test/create.test.js +4 -6
  82. package/src/tests/helpers/AuthHelper.test.js +11 -12
  83. package/src/tests/helpers/CSVExportHelper.test.js +3 -3
  84. package/src/tests/helpers/FormBuilder.test.js +21 -21
  85. package/src/tests/helpers/HTMLBuilder.test.js +4 -4
  86. package/src/tests/helpers/Inflector.test.js +1 -1
  87. package/src/tests/helpers/Pagination.test.js +1 -1
  88. package/src/tests/helpers/utils.test.js +46 -0
  89. package/src/tests/routeCategoriesModule.test.js +10 -5
  90. package/src/tests/routeCollection.test.js +1 -1
  91. package/src/tests/routeMember.test.js +2 -2
  92. package/src/tests/routeNestedCollection.test.js +3 -3
  93. package/src/tests/routeNestedMember.test.js +3 -3
  94. package/src/tests/{routeResource.test.js → routeResourceModule.test.js} +28 -25
  95. package/src/tests/routeSettings.test.js +3 -3
  96. package/src/tests/routeStandard.test.js +31 -13
  97. package/src/tests/setupAuthentication.test.js +9 -6
  98. package/src/tests/support/factory.js +33 -0
  99. package/src/tests/utils.test.js +19 -19
  100. package/src/views/content_tasks/index.ejs +191 -0
  101. package/src/views/layouts/application.ejs +2 -1
  102. package/src/views/resources/_shared/_toolbar.ejs +33 -2
  103. package/src/views/resources/_shared/_translations_strip.ejs +71 -0
  104. package/src/views/resources/index.ejs +5 -0
  105. package/src/views/resources/show.ejs +1 -29
  106. package/src/views/resources/translations/create_form.ejs +13 -0
@@ -0,0 +1,59 @@
1
+ import { gql } from "graphql-request";
2
+
3
+ /**
4
+ * Query to fetch all content tasks with filters
5
+ */
6
+ export const ContentTasksDocument = gql`
7
+ query ContentTasks($input: ContentTasksInput) {
8
+ contentTasks(input: $input) {
9
+ list {
10
+ id
11
+ workflow
12
+ operator
13
+ operatorMeta
14
+ completedAt
15
+ failedAt
16
+ rejectedAt
17
+ insertedAt
18
+ updatedAt
19
+ resource {
20
+ id
21
+ title
22
+ slug
23
+ locale
24
+ visibility
25
+ resourceType
26
+ insertedAt
27
+ updatedAt
28
+ }
29
+ lokaliseWorkflow {
30
+ id
31
+ status
32
+ settings
33
+ insertedAt
34
+ updatedAt
35
+ }
36
+ }
37
+ pagination {
38
+ currentPage
39
+ pagesCount
40
+ entriesCount
41
+ pageSize
42
+ }
43
+ }
44
+ }
45
+ `;
46
+
47
+ /**
48
+ * Query to fetch unique editors/operators for filtering
49
+ */
50
+ export const ContentTaskEditorsDocument = gql`
51
+ query ContentTaskEditors {
52
+ contentTaskEditors {
53
+ list {
54
+ id
55
+ name
56
+ }
57
+ }
58
+ }
59
+ `;
@@ -1,6 +1,7 @@
1
1
  import { gql } from "graphql-request";
2
2
  import {
3
3
  categoryFragment,
4
+ contentTaskFragment,
4
5
  errorsFragment,
5
6
  paginationFragment,
6
7
  revisionMetaFragment,
@@ -42,6 +43,17 @@ function resourceFragment() {
42
43
  tags ${tagFragment()}
43
44
  categories ${categoryFragment()}
44
45
  changes ${summaryChangeFragment()}
46
+ activeContentTask {
47
+ id
48
+ workflow
49
+ operator
50
+ operatorMeta
51
+ completedAt
52
+ failedAt
53
+ rejectedAt
54
+ insertedAt
55
+ updatedAt
56
+ }
45
57
  }
46
58
  `;
47
59
  }
package/src/filters.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * @param {RegExp} pattern - Route pattern to match
5
5
  * @param {Function} filter - The filter function
6
6
  */
7
- export const setBeforeFilter = (adapter, pattern, filter) =>
7
+ export const setBeforeFilter = (adapter, pattern, filter) =>
8
8
  adapter.setBeforeFilter(pattern, filter);
9
9
 
10
10
  /**
@@ -13,5 +13,5 @@ export const setBeforeFilter = (adapter, pattern, filter) =>
13
13
  * @param {RegExp} pattern - Route pattern to match
14
14
  * @param {Function} filter - The filter function
15
15
  */
16
- export const setAfterFilter = (adapter, pattern, filter) =>
17
- adapter.setAfterFilter(pattern, filter);
16
+ export const setAfterFilter = (adapter, pattern, filter) =>
17
+ adapter.setAfterFilter(pattern, filter);
@@ -40,7 +40,7 @@ const create = async (ctx) => {
40
40
  name: params.name,
41
41
  slug: params.slug,
42
42
  },
43
- ctx.locale
43
+ ctx.locale,
44
44
  );
45
45
 
46
46
  if (errors) {
@@ -68,7 +68,7 @@ const update = async (ctx) => {
68
68
  name: params.name,
69
69
  slug: params.slug,
70
70
  },
71
- ctx.locale
71
+ ctx.locale,
72
72
  );
73
73
 
74
74
  if (errors) {
@@ -1,7 +1,7 @@
1
1
  export default function getResourceUpdateDestination(
2
2
  ctx,
3
3
  revision_id,
4
- section
4
+ section,
5
5
  ) {
6
6
  const base = `/${ctx.locale}/${ctx.resourceConfig.resourceType}_revisions/${revision_id}/`;
7
7
  const shouldPublish = ctx.body && ctx.body._next === "publish";
@@ -2,7 +2,7 @@ const index = async (ctx) => {
2
2
  const items = await ctx.client.categories.list(
3
3
  ctx.query,
4
4
  ctx.locale,
5
- ctx.resourceConfig.categoryType
5
+ ctx.resourceConfig.categoryType,
6
6
  );
7
7
 
8
8
  return {
@@ -29,7 +29,7 @@ const create = async (ctx) => {
29
29
  const { errors } = await ctx.client.categories.create(
30
30
  resource,
31
31
  ctx.locale,
32
- ctx.resourceConfig.categoryType
32
+ ctx.resourceConfig.categoryType,
33
33
  );
34
34
 
35
35
  if (errors) {
@@ -77,7 +77,7 @@ const update = async (ctx) => {
77
77
  settings: params.settings || {},
78
78
  },
79
79
  ctx.locale,
80
- ctx.resourceConfig.categoryType
80
+ ctx.resourceConfig.categoryType,
81
81
  );
82
82
 
83
83
  if (errors) {
@@ -0,0 +1,32 @@
1
+ function buildResourceUrl(resource, resourceRoutes) {
2
+ if (!resource) return "#";
3
+
4
+ const { locale, resourceType, id } = resource;
5
+
6
+ const route = resourceRoutes[resourceType];
7
+
8
+ return `/${locale}/${route}/${id}`;
9
+ }
10
+
11
+ async function index(ctx) {
12
+ const items = await ctx.client.contentTasks.list(ctx.query);
13
+ const editors = await ctx.client.contentTasks.editors();
14
+ const resourceRoutes = ctx.globalConfig.resourceRoutes;
15
+
16
+ if (!resourceRoutes) {
17
+ throw new Error("Missing resourceRoutes in the admin config!");
18
+ }
19
+
20
+ return {
21
+ assigns: {
22
+ items,
23
+ editors: editors.list || [],
24
+ buildResourceUrl: (resource) =>
25
+ buildResourceUrl(resource, resourceRoutes),
26
+ },
27
+ };
28
+ }
29
+
30
+ export default {
31
+ index,
32
+ };
@@ -58,7 +58,10 @@ const create = async (ctx) => {
58
58
  message,
59
59
  },
60
60
  errors: {
61
- resource: ctx.client.resourceRevisions.formatErrors(errors, "message"),
61
+ resource: ctx.client.resourceRevisions.formatErrors(
62
+ errors,
63
+ "message",
64
+ ),
62
65
  },
63
66
  _translations: [],
64
67
  },
@@ -9,9 +9,7 @@ const create = async (ctx) => {
9
9
  );
10
10
 
11
11
  if (errors) {
12
- throw new Error(
13
- `Error cloning ${resourceType}: ${JSON.stringify(errors)}`,
14
- );
12
+ throw new Error(`Error cloning ${resourceType}: ${JSON.stringify(errors)}`);
15
13
  }
16
14
 
17
15
  return {
@@ -5,11 +5,7 @@ const exportCSV = async (ctx) => {
5
5
  const { resourceType } = resourceConfig;
6
6
  const locale = query.locale || "en";
7
7
 
8
- const pages = await client.resources.listAll(
9
- query,
10
- locale,
11
- resourceType,
12
- );
8
+ const pages = await client.resources.listAll(query, locale, resourceType);
13
9
 
14
10
  const fieldMapping = CSVExportHelper.standardFieldMapping(
15
11
  remoteConfig,
@@ -7,7 +7,6 @@ const index = async (ctx) => {
7
7
  resourceType,
8
8
  );
9
9
 
10
-
11
10
  const tags = await ctx.client.tags.all(ctx.locale);
12
11
  const languages = ctx.client.resources.getConfig().i18n.locales;
13
12
  const translations = Object.keys(languages).map((key) => ({
@@ -44,6 +43,7 @@ const show = async (ctx) => {
44
43
  ctx.locale,
45
44
  resourceType,
46
45
  );
46
+
47
47
  const changes = await ctx.client.resourceChanges.list(
48
48
  {
49
49
  "f:change_type": [
@@ -150,11 +150,14 @@ const create = async (ctx) => {
150
150
 
151
151
  const translationIds = [];
152
152
 
153
+ const workflow = ctx.resourceParams?.resource?.workflow;
154
+
153
155
  const translations = await ctx.client.resources.translateBatch(
154
156
  parent_id,
155
157
  selectedLocales,
156
158
  resource,
157
159
  resourceType,
160
+ workflow,
158
161
  );
159
162
 
160
163
  if (!translations) {
@@ -226,31 +229,37 @@ const create = async (ctx) => {
226
229
  }
227
230
  }
228
231
 
229
- const revisionResults =
230
- await ctx.client.resourceRevisions.createBatch(revisionInputs);
232
+ if (!workflow) {
233
+ const revisionResults =
234
+ await ctx.client.resourceRevisions.createBatch(revisionInputs);
231
235
 
232
- for (let i = 0; i < revisionResults.length; i++) {
233
- const { errors: revisionErrors } = revisionResults[i];
234
- if (revisionErrors) {
235
- return {
236
- assigns: {
237
- resource: {
238
- ...resource,
239
- translations: blueprint.translations || {},
240
- languages: formLanguages,
241
- },
242
- blueprint,
243
- targetLocale: selectedLocales[i],
244
- errors: {
245
- resource: ctx.client.resources.formatErrors(revisionErrors),
236
+ for (let i = 0; i < revisionResults.length; i++) {
237
+ const { errors: revisionErrors } = revisionResults[i];
238
+ if (revisionErrors) {
239
+ return {
240
+ assigns: {
241
+ resource: {
242
+ ...resource,
243
+ translations: blueprint.translations || {},
244
+ languages: formLanguages,
245
+ },
246
+ blueprint,
247
+ targetLocale: selectedLocales[i],
248
+ errors: {
249
+ resource: ctx.client.resources.formatErrors(revisionErrors),
250
+ },
246
251
  },
247
- },
248
- };
252
+ };
253
+ }
249
254
  }
255
+
256
+ return {
257
+ redirect: `/${originalLocale}/${resourceTypePlural}/${parent_id}/translations?translations=${translationIds.join(";")}`,
258
+ };
250
259
  }
251
260
 
252
261
  return {
253
- redirect: `/${originalLocale}/${resourceTypePlural}/${parent_id}/translations?translations=${translationIds.join(";")}`,
262
+ redirect: `/${originalLocale}/${resourceTypePlural}/${parent_id}`,
254
263
  };
255
264
  };
256
265
 
@@ -67,7 +67,9 @@ const create = async (ctx) => {
67
67
  return {
68
68
  assigns: {
69
69
  resource: { ...resource, id: record.id },
70
- errors: { resource: ctx.client.resources.formatErrors(errors, "redirect") },
70
+ errors: {
71
+ resource: ctx.client.resources.formatErrors(errors, "redirect"),
72
+ },
71
73
  _translations: [],
72
74
  },
73
75
  };
@@ -4,7 +4,7 @@ const AuthHelper = {
4
4
  parseJWT: (token) => {
5
5
  const tokenPayload = token?.split(".")?.[1];
6
6
 
7
- if(!tokenPayload){
7
+ if (!tokenPayload) {
8
8
  return "";
9
9
  }
10
10
 
@@ -127,7 +127,7 @@ export default class FormBuilder extends HTMLBuilder {
127
127
 
128
128
  return this.withHint(
129
129
  this.tag("input", null, { type: "text", name, value, ...rest }),
130
- hint
130
+ hint,
131
131
  );
132
132
  }
133
133
 
@@ -142,9 +142,9 @@ export default class FormBuilder extends HTMLBuilder {
142
142
  name,
143
143
  ...rest,
144
144
  },
145
- { nonVoid: true }
145
+ { nonVoid: true },
146
146
  ),
147
- hint
147
+ hint,
148
148
  );
149
149
  }
150
150
 
@@ -168,13 +168,13 @@ export default class FormBuilder extends HTMLBuilder {
168
168
  const additionalOpts = o[0] === selected ? { selected: "selected" } : {};
169
169
 
170
170
  renderedOpts.push(
171
- this.tag("option", o[1], { value: o[0], ...additionalOpts })
171
+ this.tag("option", o[1], { value: o[0], ...additionalOpts }),
172
172
  );
173
173
  }
174
174
 
175
175
  return this.withHint(
176
176
  this.tag("select", renderedOpts.join(""), { name, ...rest }),
177
- hint
177
+ hint,
178
178
  );
179
179
  }
180
180
 
@@ -202,7 +202,7 @@ export default class FormBuilder extends HTMLBuilder {
202
202
  ...rest,
203
203
  class: ["radio-group", rest.class].filter(Boolean).join(" "),
204
204
  }),
205
- hint
205
+ hint,
206
206
  );
207
207
  }
208
208
 
@@ -233,7 +233,7 @@ export default class FormBuilder extends HTMLBuilder {
233
233
  type: "hidden",
234
234
  name: `${optsName}[]`,
235
235
  value: "",
236
- })
236
+ }),
237
237
  );
238
238
  }
239
239
 
@@ -250,9 +250,9 @@ export default class FormBuilder extends HTMLBuilder {
250
250
  {
251
251
  ...rest,
252
252
  class: ["checkbox-group", rest.class].filter(Boolean).join(" "),
253
- }
253
+ },
254
254
  ),
255
- hint
255
+ hint,
256
256
  );
257
257
  }
258
258
 
@@ -334,7 +334,7 @@ export default class FormBuilder extends HTMLBuilder {
334
334
  ].join(""),
335
335
  {
336
336
  class: "button-group",
337
- }
337
+ },
338
338
  );
339
339
  }
340
340
 
@@ -367,7 +367,7 @@ export default class FormBuilder extends HTMLBuilder {
367
367
  ].join(""),
368
368
  {
369
369
  class: "link-group",
370
- }
370
+ },
371
371
  );
372
372
  }
373
373
 
@@ -413,14 +413,14 @@ export default class FormBuilder extends HTMLBuilder {
413
413
  .join(""),
414
414
  {
415
415
  class: "checkbox-wrapper",
416
- }
416
+ },
417
417
  ),
418
418
  hint ? this.hint(hint) : "",
419
419
  error ? this.error(error) : "",
420
420
  ]
421
421
  .filter(Boolean)
422
422
  .join(""),
423
- { class: error ? "has-error" : "" }
423
+ { class: error ? "has-error" : "" },
424
424
  );
425
425
  }
426
426
 
@@ -432,7 +432,7 @@ export default class FormBuilder extends HTMLBuilder {
432
432
  ]
433
433
  .filter(Boolean)
434
434
  .join(""),
435
- { class: error ? "has-error" : "" }
435
+ { class: error ? "has-error" : "" },
436
436
  );
437
437
  }
438
438
  }
@@ -31,7 +31,7 @@ export default class Pagination extends HTMLBuilder {
31
31
  }),
32
32
  `of ${this.pagination.pagesCount}`,
33
33
  ].join(" "),
34
- { action: this.path, method: "GET" }
34
+ { action: this.path, method: "GET" },
35
35
  );
36
36
  }
37
37
 
@@ -58,14 +58,14 @@ export default class Pagination extends HTMLBuilder {
58
58
  if (this.pagination.currentPage === 1) {
59
59
  children.push(
60
60
  this.__inactiveButton("First"),
61
- this.__inactiveButton("Previous")
61
+ this.__inactiveButton("Previous"),
62
62
  );
63
63
  } else {
64
64
  children.push(
65
65
  this.__activeButton("First", { href: this.__buildHref(1) }),
66
66
  this.__activeButton("Previous", {
67
67
  href: this.__buildHref(this.pagination.currentPage - 1),
68
- })
68
+ }),
69
69
  );
70
70
  }
71
71
 
@@ -74,7 +74,7 @@ export default class Pagination extends HTMLBuilder {
74
74
  if (this.pagination.currentPage === this.pagination.pagesCount) {
75
75
  children.push(
76
76
  this.__inactiveButton("Next"),
77
- this.__inactiveButton("Last")
77
+ this.__inactiveButton("Last"),
78
78
  );
79
79
  } else {
80
80
  children.push(
@@ -83,7 +83,7 @@ export default class Pagination extends HTMLBuilder {
83
83
  }),
84
84
  this.__activeButton("Last", {
85
85
  href: this.__buildHref(this.pagination.pagesCount),
86
- })
86
+ }),
87
87
  );
88
88
  }
89
89
 
@@ -58,11 +58,11 @@ function changeTypes(resourceType = "page") {
58
58
  ...value,
59
59
  label: value.label.replace(
60
60
  "#RESOURCE_TYPE#",
61
- Inflector.capitalize(resourceType)
61
+ Inflector.capitalize(resourceType),
62
62
  ),
63
63
  displayAction: value.displayAction.replace(
64
64
  "#RESOURCE_TYPE#",
65
- Inflector.capitalize(resourceType)
65
+ Inflector.capitalize(resourceType),
66
66
  ),
67
67
  };
68
68
  return acc;
@@ -88,7 +88,7 @@ function changeAction(change, resourceType) {
88
88
  } else {
89
89
  return "";
90
90
  }
91
- })()
91
+ })(),
92
92
  );
93
93
 
94
94
  return change.source === "revert"
@@ -12,7 +12,7 @@ function includedInCollection(value, collection) {
12
12
  }
13
13
 
14
14
  throw new Error(
15
- "Invalid input for collection. Expected a string or an array."
15
+ "Invalid input for collection. Expected a string or an array.",
16
16
  );
17
17
  }
18
18
 
@@ -33,8 +33,13 @@ function formattedDate(dateTimeString) {
33
33
  });
34
34
  }
35
35
 
36
+ function feature(featureName, context) {
37
+ return context?.globalConfig?.features?.[featureName] === true;
38
+ }
39
+
36
40
  export default {
37
41
  includedInCollection,
38
42
  formattedDate,
39
43
  formattedDateTime,
44
+ feature,
40
45
  };
package/src/index.js CHANGED
@@ -4,7 +4,7 @@ export { default as routeNestedCollection } from "./routeNestedCollection";
4
4
  export { default as routeMember } from "./routeMember";
5
5
  export { default as routeNestedMember } from "./routeNestedMember";
6
6
  export { default as setGlobalContext } from "./setGlobalContext";
7
- export { default as routeResource } from "./routeResource";
7
+ export { default as routeResourceModule } from "./routeResourceModule";
8
8
  export { default as routeSettings } from "./routeSettings";
9
9
  export { default as setupCloud } from "./setupCloud";
10
10
  export { default as routeStandard } from "./routeStandard";
@@ -22,6 +22,7 @@ export { default as ResourceRevisions } from "./cloud/ResourceRevisions";
22
22
  export { default as Resources } from "./cloud/Resources";
23
23
  export { default as Categories } from "./cloud/Categories";
24
24
 
25
+ export { default as ContentTasksHandler } from "./handlers/content_tasks/ContentTasksHandler";
25
26
  export { default as RedirectsHandler } from "./handlers/RedirectsHandler";
26
27
  export { default as TagsHandler } from "./handlers/TagsHandler";
27
28
  export { default as SettingsHandler } from "./handlers/_shared/SettingsHandler";
@@ -1,14 +1,19 @@
1
1
  const routeMember = (adapter, resource, handler, resourceConfig = {}) => {
2
2
  // Create route definitions
3
3
  const routes = [
4
- ["GET", `/${resource}`, "show", handler.show],
5
- ["GET", `/${resource}/edit`, "edit_form", handler.edit_form],
6
- ["POST", `/${resource}`, "edit_form", handler.update]
4
+ ["GET", `/${resource}`, "show", handler.show],
5
+ ["GET", `/${resource}/edit`, "edit_form", handler.edit_form],
6
+ ["POST", `/${resource}`, "edit_form", handler.update],
7
7
  ];
8
8
 
9
9
  // Map routes to full configuration
10
10
  const mapping = routes.map(([verb, path, action, fn]) => [
11
- verb, path, resource, resource, action, fn
11
+ verb,
12
+ path,
13
+ resource,
14
+ resource,
15
+ action,
16
+ fn,
12
17
  ]);
13
18
 
14
19
  adapter.routeMember(mapping, resourceConfig);
@@ -1,4 +1,10 @@
1
- const routeNestedCollection = (adapter, parent, resource, handler, resourceConfig = {}) => {
1
+ const routeNestedCollection = (
2
+ adapter,
3
+ parent,
4
+ resource,
5
+ handler,
6
+ resourceConfig = {},
7
+ ) => {
2
8
  const views = resourceConfig.views ?? `${parent}/${resource}`;
3
9
 
4
10
  // Define routes exactly as they were in the original implementation
@@ -10,7 +16,7 @@ const routeNestedCollection = (adapter, parent, resource, handler, resourceConfi
10
16
  resource,
11
17
  views,
12
18
  "index",
13
- handler.index
19
+ handler.index,
14
20
  ],
15
21
  [
16
22
  "GET",
@@ -18,23 +24,16 @@ const routeNestedCollection = (adapter, parent, resource, handler, resourceConfi
18
24
  resource,
19
25
  views,
20
26
  "create_form",
21
- handler.create_form
22
- ],
23
- [
24
- "GET",
25
- `/${resource}/:id`,
26
- resource,
27
- views,
28
- "show",
29
- handler.show
27
+ handler.create_form,
30
28
  ],
29
+ ["GET", `/${resource}/:id`, resource, views, "show", handler.show],
31
30
  [
32
31
  "GET",
33
32
  `/${resource}/:id/edit`,
34
33
  resource,
35
34
  views,
36
35
  "edit_form",
37
- handler.edit_form
36
+ handler.edit_form,
38
37
  ],
39
38
  [
40
39
  "POST",
@@ -42,24 +41,10 @@ const routeNestedCollection = (adapter, parent, resource, handler, resourceConfi
42
41
  resource,
43
42
  views,
44
43
  "create_form",
45
- handler.create
46
- ],
47
- [
48
- "PUT",
49
- `/${resource}/:id`,
50
- resource,
51
- views,
52
- "update",
53
- handler.update
44
+ handler.create,
54
45
  ],
55
- [
56
- "DELETE",
57
- `/${resource}/:id`,
58
- resource,
59
- views,
60
- "destroy",
61
- handler.destroy
62
- ]
46
+ ["PUT", `/${resource}/:id`, resource, views, "update", handler.update],
47
+ ["DELETE", `/${resource}/:id`, resource, views, "destroy", handler.destroy],
63
48
  ];
64
49
 
65
50
  adapter.routeNestedCollection(mapping, resourceConfig);