@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.
- package/package.json +1 -1
- package/src/cloud/ArticleRevisions.js +30 -0
- package/src/cloud/EventRevisions.js +30 -0
- package/src/cloud/PageRevisions.js +30 -0
- package/src/cloud/documents/articlesDocuments.js +24 -0
- package/src/cloud/documents/common.js +13 -0
- package/src/cloud/documents/eventsDocuments.js +24 -0
- package/src/cloud/documents/pagesDocuments.js +24 -0
- package/src/handlers/article_revisions/CancelSchedulesHandler.js +26 -0
- package/src/handlers/article_revisions/PublishesHandler.js +39 -10
- package/src/handlers/article_revisions/UnlocksHandler.js +1 -1
- package/src/handlers/event_revisions/CancelSchedulesHandler.js +26 -0
- package/src/handlers/event_revisions/PublishesHandler.js +34 -7
- package/src/handlers/event_revisions/UnlocksHandler.js +3 -1
- package/src/handlers/page_revisions/CancelSchedulesHandler.js +26 -0
- package/src/handlers/page_revisions/PublishesHandler.js +34 -7
- package/src/handlers/page_revisions/UnlocksHandler.js +1 -1
- package/src/routeArticlesModule.js +12 -0
- package/src/routeEventsModule.js +12 -0
- package/src/routePagesModule.js +12 -0
- package/src/styles/application.css +1 -2
- package/src/tests/handlers/article_revisions/CancelScheduledHandler.test/create.test.js +90 -0
- package/src/tests/handlers/article_revisions/PublishesHandler.test/create.test.js +187 -2
- package/src/tests/handlers/article_revisions/UnlocksHandler.test/create.test.js +2 -2
- package/src/tests/handlers/event_revisions/CancelScheduledHandler.test/create.test.js +90 -0
- package/src/tests/handlers/event_revisions/PublishesHandler.test/create.test.js +187 -2
- package/src/tests/handlers/event_revisions/UnlocksHandler.test/create.test.js +2 -2
- package/src/tests/handlers/page_revisions/CancelScheduledHandler.test/create.test.js +86 -0
- package/src/tests/handlers/page_revisions/PublishesHandler.test/create.test.js +187 -2
- package/src/tests/handlers/page_revisions/UnlocksHandler.test/create.test.js +2 -2
- package/src/tests/support/factory.js +16 -0
- package/src/views/article_revisions/publishes/_form.ejs +4 -1
- package/src/views/articles/show.ejs +117 -4
- package/src/views/event_revisions/publishes/_form.ejs +4 -1
- package/src/views/events/show.ejs +117 -4
- package/src/views/layouts/application.ejs +15 -0
- package/src/views/page_revisions/publishes/_form.ejs +4 -1
- package/src/views/pages/show.ejs +117 -4
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import Factory from "../../../support/factory";
|
|
2
|
+
import PageRevisions from "../../../../cloud/PageRevisions";
|
|
3
|
+
import CancelSchedulesHandler from "../../../../handlers/page_revisions/CancelSchedulesHandler";
|
|
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 schedule cancel", () => {
|
|
20
|
+
test("cancel of schedule successful", async () => {
|
|
21
|
+
const revision = Factory.build("page_revision");
|
|
22
|
+
const ctx = buildCtx(revision);
|
|
23
|
+
|
|
24
|
+
const mockUnlock = jest
|
|
25
|
+
.spyOn(ctx.client.pageRevisions, "cancelSchedule")
|
|
26
|
+
.mockImplementation(() => ({
|
|
27
|
+
revision: revision,
|
|
28
|
+
errors: null,
|
|
29
|
+
pageErrors: null,
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
const result = await CancelSchedulesHandler.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
|
+
{
|
|
46
|
+
key: "generalError",
|
|
47
|
+
message: "Failed to cancel schedule for revision",
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const mockUnlock = jest
|
|
52
|
+
.spyOn(ctx.client.pageRevisions, "cancelSchedule")
|
|
53
|
+
.mockImplementation(() => ({ revision: null, errors, pageErrors: null }));
|
|
54
|
+
|
|
55
|
+
await expect(CancelSchedulesHandler.create(ctx)).rejects.toThrow(
|
|
56
|
+
`Failed to cancel schedule for revision: ${JSON.stringify(errors)}`
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
expect(mockUnlock).toHaveBeenCalledWith(revision.id, "en");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("unlock failed with page errors", async () => {
|
|
63
|
+
const revision = Factory.build("page_revision");
|
|
64
|
+
const ctx = buildCtx(revision);
|
|
65
|
+
const pageErrors = [
|
|
66
|
+
{
|
|
67
|
+
key: "generalError",
|
|
68
|
+
message: "Failed to cancel schedule for revision",
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
const mockUnlock = jest
|
|
73
|
+
.spyOn(ctx.client.pageRevisions, "cancelSchedule")
|
|
74
|
+
.mockImplementation(() => ({
|
|
75
|
+
revision: null,
|
|
76
|
+
errors: null,
|
|
77
|
+
pageErrors,
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
await expect(CancelSchedulesHandler.create(ctx)).rejects.toThrow(
|
|
81
|
+
`Failed to cancel schedule for revision: ${JSON.stringify(pageErrors)}`
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(mockUnlock).toHaveBeenCalledWith(revision.id, "en");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -21,7 +21,7 @@ function buildCtx(revision, resourceParams) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
describe("Publish page revision", () => {
|
|
24
|
-
test("create successful", async () => {
|
|
24
|
+
test("create successful for publishing", async () => {
|
|
25
25
|
const revision = Factory.build("page_revision");
|
|
26
26
|
const publishing = {
|
|
27
27
|
title: "A new revision!",
|
|
@@ -80,7 +80,7 @@ describe("Publish page revision", () => {
|
|
|
80
80
|
});
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
test("create failed", async () => {
|
|
83
|
+
test("create failed for publishing", async () => {
|
|
84
84
|
const revision = Factory.build("page_revision");
|
|
85
85
|
const publishing = {
|
|
86
86
|
title: "A new revision!",
|
|
@@ -133,6 +133,191 @@ describe("Publish page revision", () => {
|
|
|
133
133
|
errors: {
|
|
134
134
|
url: "Oops",
|
|
135
135
|
},
|
|
136
|
+
pageErrors: null,
|
|
137
|
+
_translations: [],
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("create successful for scheduling", async () => {
|
|
143
|
+
const revision = Factory.build("page_revision");
|
|
144
|
+
const schedule = Factory.build("revision_schedule");
|
|
145
|
+
const publishing = {
|
|
146
|
+
mergeAt: "2024-12-20T20:20",
|
|
147
|
+
title: "A new revision!",
|
|
148
|
+
description: "Nice!",
|
|
149
|
+
visibility: "protected",
|
|
150
|
+
username: "admin",
|
|
151
|
+
password: "admin123!@#",
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const ctx = buildCtx(revision, {
|
|
155
|
+
publishing,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const updatedRevision = { ...revision, schedule: { ...schedule } };
|
|
159
|
+
|
|
160
|
+
const mockFind = jest
|
|
161
|
+
.spyOn(ctx.client.pageRevisions, "find")
|
|
162
|
+
.mockImplementation(() => revision);
|
|
163
|
+
|
|
164
|
+
const mockSchedule = jest
|
|
165
|
+
.spyOn(ctx.client.pageRevisions, "schedule")
|
|
166
|
+
.mockImplementation(() => ({
|
|
167
|
+
revision: updatedRevision,
|
|
168
|
+
errors: null,
|
|
169
|
+
pageErrors: null,
|
|
170
|
+
}));
|
|
171
|
+
|
|
172
|
+
const result = await PublishesHandler.create(ctx);
|
|
173
|
+
|
|
174
|
+
expect(mockFind).toHaveBeenCalledWith(revision.id, "en");
|
|
175
|
+
expect(mockSchedule).toHaveBeenCalledWith(
|
|
176
|
+
revision.id,
|
|
177
|
+
"en",
|
|
178
|
+
{
|
|
179
|
+
title: publishing.title,
|
|
180
|
+
description: publishing.description,
|
|
181
|
+
mergeAt: "2024-12-20T20:20:00Z",
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
visibility: publishing.visibility,
|
|
185
|
+
settings: JSON.stringify({
|
|
186
|
+
...revision.settings,
|
|
187
|
+
credentials: {
|
|
188
|
+
user: publishing.username,
|
|
189
|
+
password: publishing.password,
|
|
190
|
+
},
|
|
191
|
+
}),
|
|
192
|
+
}
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
expect(result).toEqual({
|
|
196
|
+
redirect: `/en/pages/${updatedRevision.originalId}`,
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("create failed for scheduling - pageErrors", async () => {
|
|
201
|
+
const revision = Factory.build("page_revision");
|
|
202
|
+
const publishing = {
|
|
203
|
+
mergeAt: "2024-12-20T20:20",
|
|
204
|
+
title: "A new revision!",
|
|
205
|
+
description: "Nice!",
|
|
206
|
+
visibility: "public",
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const ctx = buildCtx(revision, {
|
|
210
|
+
publishing,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const mockFind = jest
|
|
214
|
+
.spyOn(ctx.client.pageRevisions, "find")
|
|
215
|
+
.mockImplementation(() => revision);
|
|
216
|
+
|
|
217
|
+
const mockSchedule = jest
|
|
218
|
+
.spyOn(ctx.client.pageRevisions, "schedule")
|
|
219
|
+
.mockImplementation(() => ({
|
|
220
|
+
revision: null,
|
|
221
|
+
pageErrors: [{ key: "slug", message: "Oops" }],
|
|
222
|
+
errors: null,
|
|
223
|
+
}));
|
|
224
|
+
|
|
225
|
+
const result = await PublishesHandler.create(ctx);
|
|
226
|
+
|
|
227
|
+
expect(mockFind).toHaveBeenCalledWith(revision.id, "en");
|
|
228
|
+
expect(mockSchedule).toHaveBeenCalledWith(
|
|
229
|
+
revision.id,
|
|
230
|
+
"en",
|
|
231
|
+
{
|
|
232
|
+
title: publishing.title,
|
|
233
|
+
description: publishing.description,
|
|
234
|
+
mergeAt: "2024-12-20T20:20:00Z",
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
visibility: publishing.visibility,
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
expect(result).toEqual({
|
|
242
|
+
assigns: {
|
|
243
|
+
publishing: {
|
|
244
|
+
id: revision.id,
|
|
245
|
+
originalId: revision.originalId,
|
|
246
|
+
title: publishing.title,
|
|
247
|
+
mergeAt: "2024-12-20T20:20",
|
|
248
|
+
description: publishing.description,
|
|
249
|
+
visibility: publishing.visibility,
|
|
250
|
+
username: publishing.username,
|
|
251
|
+
password: publishing.password,
|
|
252
|
+
},
|
|
253
|
+
visibilityOptions: ctx.client.pages.visibilityOptions(),
|
|
254
|
+
pageErrors: {
|
|
255
|
+
slug: "Oops",
|
|
256
|
+
},
|
|
257
|
+
errors: null,
|
|
258
|
+
_translations: [],
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("create failed for scheduling - errors", async () => {
|
|
264
|
+
const revision = Factory.build("page_revision");
|
|
265
|
+
const publishing = {
|
|
266
|
+
mergeAt: "2024-12-20T20:20",
|
|
267
|
+
title: "A new revision!",
|
|
268
|
+
description: "Nice!",
|
|
269
|
+
visibility: "public",
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const ctx = buildCtx(revision, {
|
|
273
|
+
publishing,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
const mockFind = jest
|
|
277
|
+
.spyOn(ctx.client.pageRevisions, "find")
|
|
278
|
+
.mockImplementation(() => revision);
|
|
279
|
+
|
|
280
|
+
const mockSchedule = jest
|
|
281
|
+
.spyOn(ctx.client.pageRevisions, "schedule")
|
|
282
|
+
.mockImplementation(() => ({
|
|
283
|
+
revision: null,
|
|
284
|
+
errors: [{ key: "slug", message: "Oops" }],
|
|
285
|
+
pageErrors: null,
|
|
286
|
+
}));
|
|
287
|
+
|
|
288
|
+
const result = await PublishesHandler.create(ctx);
|
|
289
|
+
|
|
290
|
+
expect(mockFind).toHaveBeenCalledWith(revision.id, "en");
|
|
291
|
+
expect(mockSchedule).toHaveBeenCalledWith(
|
|
292
|
+
revision.id,
|
|
293
|
+
"en",
|
|
294
|
+
{
|
|
295
|
+
title: publishing.title,
|
|
296
|
+
description: publishing.description,
|
|
297
|
+
mergeAt: "2024-12-20T20:20:00Z",
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
visibility: publishing.visibility,
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
expect(result).toEqual({
|
|
305
|
+
assigns: {
|
|
306
|
+
publishing: {
|
|
307
|
+
id: revision.id,
|
|
308
|
+
originalId: revision.originalId,
|
|
309
|
+
title: publishing.title,
|
|
310
|
+
mergeAt: "2024-12-20T20:20",
|
|
311
|
+
description: publishing.description,
|
|
312
|
+
visibility: publishing.visibility,
|
|
313
|
+
username: publishing.username,
|
|
314
|
+
password: publishing.password,
|
|
315
|
+
},
|
|
316
|
+
visibilityOptions: ctx.client.pages.visibilityOptions(),
|
|
317
|
+
errors: {
|
|
318
|
+
slug: "Oops",
|
|
319
|
+
},
|
|
320
|
+
pageErrors: null,
|
|
136
321
|
_translations: [],
|
|
137
322
|
},
|
|
138
323
|
});
|
|
@@ -60,7 +60,7 @@ describe("Page revision unlock", () => {
|
|
|
60
60
|
const revision = Factory.build("page_revision");
|
|
61
61
|
const ctx = buildCtx(revision);
|
|
62
62
|
const pageErrors = [
|
|
63
|
-
{ key: "generalError", message: "Failed to
|
|
63
|
+
{ key: "generalError", message: "Failed to unlock revision" },
|
|
64
64
|
];
|
|
65
65
|
|
|
66
66
|
const mockUnlock = jest
|
|
@@ -72,7 +72,7 @@ describe("Page revision unlock", () => {
|
|
|
72
72
|
}));
|
|
73
73
|
|
|
74
74
|
await expect(UnlocksHandler.create(ctx)).rejects.toThrow(
|
|
75
|
-
`Failed to
|
|
75
|
+
`Failed to unlock revision: ${JSON.stringify(pageErrors)}`
|
|
76
76
|
);
|
|
77
77
|
|
|
78
78
|
expect(mockUnlock).toHaveBeenCalledWith(revision.id, "en");
|
|
@@ -13,6 +13,21 @@ const REVISION_META = {
|
|
|
13
13
|
},
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
+
const REVISION_SCHEDULE = {
|
|
17
|
+
id: "1",
|
|
18
|
+
title: "New Schedule",
|
|
19
|
+
description: "Scheduled due to some campaign",
|
|
20
|
+
operator: "7a456cdd-7278-4610-8b82-5b93cfcae396",
|
|
21
|
+
operatorMeta: {
|
|
22
|
+
name: "Jane Doe",
|
|
23
|
+
roles: [],
|
|
24
|
+
active: true,
|
|
25
|
+
avatar: "",
|
|
26
|
+
user_pool: "Raketa",
|
|
27
|
+
user_pool_id: "some-user-pool-slug",
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
16
31
|
const PAGE = {
|
|
17
32
|
id: "2",
|
|
18
33
|
slug: "page-revision",
|
|
@@ -140,6 +155,7 @@ const FIXTURES = {
|
|
|
140
155
|
createdAt: "2024-08-30T19:00:00Z",
|
|
141
156
|
},
|
|
142
157
|
revision_meta: { ...REVISION_META },
|
|
158
|
+
revision_schedule: { ...REVISION_SCHEDULE },
|
|
143
159
|
page: { ...PAGE },
|
|
144
160
|
page_revision: { ...PAGE, meta: { ...REVISION_META }, originalId: "1" },
|
|
145
161
|
page_change: { ...PAGE_CHANGE },
|
|
@@ -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>
|
|
@@ -34,7 +34,20 @@
|
|
|
34
34
|
<% } %>
|
|
35
35
|
</div>
|
|
36
36
|
|
|
37
|
-
<%
|
|
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
|
-
<%
|
|
72
|
+
<% openedRevisions.forEach((revision, idx)=> { %>
|
|
60
73
|
<tr class="border-b border-mono-25">
|
|
61
|
-
<td class="py-4 pl-2 w-
|
|
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> </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.articleType}_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.articleType}_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.articleType %>-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>
|
|
@@ -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>
|