@raketa-cloud/admin 0.0.34 → 0.0.37

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 (44) hide show
  1. package/package.json +1 -1
  2. package/src/handlers/article_revisions/LocksHandler.js +22 -4
  3. package/src/handlers/article_revisions/UnlocksHandler.js +3 -1
  4. package/src/handlers/event_revisions/LocksHandler.js +17 -4
  5. package/src/handlers/event_revisions/UnlocksHandler.js +1 -1
  6. package/src/handlers/page_revisions/LocksHandler.js +13 -3
  7. package/src/handlers/page_revisions/UnlocksHandler.js +1 -1
  8. package/src/handlers/page_revisions/VisualHandler.js +1 -0
  9. package/src/helpers/FormBuilder.js +88 -38
  10. package/src/helpers/Inflector.js +1 -1
  11. package/src/styles/application.css +11 -2
  12. package/src/tests/handlers/article_revisions/CodesHandler.test/update.test.js +5 -5
  13. package/src/tests/handlers/article_revisions/LocksHandler.test/create.test.js +142 -0
  14. package/src/tests/handlers/article_revisions/LocksHandler.test/create_form.test.js +55 -0
  15. package/src/tests/handlers/article_revisions/UnlocksHandler.test/create.test.js +84 -0
  16. package/src/tests/handlers/event_revisions/CodesHandler.test/update.test.js +5 -5
  17. package/src/tests/handlers/event_revisions/LocksHandler.test/create.test.js +142 -0
  18. package/src/tests/handlers/event_revisions/LocksHandler.test/create_form.test.js +55 -0
  19. package/src/tests/handlers/event_revisions/UnlocksHandler.test/create.test.js +84 -0
  20. package/src/tests/handlers/page_revisions/CodesHandler.test/edit_form.test.js +1 -1
  21. package/src/tests/handlers/page_revisions/CodesHandler.test/update.test.js +5 -5
  22. package/src/tests/handlers/page_revisions/LocksHandler.test/create.test.js +138 -0
  23. package/src/tests/handlers/page_revisions/LocksHandler.test/create_form.test.js +55 -0
  24. package/src/tests/handlers/page_revisions/UnlocksHandler.test/create.test.js +80 -0
  25. package/src/views/article_revisions/codes/edit_form.ejs +3 -3
  26. package/src/views/article_revisions/tags/edit_form.ejs +1 -1
  27. package/src/views/articles/_form.ejs +1 -1
  28. package/src/views/articles/create_form.ejs +1 -1
  29. package/src/views/articles/deletes/create_form.ejs +1 -1
  30. package/src/views/articles/translations/_form.ejs +1 -1
  31. package/src/views/articles/translations/create_form.ejs +1 -1
  32. package/src/views/event_revisions/codes/edit_form.ejs +3 -3
  33. package/src/views/event_revisions/tags/edit_form.ejs +1 -1
  34. package/src/views/events/_form.ejs +1 -1
  35. package/src/views/events/create_form.ejs +1 -1
  36. package/src/views/events/deletes/create_form.ejs +1 -1
  37. package/src/views/events/translations/_form.ejs +1 -1
  38. package/src/views/events/translations/create_form.ejs +1 -1
  39. package/src/views/page_revisions/codes/edit_form.ejs +3 -3
  40. package/src/views/pages/_form.ejs +1 -1
  41. package/src/views/pages/create_form.ejs +1 -1
  42. package/src/views/pages/deletes/create_form.ejs +1 -1
  43. package/src/views/pages/translations/_form.ejs +1 -1
  44. package/src/views/pages/translations/create_form.ejs +1 -1
@@ -0,0 +1,55 @@
1
+ import Factory from "../../../support/factory";
2
+ import PageRevisions from "../../../../cloud/PageRevisions";
3
+ import LocksHandler from "../../../../handlers/page_revisions/LocksHandler";
4
+
5
+ function buildCtx(revision) {
6
+ return {
7
+ client: {
8
+ pageRevisions: new PageRevisions(() => ({}), "token"),
9
+ },
10
+ params: { parent_id: revision.id },
11
+ locale: "en",
12
+ };
13
+ }
14
+
15
+ describe("New page revision lock", () => {
16
+ test("create_form for locking page revision", async () => {
17
+ const revision = Factory.build("page_revision");
18
+ const ctx = buildCtx(revision);
19
+
20
+ const mockFind = jest
21
+ .spyOn(ctx.client.pageRevisions, "find")
22
+ .mockImplementation(() => revision);
23
+
24
+ const result = await LocksHandler.create_form(ctx);
25
+
26
+ expect(mockFind).toHaveBeenCalledWith(revision.id, "en");
27
+
28
+ expect(result).toEqual({
29
+ assigns: {
30
+ resource: {
31
+ id: revision.id,
32
+ originalId: revision.originalId,
33
+ message: "",
34
+ },
35
+ errors: {},
36
+ _translations: [],
37
+ },
38
+ });
39
+ });
40
+
41
+ test("create_form for non existing page revision", async () => {
42
+ const nonExistentRevision = Factory.build("page_revision");
43
+ const ctx = buildCtx(nonExistentRevision);
44
+
45
+ const mockFind = jest
46
+ .spyOn(ctx.client.pageRevisions, "find")
47
+ .mockImplementation(() => null);
48
+
49
+ await expect(LocksHandler.create_form(ctx)).rejects.toThrow(
50
+ `Missing revision #${nonExistentRevision.id}`
51
+ );
52
+
53
+ expect(mockFind).toHaveBeenCalledWith(nonExistentRevision.id, "en");
54
+ });
55
+ });
@@ -0,0 +1,80 @@
1
+ import Factory from "../../../support/factory";
2
+ import PageRevisions from "../../../../cloud/PageRevisions";
3
+ import UnlocksHandler from "../../../../handlers/page_revisions/UnlocksHandler";
4
+
5
+ function buildCtx(revision) {
6
+ return {
7
+ client: {
8
+ pageRevisions: new PageRevisions(() => ({}), "token"),
9
+ },
10
+ params: { parent_id: revision.id },
11
+ locale: "en",
12
+ resourceConfig: {
13
+ pageType: "page",
14
+ pageTypePlural: "pages",
15
+ },
16
+ };
17
+ }
18
+
19
+ describe("Page revision unlock", () => {
20
+ test("unlock successful", async () => {
21
+ const revision = Factory.build("page_revision");
22
+ const ctx = buildCtx(revision);
23
+
24
+ const mockUnlock = jest
25
+ .spyOn(ctx.client.pageRevisions, "unlock")
26
+ .mockImplementation(() => ({
27
+ revision: revision,
28
+ errors: null,
29
+ pageErrors: null,
30
+ }));
31
+
32
+ const result = await UnlocksHandler.create(ctx);
33
+
34
+ expect(mockUnlock).toHaveBeenCalledWith(revision.id, "en");
35
+
36
+ expect(result).toEqual({
37
+ redirect: `/en/pages/${revision.originalId}`,
38
+ });
39
+ });
40
+
41
+ test("unlock failed with errors", async () => {
42
+ const revision = Factory.build("page_revision");
43
+ const ctx = buildCtx(revision);
44
+ const errors = [
45
+ { key: "generalError", message: "Failed to unlock revision" },
46
+ ];
47
+
48
+ const mockUnlock = jest
49
+ .spyOn(ctx.client.pageRevisions, "unlock")
50
+ .mockImplementation(() => ({ revision: null, errors, pageErrors: null }));
51
+
52
+ await expect(UnlocksHandler.create(ctx)).rejects.toThrow(
53
+ `Failed to unlock revision: ${JSON.stringify(errors)}`
54
+ );
55
+
56
+ expect(mockUnlock).toHaveBeenCalledWith(revision.id, "en");
57
+ });
58
+
59
+ test("unlock failed with page errors", async () => {
60
+ const revision = Factory.build("page_revision");
61
+ const ctx = buildCtx(revision);
62
+ const pageErrors = [
63
+ { key: "generalError", message: "Failed to start revision" },
64
+ ];
65
+
66
+ const mockUnlock = jest
67
+ .spyOn(ctx.client.pageRevisions, "unlock")
68
+ .mockImplementation(() => ({
69
+ revision: null,
70
+ errors: null,
71
+ pageErrors,
72
+ }));
73
+
74
+ await expect(UnlocksHandler.create(ctx)).rejects.toThrow(
75
+ `Failed to start revision: ${JSON.stringify(pageErrors)}`
76
+ );
77
+
78
+ expect(mockUnlock).toHaveBeenCalledWith(revision.id, "en");
79
+ });
80
+ });
@@ -15,12 +15,12 @@
15
15
  value: JSON.stringify(resource.settings?.codes?.scripts || undefined)
16
16
  }) %>
17
17
 
18
- <%- f.field('resource.settings.codes.structured_data', {
18
+ <%- f.field('resource.settings.codes.structured_json', {
19
19
  label: 'Structured data (JSON)',
20
20
  as: 'textarea',
21
- hint: 'Click here for a structured data verification tool',
21
+ hint: '<a target="_blank" href="https://search.google.com/test/rich-results">Click here for a structured data verification tool</a>',
22
22
  "data-validations-json": true,
23
- value: JSON.stringify(resource.settings?.codes?.structured_data || undefined)
23
+ value: JSON.stringify(resource.settings?.codes?.structured_json || undefined)
24
24
  }) %>
25
25
 
26
26
  <div class="form-actions">
@@ -9,7 +9,7 @@
9
9
  <div>
10
10
  <% form_for({ resource }, errors, (f) => { %>
11
11
  <form action="<%= `/${_context.locale}/${_context.resourceConfig.articleType}_revisions/${resource.id}/tags` %>" method="POST" class="form">
12
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name]) }) %>
12
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name]) }) %>
13
13
 
14
14
  <div class="form-actions">
15
15
  <div class="btn-toolbar">
@@ -13,7 +13,7 @@
13
13
 
14
14
  <raketa-image-picker name="resource[settings][meta][image]" value="<%= JSON.stringify(resource.settings?.meta?.image || {}) %>" label="Meta image"></raketa-image-picker>
15
15
 
16
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name]) }) %>
16
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name]) }) %>
17
17
 
18
18
  <div class="form-actions">
19
19
  <div class="btn-toolbar">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Create article</h1>
3
+ <h1 class="heading-1">Create <%= Inflector.downcase(_context.resourceConfig.articleType) %></h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Delete an <%= _context.resourceConfig.articleType %></h1>
3
+ <h1 class="heading-1">Delete <%= Inflector.downcase(_context.resourceConfig.articleType) %></h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -18,7 +18,7 @@
18
18
  <h6>Original tags:</h6>
19
19
  <div><%= blueprint.tags.map((tag) => tag.name).join(", ")%></div>
20
20
 
21
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name])}) %>
21
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name])}) %>
22
22
 
23
23
  <div class="form-actions">
24
24
  <div class="btn-toolbar">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Create <%= _context.resourceConfig.articleType %> translation</h1>
3
+ <h1 class="heading-1">Create <%= Inflector.downcase(_context.resourceConfig.articleType) %> translation</h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -15,12 +15,12 @@
15
15
  value: JSON.stringify(resource.settings?.codes?.scripts || undefined)
16
16
  }) %>
17
17
 
18
- <%- f.field('resource.settings.codes.structured_data', {
18
+ <%- f.field('resource.settings.codes.structured_json', {
19
19
  label: 'Structured data (JSON)',
20
20
  as: 'textarea',
21
- hint: 'Click here for a structured data verification tool',
21
+ hint: '<a target="_blank" href="https://search.google.com/test/rich-results">Click here for a structured data verification tool</a>',
22
22
  "data-validations-json": true,
23
- value: JSON.stringify(resource.settings?.codes?.structured_data || undefined)
23
+ value: JSON.stringify(resource.settings?.codes?.structured_json || undefined)
24
24
  }) %>
25
25
 
26
26
  <div class="form-actions">
@@ -9,7 +9,7 @@
9
9
  <div>
10
10
  <% form_for({ resource }, errors, (f) => { %>
11
11
  <form action="<%= `/${_context.locale}/${_context.resourceConfig.eventType}_revisions/${resource.id}/tags` %>" method="POST" class="form">
12
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name]) }) %>
12
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name]) }) %>
13
13
 
14
14
  <div class="form-actions">
15
15
  <div class="btn-toolbar">
@@ -15,7 +15,7 @@
15
15
 
16
16
  <raketa-image-picker name="resource[settings][meta][image]" value="<%= JSON.stringify(resource.settings?.meta?.image || {}) %>" label="Meta image"></raketa-image-picker>
17
17
 
18
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name]) }) %>
18
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name]) }) %>
19
19
 
20
20
  <div class="form-actions">
21
21
  <div class="btn-toolbar">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Create event</h1>
3
+ <h1 class="heading-1">Create <%= Inflector.downcase(_context.resourceConfig.eventType) %></h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Delete an <%= _context.resourceConfig.eventType %></h1>
3
+ <h1 class="heading-1">Delete <%= Inflector.downcase(_context.resourceConfig.eventType) %></h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -20,7 +20,7 @@
20
20
  <h6>Original tags:</h6>
21
21
  <div><%= blueprint.tags.map((tag) => tag.name).join(", ")%></div>
22
22
 
23
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name])}) %>
23
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name])}) %>
24
24
 
25
25
  <div class="form-actions">
26
26
  <div class="btn-toolbar">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Create <%= _context.resourceConfig.eventType %> translation</h1>
3
+ <h1 class="heading-1">Create <%= Inflector.downcase(_context.resourceConfig.eventType) %> translation</h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -15,12 +15,12 @@
15
15
  value: JSON.stringify(resource.settings?.codes?.scripts || undefined)
16
16
  }) %>
17
17
 
18
- <%- f.field('resource.settings.codes.structured_data', {
18
+ <%- f.field('resource.settings.codes.structured_json', {
19
19
  label: 'Structured data (JSON)',
20
20
  as: 'textarea',
21
- hint: 'Click here for a structured data verification tool',
21
+ hint: '<a target="_blank" href="https://search.google.com/test/rich-results">Click here for a structured data verification tool</a>',
22
22
  "data-validations-json": true,
23
- value: JSON.stringify(resource.settings?.codes?.structured_data || undefined)
23
+ value: JSON.stringify(resource.settings?.codes?.structured_json || undefined)
24
24
  }) %>
25
25
 
26
26
  <div class="form-actions">
@@ -12,7 +12,7 @@
12
12
 
13
13
  <raketa-image-picker name="resource[settings][meta][image]" value="<%= JSON.stringify(resource.settings?.meta?.image || {}) %>" label="Meta image"></raketa-image-picker>
14
14
 
15
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name]) }) %>
15
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name]) }) %>
16
16
 
17
17
  <div class="form-actions">
18
18
  <div class="btn-toolbar">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Create page</h1>
3
+ <h1 class="heading-1">Create <%= Inflector.downcase(_context.resourceConfig.pageType) %></h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Delete a <%= _context.resourceConfig.pageType %></h1>
3
+ <h1 class="heading-1">Delete <%= Inflector.downcase(_context.resourceConfig.pageType) %></h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">
@@ -17,7 +17,7 @@
17
17
  <h6>Original tags:</h6>
18
18
  <div><%= blueprint.tags.map((tag) => tag.name).join(", ")%></div>
19
19
 
20
- <%- f.field('resource.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name]) }) %>
20
+ <%- f.field('resource.tags', { as: 'checkbox_group', options: tags.map(tag => [tag.id, tag.name]) }) %>
21
21
 
22
22
  <div class="form-actions">
23
23
  <div class="btn-toolbar">
@@ -1,6 +1,6 @@
1
1
  <div class="page-wrapper">
2
2
  <div class="page-title">
3
- <h1 class="heading-1">Create <%= _context.resourceConfig.pageType %> translation</h1>
3
+ <h1 class="heading-1">Create <%= Inflector.downcase(_context.resourceConfig.pageType) %> translation</h1>
4
4
  </div>
5
5
 
6
6
  <div class="grid gap-4 md:grid-cols-3">