@raketa-cloud/admin 1.2.0 → 1.4.0

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 (41) hide show
  1. package/package.json +1 -1
  2. package/src/HonoAdapter.js +304 -169
  3. package/src/filters.js +17 -0
  4. package/src/handlers/article_revisions/ArticleRevisionsHandler.js +8 -0
  5. package/src/handlers/articles/ArticlesHandler.js +12 -1
  6. package/src/handlers/event_revisions/EventRevisionsHandler.js +8 -0
  7. package/src/handlers/events/EventsHandler.js +13 -2
  8. package/src/handlers/page_revisions/PageRevisionsHandler.js +8 -0
  9. package/src/handlers/pages/PagesHandler.js +12 -1
  10. package/src/index.js +1 -0
  11. package/src/routeCollection.js +14 -83
  12. package/src/routeMember.js +10 -33
  13. package/src/routeNestedCollection.js +19 -47
  14. package/src/routeNestedMember.js +14 -40
  15. package/src/tests/Adapter.test.js +4 -4
  16. package/src/tests/HonoAdapter.filter.test.js +40 -0
  17. package/src/tests/HonoAdapter.test.js +110 -9
  18. package/src/tests/RaketaContext.test.js +65 -0
  19. package/src/tests/cipher.test.js +73 -0
  20. package/src/tests/filters.test.js +97 -0
  21. package/src/tests/handlers/article_revisions/ArticleRevisionsHandler.test/create.test.js +43 -35
  22. package/src/tests/handlers/articles/ArticlesHandler.test/show.test.js +12 -1
  23. package/src/tests/handlers/event_revisions/EventRevisionsHandler.test/create.test.js +41 -33
  24. package/src/tests/handlers/events/EventsHandler.test/show.test.js +12 -1
  25. package/src/tests/handlers/page_revisions/PageRevisionsHandler.test/create.test.js +41 -27
  26. package/src/tests/handlers/pages/PagesHandler.test/show.test.js +12 -1
  27. package/src/tests/routeCollection.test.js +0 -92
  28. package/src/tests/routeMember.test.js +0 -6
  29. package/src/tests/routeNestedCollection.test.js +0 -14
  30. package/src/tests/routeNestedMember.test.js +0 -6
  31. package/src/tests/utils.test.js +70 -0
  32. package/src/views/articles/_shared/_history_toolbar.ejs +2 -2
  33. package/src/views/articles/_shared/_toolbar.ejs +38 -26
  34. package/src/views/articles/_shared/history_table.ejs +6 -0
  35. package/src/views/events/_shared/_history_toolbar.ejs +2 -2
  36. package/src/views/events/_shared/_toolbar.ejs +38 -26
  37. package/src/views/events/_shared/history_table.ejs +6 -0
  38. package/src/views/pages/_shared/_history_toolbar.ejs +2 -2
  39. package/src/views/pages/_shared/_toolbar.ejs +38 -26
  40. package/src/views/pages/_shared/history_table.ejs +6 -0
  41. package/src/Adapter.js +0 -265
@@ -112,8 +112,6 @@ describe("routeNestedCollection", () => {
112
112
  "orders/line_items",
113
113
  "index",
114
114
  OrdersHandlerWithFilters.index,
115
- OrdersHandlerWithFilters.before_filter,
116
- OrdersHandlerWithFilters.after_filter,
117
115
  ],
118
116
  [
119
117
  "GET",
@@ -122,8 +120,6 @@ describe("routeNestedCollection", () => {
122
120
  "orders/line_items",
123
121
  "create_form",
124
122
  OrdersHandlerWithFilters.create_form,
125
- OrdersHandlerWithFilters.before_filter,
126
- OrdersHandlerWithFilters.after_filter,
127
123
  ],
128
124
  [
129
125
  "GET",
@@ -132,8 +128,6 @@ describe("routeNestedCollection", () => {
132
128
  "orders/line_items",
133
129
  "show",
134
130
  OrdersHandlerWithFilters.show,
135
- OrdersHandlerWithFilters.before_filter,
136
- OrdersHandlerWithFilters.after_filter,
137
131
  ],
138
132
  [
139
133
  "GET",
@@ -142,8 +136,6 @@ describe("routeNestedCollection", () => {
142
136
  "orders/line_items",
143
137
  "edit_form",
144
138
  OrdersHandlerWithFilters.edit_form,
145
- OrdersHandlerWithFilters.before_filter,
146
- OrdersHandlerWithFilters.after_filter,
147
139
  ],
148
140
  [
149
141
  "POST",
@@ -152,8 +144,6 @@ describe("routeNestedCollection", () => {
152
144
  "orders/line_items",
153
145
  "create_form",
154
146
  OrdersHandlerWithFilters.create,
155
- OrdersHandlerWithFilters.before_filter,
156
- OrdersHandlerWithFilters.after_filter,
157
147
  ],
158
148
  [
159
149
  "PUT",
@@ -162,8 +152,6 @@ describe("routeNestedCollection", () => {
162
152
  "orders/line_items",
163
153
  "update",
164
154
  OrdersHandlerWithFilters.update,
165
- OrdersHandlerWithFilters.before_filter,
166
- OrdersHandlerWithFilters.after_filter,
167
155
  ],
168
156
  [
169
157
  "DELETE",
@@ -172,8 +160,6 @@ describe("routeNestedCollection", () => {
172
160
  "orders/line_items",
173
161
  "destroy",
174
162
  OrdersHandlerWithFilters.destroy,
175
- OrdersHandlerWithFilters.before_filter,
176
- OrdersHandlerWithFilters.after_filter,
177
163
  ],
178
164
  ],
179
165
  {}
@@ -72,8 +72,6 @@ describe("routeNestedMember", () => {
72
72
  "artist/bio",
73
73
  "show",
74
74
  ArtistHandWithFiltersWithFilters.show,
75
- ArtistHandWithFiltersWithFilters.before_filter,
76
- ArtistHandWithFiltersWithFilters.after_filter,
77
75
  ],
78
76
  [
79
77
  "GET",
@@ -82,8 +80,6 @@ describe("routeNestedMember", () => {
82
80
  "artist/bio",
83
81
  "edit_form",
84
82
  ArtistHandWithFiltersWithFilters.edit_form,
85
- ArtistHandWithFiltersWithFilters.before_filter,
86
- ArtistHandWithFiltersWithFilters.after_filter,
87
83
  ],
88
84
  [
89
85
  "POST",
@@ -92,8 +88,6 @@ describe("routeNestedMember", () => {
92
88
  "artist/bio",
93
89
  "edit_form",
94
90
  ArtistHandWithFiltersWithFilters.update,
95
- ArtistHandWithFiltersWithFilters.before_filter,
96
- ArtistHandWithFiltersWithFilters.after_filter,
97
91
  ],
98
92
  ],
99
93
  {}
@@ -0,0 +1,70 @@
1
+ import {
2
+ toUTCISO8601String,
3
+ dateToUTCISO8601String,
4
+ toDateInput,
5
+ toDateTimeInput
6
+ } from "../utils";
7
+
8
+ describe("utils", () => {
9
+ describe("toUTCISO8601String", () => {
10
+ test("converts datetime-local input to UTC ISO8601 string", () => {
11
+ const inputDateTime = "2024-05-15T14:30";
12
+ const expected = "2024-05-15T14:30:00Z";
13
+
14
+ expect(toUTCISO8601String(inputDateTime)).toBe(expected);
15
+ });
16
+ });
17
+
18
+ describe("dateToUTCISO8601String", () => {
19
+ test("converts date input to UTC ISO8601 string with midnight time", () => {
20
+ const inputDate = "2024-05-15";
21
+ const expected = "2024-05-15T00:00:00Z";
22
+
23
+ expect(dateToUTCISO8601String(inputDate)).toBe(expected);
24
+ });
25
+ });
26
+
27
+ describe("toDateInput", () => {
28
+ test("extracts date part from ISO8601 string", () => {
29
+ const isoString = "2024-05-15T14:30:00Z";
30
+ const expected = "2024-05-15";
31
+
32
+ expect(toDateInput(isoString)).toBe(expected);
33
+ });
34
+
35
+ test("returns current date when no initial date is provided", () => {
36
+ // Mock current date
37
+ const mockDate = new Date(2024, 4, 15); // May 15, 2024
38
+ jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
39
+
40
+ const expected = "2024-05-15";
41
+
42
+ expect(toDateInput()).toBe(expected);
43
+
44
+ // Restore Date
45
+ jest.restoreAllMocks();
46
+ });
47
+ });
48
+
49
+ describe("toDateTimeInput", () => {
50
+ test("removes Z suffix from ISO8601 string", () => {
51
+ const isoString = "2024-05-15T14:30:00Z";
52
+ const expected = "2024-05-15T14:30:00";
53
+
54
+ expect(toDateTimeInput(isoString)).toBe(expected);
55
+ });
56
+
57
+ test("returns current datetime when no initial date is provided", () => {
58
+ // Mock current date
59
+ const mockDate = new Date(2024, 4, 15, 14, 30); // May 15, 2024, 14:30
60
+ jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
61
+
62
+ const expected = "2024-05-15T14:30";
63
+
64
+ expect(toDateTimeInput()).toBe(expected);
65
+
66
+ // Restore Date
67
+ jest.restoreAllMocks();
68
+ });
69
+ });
70
+ });
@@ -2,7 +2,7 @@
2
2
  <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/${_context.resourceConfig.pageType}_changes/reverts` %>" class="inline-block">
3
3
  <input type="hidden" name="version" value="<%= change.version %>">
4
4
 
5
- <% if (history.isChangeRevertable(change, maxVersion)) { %>
5
+ <% if (history.isChangeRevertable(change, maxVersion) && !(resource.revisionsCount >= _context.maxOpenRevisions)) { %>
6
6
  <button type="submit" class="btn-text">
7
7
  Revert
8
8
  </button>
@@ -21,4 +21,4 @@
21
21
 
22
22
  Preview
23
23
  </a>
24
- </div>
24
+ </div>
@@ -1,33 +1,45 @@
1
- <div class="actions-toolbar">
2
- <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/${_context.resourceConfig.articleType}_revisions` %>" class="inline-block">
3
- <button type="submit" class="btn-primary">
4
- Start revision
5
- </button>
6
- </form>
1
+ <div>
2
+ <div class="actions-toolbar">
3
+ <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/${_context.resourceConfig.articleType}_revisions` %>" class="inline-block">
4
+ <% if (resource.revisionsCount >= _context?.maxOpenRevisions) { %>
5
+ <button type="submit" class="btn-primary" disabled style="opacity: 50%;">
6
+ Start revision
7
+ </button>
8
+ <% } else {%>
9
+ <button type="submit" class="btn-primary">
10
+ Start revision
11
+ </button>
12
+ <% } %>
13
+ </form>
7
14
 
8
- <a href="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/urls/new` %>" class="btn-text has-icon">
9
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
10
- <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
11
- </svg>
15
+ <a href="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/urls/new` %>" class="btn-text has-icon">
16
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
17
+ <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
18
+ </svg>
19
+
20
+ Change URL
21
+ </a>
12
22
 
13
- Change URL
14
- </a>
23
+ <form action="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/clones` %>" method="post" class="inline-block">
24
+ <button type="submit" class="btn-text has-icon">
25
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
26
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
27
+ </svg>
15
28
 
16
- <form action="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/clones` %>" method="post" class="inline-block">
17
- <button type="submit" class="btn-text has-icon">
29
+ Clone <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.articleType)) %>
30
+ </button>
31
+ </form>
32
+
33
+ <a href="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/deletes/new` %>" class="btn-danger has-icon">
18
34
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
19
- <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
35
+ <path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
20
36
  </svg>
21
37
 
22
- Clone <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.articleType)) %>
23
- </button>
24
- </form>
25
-
26
- <a href="<%= `/${_context.locale}/${_context.resourceConfig.articleTypePlural}/${resource.id}/deletes/new` %>" class="btn-danger has-icon">
27
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
28
- <path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
29
- </svg>
38
+ Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.articleType)) %>
39
+ </a>
40
+ </div>
30
41
 
31
- Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.articleType)) %>
32
- </a>
33
- </div>
42
+ <% if (_context.query?.revisions_count_error) { %>
43
+ <div class="text-red-600">Cannot open a new revision. Current limit is <%= _context.maxOpenRevisions %>. </div>
44
+ <% } %>
45
+ </div>
@@ -1,3 +1,4 @@
1
+ <% if (changes && changes.list.length > 0) { %>
1
2
  <% const maxVersion = history.getMaxVersion(changes); %>
2
3
 
3
4
  <div class="mb-4 history-table-wrapper">
@@ -66,3 +67,8 @@
66
67
  <%- pagination(changes.pagination, _context) %>
67
68
  <% } %>
68
69
  </div>
70
+ <% } else { %>
71
+ <div class="history-table-wrapper mb-4">
72
+ <p class="text-center py-4">No changes, yet.</p>
73
+ </div>
74
+ <% } %>
@@ -2,7 +2,7 @@
2
2
  <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/${_context.resourceConfig.pageType}_changes/reverts` %>" class="inline-block">
3
3
  <input type="hidden" name="version" value="<%= change.version %>">
4
4
 
5
- <% if (history.isChangeRevertable(change, maxVersion)) { %>
5
+ <% if (history.isChangeRevertable(change, maxVersion) && !(resource.revisionsCount >= _context.maxOpenRevisions)) { %>
6
6
  <button type="submit" class="btn-text">
7
7
  Revert
8
8
  </button>
@@ -21,4 +21,4 @@
21
21
 
22
22
  Preview
23
23
  </a>
24
- </div>
24
+ </div>
@@ -1,33 +1,45 @@
1
- <div class="actions-toolbar">
2
- <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/${_context.resourceConfig.eventType}_revisions` %>" class="inline-block">
3
- <button type="submit" class="btn-primary">
4
- Start revision
5
- </button>
6
- </form>
1
+ <div>
2
+ <div class="actions-toolbar">
3
+ <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/${_context.resourceConfig.eventType}_revisions` %>" class="inline-block">
4
+ <% if (resource.revisionsCount >= _context?.maxOpenRevisions) { %>
5
+ <button type="submit" class="btn-primary" disabled style="opacity: 50%;">
6
+ Start revision
7
+ </button>
8
+ <% } else {%>
9
+ <button type="submit" class="btn-primary">
10
+ Start revision
11
+ </button>
12
+ <% } %>
13
+ </form>
7
14
 
8
- <a href="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/urls/new` %>" class="btn-text has-icon">
9
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
10
- <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
11
- </svg>
15
+ <a href="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/urls/new` %>" class="btn-text has-icon">
16
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
17
+ <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
18
+ </svg>
19
+
20
+ Change URL
21
+ </a>
12
22
 
13
- Change URL
14
- </a>
23
+ <form action="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/clones` %>" method="post" class="inline-block">
24
+ <button type="submit" class="btn-text has-icon">
25
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
26
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
27
+ </svg>
15
28
 
16
- <form action="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/clones` %>" method="post" class="inline-block">
17
- <button type="submit" class="btn-text has-icon">
29
+ Clone <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.eventType)) %>
30
+ </button>
31
+ </form>
32
+
33
+ <a href="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/deletes/new` %>" class="btn-danger has-icon">
18
34
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
19
- <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
35
+ <path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
20
36
  </svg>
21
37
 
22
- Clone <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.eventType)) %>
23
- </button>
24
- </form>
25
-
26
- <a href="<%= `/${_context.locale}/${_context.resourceConfig.eventTypePlural}/${resource.id}/deletes/new` %>" class="btn-danger has-icon">
27
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
28
- <path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
29
- </svg>
38
+ Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.eventType)) %>
39
+ </a>
40
+ </div>
30
41
 
31
- Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.eventType)) %>
32
- </a>
33
- </div>
42
+ <% if (_context.query?.revisions_count_error) { %>
43
+ <div class="text-red-600">Cannot open a new revision. Current limit is <%= _context.maxOpenRevisions %>. </div>
44
+ <% } %>
45
+ </div>
@@ -1,3 +1,4 @@
1
+ <% if (changes && changes.list.length > 0) { %>
1
2
  <% const maxVersion = history.getMaxVersion(changes); %>
2
3
 
3
4
  <div class="history-table-wrapper mb-4">
@@ -66,3 +67,8 @@
66
67
  <%- pagination(changes.pagination, _context) %>
67
68
  <% } %>
68
69
  </div>
70
+ <% } else { %>
71
+ <div class="history-table-wrapper mb-4">
72
+ <p class="text-center py-4">No changes, yet.</p>
73
+ </div>
74
+ <% } %>
@@ -2,7 +2,7 @@
2
2
  <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/${_context.resourceConfig.pageType}_changes/reverts` %>" class="inline-block">
3
3
  <input type="hidden" name="version" value="<%= change.version %>">
4
4
 
5
- <% if (history.isChangeRevertable(change, maxVersion)) { %>
5
+ <% if (history.isChangeRevertable(change, maxVersion) && !(resource.revisionsCount >= _context.maxOpenRevisions)) { %>
6
6
  <button type="submit" class="btn-text">
7
7
  Revert
8
8
  </button>
@@ -21,4 +21,4 @@
21
21
 
22
22
  Preview
23
23
  </a>
24
- </div>
24
+ </div>
@@ -1,33 +1,45 @@
1
- <div class="actions-toolbar">
2
- <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/${_context.resourceConfig.pageType}_revisions` %>" class="inline-block">
3
- <button type="submit" class="btn-primary">
4
- Start revision
5
- </button>
6
- </form>
1
+ <div>
2
+ <div class="actions-toolbar">
3
+ <form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/${_context.resourceConfig.pageType}_revisions` %>" class="inline-block">
4
+ <% if (resource.revisionsCount >= _context?.maxOpenRevisions) { %>
5
+ <button type="submit" class="btn-primary" disabled style="opacity: 50%;">
6
+ Start revision
7
+ </button>
8
+ <% } else {%>
9
+ <button type="submit" class="btn-primary">
10
+ Start revision
11
+ </button>
12
+ <% } %>
13
+ </form>
7
14
 
8
- <a href="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/urls/new` %>" class="btn-text has-icon">
9
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
10
- <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
11
- </svg>
15
+ <a href="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/urls/new` %>" class="btn-text has-icon">
16
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
17
+ <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 0 1 1.242 7.244l-4.5 4.5a4.5 4.5 0 0 1-6.364-6.364l1.757-1.757m13.35-.622 1.757-1.757a4.5 4.5 0 0 0-6.364-6.364l-4.5 4.5a4.5 4.5 0 0 0 1.242 7.244" />
18
+ </svg>
19
+
20
+ Change URL
21
+ </a>
12
22
 
13
- Change URL
14
- </a>
23
+ <form action="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/clones` %>" method="post" class="inline-block">
24
+ <button type="submit" class="btn-text has-icon">
25
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
26
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
27
+ </svg>
15
28
 
16
- <form action="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/clones` %>" method="post" class="inline-block">
17
- <button type="submit" class="btn-text has-icon">
29
+ Clone <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.pageType)) %>
30
+ </button>
31
+ </form>
32
+
33
+ <a href="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/deletes/new` %>" class="btn-danger has-icon">
18
34
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
19
- <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
35
+ <path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
20
36
  </svg>
21
37
 
22
- Clone <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.pageType)) %>
23
- </button>
24
- </form>
25
-
26
- <a href="<%= `/${_context.locale}/${_context.resourceConfig.pageTypePlural}/${resource.id}/deletes/new` %>" class="btn-danger has-icon">
27
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
28
- <path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
29
- </svg>
38
+ Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.pageType)) %>
39
+ </a>
40
+ </div>
30
41
 
31
- Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.pageType)) %>
32
- </a>
33
- </div>
42
+ <% if (_context.query?.revisions_count_error) { %>
43
+ <div class="text-red-600">Cannot open a new revision. Current limit is <%= _context.maxOpenRevisions %>. </div>
44
+ <% } %>
45
+ </div>
@@ -1,3 +1,4 @@
1
+ <% if (changes && changes.list.length > 0) { %>
1
2
  <% const maxVersion = history.getMaxVersion(changes); %>
2
3
 
3
4
  <div class="history-table-wrapper mb-4">
@@ -66,3 +67,8 @@
66
67
  <%- pagination(changes.pagination, _context) %>
67
68
  <% } %>
68
69
  </div>
70
+ <% } else { %>
71
+ <div class="history-table-wrapper mb-4">
72
+ <p class="text-center py-4">No changes, yet.</p>
73
+ </div>
74
+ <% } %>