@raketa-cloud/admin 0.0.79 → 0.0.82

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 (38) hide show
  1. package/package.json +1 -1
  2. package/src/cloud/ArticleRevisions.js +30 -0
  3. package/src/cloud/EventRevisions.js +30 -0
  4. package/src/cloud/PageRevisions.js +30 -0
  5. package/src/cloud/documents/articlesDocuments.js +24 -0
  6. package/src/cloud/documents/common.js +13 -0
  7. package/src/cloud/documents/eventsDocuments.js +24 -0
  8. package/src/cloud/documents/pagesDocuments.js +24 -0
  9. package/src/handlers/article_revisions/CancelSchedulesHandler.js +26 -0
  10. package/src/handlers/article_revisions/PublishesHandler.js +39 -10
  11. package/src/handlers/article_revisions/UnlocksHandler.js +1 -1
  12. package/src/handlers/event_revisions/CancelSchedulesHandler.js +26 -0
  13. package/src/handlers/event_revisions/PublishesHandler.js +34 -7
  14. package/src/handlers/event_revisions/UnlocksHandler.js +3 -1
  15. package/src/handlers/page_revisions/CancelSchedulesHandler.js +26 -0
  16. package/src/handlers/page_revisions/PublishesHandler.js +34 -7
  17. package/src/handlers/page_revisions/UnlocksHandler.js +1 -1
  18. package/src/routeArticlesModule.js +12 -0
  19. package/src/routeEventsModule.js +12 -0
  20. package/src/routePagesModule.js +12 -0
  21. package/src/styles/application.css +1 -2
  22. package/src/tests/handlers/article_revisions/CancelScheduledHandler.test/create.test.js +90 -0
  23. package/src/tests/handlers/article_revisions/PublishesHandler.test/create.test.js +187 -2
  24. package/src/tests/handlers/article_revisions/UnlocksHandler.test/create.test.js +2 -2
  25. package/src/tests/handlers/event_revisions/CancelScheduledHandler.test/create.test.js +90 -0
  26. package/src/tests/handlers/event_revisions/PublishesHandler.test/create.test.js +187 -2
  27. package/src/tests/handlers/event_revisions/UnlocksHandler.test/create.test.js +2 -2
  28. package/src/tests/handlers/page_revisions/CancelScheduledHandler.test/create.test.js +86 -0
  29. package/src/tests/handlers/page_revisions/PublishesHandler.test/create.test.js +187 -2
  30. package/src/tests/handlers/page_revisions/UnlocksHandler.test/create.test.js +2 -2
  31. package/src/tests/support/factory.js +16 -0
  32. package/src/views/article_revisions/publishes/_form.ejs +4 -1
  33. package/src/views/articles/show.ejs +117 -4
  34. package/src/views/event_revisions/publishes/_form.ejs +4 -1
  35. package/src/views/events/show.ejs +117 -4
  36. package/src/views/layouts/application.ejs +15 -0
  37. package/src/views/page_revisions/publishes/_form.ejs +4 -1
  38. package/src/views/pages/show.ejs +117 -4
@@ -34,7 +34,20 @@
34
34
  <% } %>
35
35
  </div>
36
36
 
37
- <% if (revisions.length) { %>
37
+ <%
38
+ const openedRevisions = []
39
+ const scheduledRevisions = []
40
+
41
+ revisions.forEach(r => {
42
+ if (r.schedule) {
43
+ scheduledRevisions.push(r)
44
+ } else {
45
+ openedRevisions.push(r)
46
+ }
47
+ })
48
+ %>
49
+
50
+ <% if (openedRevisions.length) { %>
38
51
  <div class="pb-8">
39
52
  <h4 class="pb-4 heading-3 flex items-center gap-2">
40
53
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
@@ -56,9 +69,9 @@
56
69
  </thead>
57
70
 
58
71
  <tbody>
59
- <% revisions.forEach((revision, idx)=> { %>
72
+ <% openedRevisions.forEach((revision, idx)=> { %>
60
73
  <tr class="border-b border-mono-25">
61
- <td class="py-4 pl-2 w-full">
74
+ <td class="py-4 pl-2 w-1/2">
62
75
  <div class="flex gap-1 items-center">
63
76
  <% if (revision.meta && revision.meta.locked) { %>
64
77
  <div title="<%= revision.meta.lockMessage %>">
@@ -75,7 +88,9 @@
75
88
  <td class="whitespace-nowrap">
76
89
  <div class="body-3 text-raketa-foreground/50">
77
90
  <div class="flex items-center gap-1" title="<%= revision.meta.operatorMeta.name %>">
91
+ <% if (revision.meta.operatorMeta.avatar) { %>
78
92
  <img src="<%= revision.meta.operatorMeta.avatar %>" class="size-4 rounded-full">
93
+ <% } %>
79
94
  <%= revision.meta.operatorMeta.name %>
80
95
  </div>
81
96
  </div>
@@ -103,6 +118,104 @@
103
118
  </div>
104
119
  <% } %>
105
120
 
121
+ <% if (scheduledRevisions.length) { %>
122
+ <div class="pb-8">
123
+ <h4 class="pb-4 heading-3 flex items-center gap-2">
124
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
125
+ <path fill-rule="evenodd" d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0 0 16.5 9h-1.875a1.875 1.875 0 0 1-1.875-1.875V5.25A3.75 3.75 0 0 0 9 1.5H5.625ZM7.5 15a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 7.5 15Zm.75 2.25a.75.75 0 0 0 0 1.5H12a.75.75 0 0 0 0-1.5H8.25Z" clip-rule="evenodd" />
126
+ <path d="M12.971 1.816A5.23 5.23 0 0 1 14.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 0 1 3.434 1.279 9.768 9.768 0 0 0-6.963-6.963Z" />
127
+ </svg>
128
+
129
+ Scheduled for publication
130
+ </h4>
131
+
132
+ <table class="data-grid alt">
133
+ <thead>
134
+ <tr>
135
+ <th>Title</th>
136
+ <th>Created by</th>
137
+ <th>Scheduled by</th>
138
+ <th>Publish on</th>
139
+ <th>&nbsp;</th>
140
+ </tr>
141
+ </thead>
142
+
143
+ <tbody>
144
+ <% scheduledRevisions.forEach((revision, idx)=> { %>
145
+ <tr class="border-b border-mono-25">
146
+ <td class="py-4 pl-2 w-1/2">
147
+ <div class="flex gap-1 items-center">
148
+ <%= revision.title %>
149
+ </div>
150
+ </td>
151
+
152
+ <td class="whitespace-nowrap">
153
+ <div class="body-3 text-raketa-foreground/50">
154
+ <div class="flex items-center gap-1" title="<%= revision.meta.operatorMeta.name %>">
155
+ <% if (revision.meta.operatorMeta.avatar) { %>
156
+ <img src="<%= revision.meta.operatorMeta.avatar %>" class="size-4 rounded-full">
157
+ <% } %>
158
+ <%= revision.meta.operatorMeta.name %>
159
+ </div>
160
+ </div>
161
+ </td>
162
+
163
+ <td class="whitespace-nowrap">
164
+ <div class="body-3 text-raketa-foreground/50">
165
+ <div class="flex items-center gap-1" title="<%= revision.schedule.operatorMeta.name %>">
166
+ <% if (revision.schedule.operatorMeta.avatar) { %>
167
+ <img src="<%= revision.schedule.operatorMeta.avatar %>" class="size-4 rounded-full">
168
+ <% } %>
169
+ <%= revision.schedule.operatorMeta.name %>
170
+ </div>
171
+ </div>
172
+ </td>
173
+
174
+ <td class="whitespace-nowrap">
175
+ <div class="body-3 text-raketa-foreground/50">
176
+ <div class="flex items-center gap-1">
177
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4 text-raketa-foreground" viewBox="0 0 512 512">
178
+ <path d="M112.91 128A191.85 191.85 0 0064 254c-1.18 106.35 85.65 193.8 192 194 106.2.2 192-85.83 192-192 0-104.54-83.55-189.61-187.5-192a4.36 4.36 0 00-4.5 4.37V152" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" />
179
+ <path d="M233.38 278.63l-79-113a8.13 8.13 0 0111.32-11.32l113 79a32.5 32.5 0 01-37.25 53.26 33.21 33.21 0 01-8.07-7.94z" />
180
+ </svg>
181
+
182
+
183
+ <time data-pretty-expiration-time datetime="<%= revision.schedule.mergeAt %>"><%= revision.schedule.mergeAt %></time>
184
+ </div>
185
+ </div>
186
+ </td>
187
+
188
+ <td class="whitespace-nowrap">
189
+ <div class="actions-toolbar justify-end">
190
+ <form action="<%= `/${_context.locale}/${_context.resourceConfig.eventType}_revisions/${revision.id}/cancel_schedules` %>" method="post" class="inline-flex gap-2 items-center">
191
+ <%- f.submit('Remove schedule', { class: 'btn-text' }) %>
192
+ </form>
193
+
194
+ <button hx-delete="<%= `/${_context.locale}/${_context.resourceConfig.eventType}_revisions/${revision.id}` %>" hx-confirm="Are you sure?" type="button" class="btn-danger has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
195
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
196
+ <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" />
197
+ </svg>
198
+
199
+ Delete
200
+ </button>
201
+
202
+ <a href="/remote-login?redirect_to=/admin/<%= _context.resourceConfig.eventType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
203
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
204
+ <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
205
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
206
+ </svg>
207
+
208
+ Preview
209
+ </a>
210
+ </div>
211
+ </td>
212
+ </tr>
213
+ <% }); %>
214
+ </tbody>
215
+ </table>
216
+ </div>
217
+ <% } %>
218
+
106
219
  <div>
107
220
  <h4 class="pb-4 heading-3 items-center gap-2 flex">
108
221
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
@@ -166,4 +279,4 @@
166
279
  </tbody>
167
280
  </table>
168
281
  </div>
169
- </div>
282
+ </div>
@@ -217,6 +217,21 @@
217
217
  timeStyle: "short"
218
218
  })
219
219
  })
220
+
221
+ document.querySelectorAll('time[data-pretty-expiration-time]').forEach(item => {
222
+ const dateStr = item.getAttribute("datetime");
223
+
224
+ const expTime = new Date(dateStr)
225
+
226
+ item.innerText = expTime.toLocaleString('en-GB', {
227
+ dateStyle: "short",
228
+ timeStyle: "short"
229
+ })
230
+
231
+ if (new Date() > expTime) {
232
+ item.style.color = 'red';
233
+ }
234
+ })
220
235
  })
221
236
  </script>
222
237
  </body>
@@ -6,6 +6,9 @@
6
6
 
7
7
  <%- f.field('publishing.title'), { required: true, hint: "Appears in the history of changes" } %>
8
8
  <%- f.field('publishing.description', { as: "textarea", hint: "Provide optional details" }) %>
9
+
10
+ <%- f.field('publishing.mergeAt', { type: 'datetime-local', label: 'Publish revision at (UTC)' }) %>
11
+
9
12
  <%- f.field('publishing.visibility', { as: 'select', required: true, options: visibilityOptions }) %>
10
13
  <%- f.field('publishing.username', { required: true }) %>
11
14
  <%- f.field('publishing.password', { required: true }) %>
@@ -37,4 +40,4 @@
37
40
 
38
41
  visibilityEl.addEventListener("change", (e) => handleVisibilityChange(e.target.value));
39
42
  handleVisibilityChange(visibilityEl.value);
40
- </script>
43
+ </script>
@@ -35,7 +35,20 @@
35
35
  <% } %>
36
36
  </div>
37
37
 
38
- <% if (revisions.length) { %>
38
+ <%
39
+ const openedRevisions = []
40
+ const scheduledRevisions = []
41
+
42
+ revisions.forEach(r => {
43
+ if (r.schedule) {
44
+ scheduledRevisions.push(r)
45
+ } else {
46
+ openedRevisions.push(r)
47
+ }
48
+ })
49
+ %>
50
+
51
+ <% if (openedRevisions.length) { %>
39
52
  <div class="pb-8">
40
53
  <h4 class="pb-4 heading-3 flex items-center gap-2">
41
54
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
@@ -57,9 +70,9 @@
57
70
  </thead>
58
71
 
59
72
  <tbody>
60
- <% revisions.forEach((revision, idx)=> { %>
73
+ <% openedRevisions.forEach((revision, idx)=> { %>
61
74
  <tr class="border-b border-mono-25">
62
- <td class="py-4 pl-2 w-full">
75
+ <td class="py-4 pl-2 w-1/2">
63
76
  <div class="flex gap-1 items-center">
64
77
  <% if (revision.meta && revision.meta.locked) { %>
65
78
  <div title="<%= revision.meta.lockMessage %>">
@@ -76,7 +89,9 @@
76
89
  <td class="whitespace-nowrap">
77
90
  <div class="body-3 text-raketa-foreground/50">
78
91
  <div class="flex items-center gap-1" title="<%= revision.meta.operatorMeta.name %>">
92
+ <% if (revision.meta.operatorMeta.avatar) { %>
79
93
  <img src="<%= revision.meta.operatorMeta.avatar %>" class="size-4 rounded-full">
94
+ <% } %>
80
95
  <%= revision.meta.operatorMeta.name %>
81
96
  </div>
82
97
  </div>
@@ -104,6 +119,104 @@
104
119
  </div>
105
120
  <% } %>
106
121
 
122
+ <% if (scheduledRevisions.length) { %>
123
+ <div class="pb-8">
124
+ <h4 class="pb-4 heading-3 flex items-center gap-2">
125
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
126
+ <path fill-rule="evenodd" d="M5.625 1.5c-1.036 0-1.875.84-1.875 1.875v17.25c0 1.035.84 1.875 1.875 1.875h12.75c1.035 0 1.875-.84 1.875-1.875V12.75A3.75 3.75 0 0 0 16.5 9h-1.875a1.875 1.875 0 0 1-1.875-1.875V5.25A3.75 3.75 0 0 0 9 1.5H5.625ZM7.5 15a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5A.75.75 0 0 1 7.5 15Zm.75 2.25a.75.75 0 0 0 0 1.5H12a.75.75 0 0 0 0-1.5H8.25Z" clip-rule="evenodd" />
127
+ <path d="M12.971 1.816A5.23 5.23 0 0 1 14.25 5.25v1.875c0 .207.168.375.375.375H16.5a5.23 5.23 0 0 1 3.434 1.279 9.768 9.768 0 0 0-6.963-6.963Z" />
128
+ </svg>
129
+
130
+ Scheduled for publication
131
+ </h4>
132
+
133
+ <table class="data-grid alt">
134
+ <thead>
135
+ <tr>
136
+ <th>Title</th>
137
+ <th>Created by</th>
138
+ <th>Scheduled by</th>
139
+ <th>Publish on</th>
140
+ <th>&nbsp;</th>
141
+ </tr>
142
+ </thead>
143
+
144
+ <tbody>
145
+ <% scheduledRevisions.forEach((revision, idx)=> { %>
146
+ <tr class="border-b border-mono-25">
147
+ <td class="py-4 pl-2 w-1/2">
148
+ <div class="flex gap-1 items-center">
149
+ <%= revision.title %>
150
+ </div>
151
+ </td>
152
+
153
+ <td class="whitespace-nowrap">
154
+ <div class="body-3 text-raketa-foreground/50">
155
+ <div class="flex items-center gap-1" title="<%= revision.meta.operatorMeta.name %>">
156
+ <% if (revision.meta.operatorMeta.avatar) { %>
157
+ <img src="<%= revision.meta.operatorMeta.avatar %>" class="size-4 rounded-full">
158
+ <% } %>
159
+ <%= revision.meta.operatorMeta.name %>
160
+ </div>
161
+ </div>
162
+ </td>
163
+
164
+ <td class="whitespace-nowrap">
165
+ <div class="body-3 text-raketa-foreground/50">
166
+ <div class="flex items-center gap-1" title="<%= revision.schedule.operatorMeta.name %>">
167
+ <% if (revision.schedule.operatorMeta.avatar) { %>
168
+ <img src="<%= revision.schedule.operatorMeta.avatar %>" class="size-4 rounded-full">
169
+ <% } %>
170
+ <%= revision.schedule.operatorMeta.name %>
171
+ </div>
172
+ </div>
173
+ </td>
174
+
175
+ <td class="whitespace-nowrap">
176
+ <div class="body-3 text-raketa-foreground/50">
177
+ <div class="flex items-center gap-1">
178
+ <svg xmlns="http://www.w3.org/2000/svg" class="size-4 text-raketa-foreground" viewBox="0 0 512 512">
179
+ <path d="M112.91 128A191.85 191.85 0 0064 254c-1.18 106.35 85.65 193.8 192 194 106.2.2 192-85.83 192-192 0-104.54-83.55-189.61-187.5-192a4.36 4.36 0 00-4.5 4.37V152" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" />
180
+ <path d="M233.38 278.63l-79-113a8.13 8.13 0 0111.32-11.32l113 79a32.5 32.5 0 01-37.25 53.26 33.21 33.21 0 01-8.07-7.94z" />
181
+ </svg>
182
+
183
+
184
+ <time data-pretty-expiration-time datetime="<%= revision.schedule.mergeAt %>"><%= revision.schedule.mergeAt %></time>
185
+ </div>
186
+ </div>
187
+ </td>
188
+
189
+ <td class="whitespace-nowrap">
190
+ <div class="actions-toolbar justify-end">
191
+ <form action="<%= `/${_context.locale}/${_context.resourceConfig.pageType}_revisions/${revision.id}/cancel_schedules` %>" method="post" class="inline-flex gap-2 items-center">
192
+ <%- f.submit('Remove schedule', { class: 'btn-text' }) %>
193
+ </form>
194
+
195
+ <button hx-delete="<%= `/${_context.locale}/${_context.resourceConfig.pageType}_revisions/${revision.id}` %>" hx-confirm="Are you sure?" type="button" class="btn-danger has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
196
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
197
+ <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" />
198
+ </svg>
199
+
200
+ Delete
201
+ </button>
202
+
203
+ <a href="/remote-login?redirect_to=/admin/<%= _context.resourceConfig.pageType %>-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon">
204
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
205
+ <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
206
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
207
+ </svg>
208
+
209
+ Preview
210
+ </a>
211
+ </div>
212
+ </td>
213
+ </tr>
214
+ <% }); %>
215
+ </tbody>
216
+ </table>
217
+ </div>
218
+ <% } %>
219
+
107
220
  <div>
108
221
  <h4 class="pb-4 heading-3 items-center gap-2 flex">
109
222
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
@@ -167,4 +280,4 @@
167
280
  </tbody>
168
281
  </table>
169
282
  </div>
170
- </div>
283
+ </div>