@raketa-cloud/admin 0.0.14 → 0.0.15
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/ArticleChanges.js +15 -0
- package/src/cloud/ArticleRevisions.js +152 -0
- package/src/cloud/Articles.js +133 -0
- package/src/cloud/documents/articlesDocuments.js +109 -469
- package/src/cloud/documents/common.js +10 -0
- package/src/handlers/article_revisions/ArticleRevisionsHandler.js +49 -0
- package/src/handlers/article_revisions/CodeHandler.js +90 -0
- package/src/handlers/article_revisions/GeneralHandler.js +95 -0
- package/src/handlers/article_revisions/LocksHandler.js +54 -0
- package/src/handlers/article_revisions/MetaHandler.js +90 -0
- package/src/handlers/article_revisions/PublishesHandler.js +90 -0
- package/src/handlers/article_revisions/RevertsHandler.js +28 -0
- package/src/handlers/article_revisions/TagHandler.js +89 -0
- package/src/handlers/article_revisions/UnlocksHandler.js +22 -0
- package/src/handlers/article_revisions/VisualHandler.js +84 -0
- package/src/handlers/article_revisions/WidgetHandler.js +47 -0
- package/src/handlers/articles/ArticlesHandler.js +119 -0
- package/src/handlers/articles/ClonesHandler.js +17 -0
- package/src/handlers/articles/DeletesHandler.js +68 -0
- package/src/handlers/articles/TranslationsHandler.js +103 -0
- package/src/handlers/articles/URLsHandler.js +71 -0
- package/src/handlers/pages/PagesHandler.js +4 -2
- package/src/handlers/pages/TranslationsHandler.js +7 -5
- package/src/index.js +22 -0
- package/src/routeArticles.js +65 -0
- package/src/routeStandard.js +2 -0
- package/src/setupCloud.js +12 -0
- package/src/tests/handlers/articles/ArticlesHandler.test/create.test.js +144 -0
- package/src/tests/handlers/articles/ArticlesHandler.test/create_form.test.js +41 -0
- package/src/tests/handlers/articles/ArticlesHandler.test/index.test.js +49 -0
- package/src/tests/handlers/articles/ArticlesHandler.test/show.test.js +105 -0
- package/src/tests/handlers/articles/ConesHandler.test/create.test.js +54 -0
- package/src/tests/handlers/articles/DeletesHandler.test/create.test.js +110 -0
- package/src/tests/handlers/articles/DeletesHandler.test/create_form.test.js +54 -0
- package/src/tests/handlers/articles/URLsHandler.test/create.test.js +155 -0
- package/src/tests/handlers/articles/URLsHandler.test/create_form.test.js +51 -0
- package/src/tests/handlers/pages/PagesHandler.test/create.test.js +3 -3
- package/src/utils.js +46 -0
- package/src/views/article_revisions/_nav.ejs +40 -0
- package/src/views/article_revisions/codes/edit_form.ejs +39 -0
- package/src/views/article_revisions/general/edit_form.ejs +70 -0
- package/src/views/article_revisions/locks/create_form.ejs +35 -0
- package/src/views/article_revisions/meta/edit_form.ejs +41 -0
- package/src/views/article_revisions/publishes/_form.ejs +57 -0
- package/src/views/article_revisions/publishes/create_form.ejs +10 -0
- package/src/views/article_revisions/tags/edit_form.ejs +64 -0
- package/src/views/article_revisions/visuals/edit_form.ejs +42 -0
- package/src/views/articles/_form.ejs +86 -0
- package/src/views/articles/create_form.ejs +9 -0
- package/src/views/articles/deletes/create_form.ejs +55 -0
- package/src/views/articles/edit_form.ejs +3 -0
- package/src/views/articles/index.ejs +161 -0
- package/src/views/articles/show.ejs +281 -0
- package/src/views/articles/translations/_form.ejs +77 -0
- package/src/views/articles/translations/create_form.ejs +11 -0
- package/src/views/articles/urls/create_form.ejs +31 -0
- package/src/views/page_revisions/locks/create_form.ejs +1 -1
- package/test/factory.js +37 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
<div class="page-wrapper">
|
|
2
|
+
<div class="page-title">
|
|
3
|
+
<div class="flex items-center gap-4">
|
|
4
|
+
<h1 class="heading-1"><%= article.title %></h1>
|
|
5
|
+
<div class="flex flex-wrap items-center gap-1">
|
|
6
|
+
<% Object.keys(_context.locales).forEach(key => { %>
|
|
7
|
+
<% const { name, _code, flag} = _context.locales[key] %>
|
|
8
|
+
<% if (key === _context.locale) { %>
|
|
9
|
+
<img title="<%= name %>" src="<%= flag %>" alt="<%= name %>" class="size-6 rounded-full border dark:border-neutral-700" />
|
|
10
|
+
<% } else if (article.translations[key]) { %>
|
|
11
|
+
<a href="<%= `/${key}/articles/${article.translations[key].id}` %>">
|
|
12
|
+
<img title="<%= name %>" src="<%= flag %>" alt="<%= name %>" class="size-6 rounded-full border dark:border-neutral-700" />
|
|
13
|
+
</a>
|
|
14
|
+
<% } else { %>
|
|
15
|
+
<a href="<%= `/${_context.locale}/articles/${article.id}/translations/new?target_locale=${key}` %>">
|
|
16
|
+
<img title="<%= name %>" src="<%= flag %>" alt="<%= name %>" class="<%= [" transition-all ease-in-out duration-300 size-6 rounded-full border hover:opacity-100 dark:border-neutral-700", key === _context.locale ? "opacity-100" : "opacity-10"].join(" ") %>" />
|
|
17
|
+
</a>
|
|
18
|
+
<% } %>
|
|
19
|
+
<% }); %>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="actions-toolbar">
|
|
24
|
+
<form method="POST" action="<%= `/${_context.locale}/articles/${article.id}/article_revisions` %>" class="inline-block">
|
|
25
|
+
<button type="submit" class="btn-primary">
|
|
26
|
+
Start revision
|
|
27
|
+
</button>
|
|
28
|
+
</form>
|
|
29
|
+
|
|
30
|
+
<a href="<%= `/${_context.locale}/articles/${article.id}/urls/new` %>" class="btn-text has-icon">
|
|
31
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
32
|
+
<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" />
|
|
33
|
+
</svg>
|
|
34
|
+
|
|
35
|
+
Change URL
|
|
36
|
+
</a>
|
|
37
|
+
|
|
38
|
+
<form action="<%= `/${_context.locale}/articles/${article.id}/clones` %>" method="post" class="inline-block">
|
|
39
|
+
<button type="submit" class="btn-text has-icon">
|
|
40
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
41
|
+
<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" />
|
|
42
|
+
</svg>
|
|
43
|
+
|
|
44
|
+
Clone article
|
|
45
|
+
</button>
|
|
46
|
+
</form>
|
|
47
|
+
|
|
48
|
+
<a href="<%= `/${_context.locale}/articles/${article.id}/deletes/new` %>" class="btn-danger has-icon">
|
|
49
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
50
|
+
<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" />
|
|
51
|
+
</svg>
|
|
52
|
+
|
|
53
|
+
Delete article
|
|
54
|
+
</a>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<% if (revisions.length) { %>
|
|
59
|
+
<div class="pb-8">
|
|
60
|
+
<h4 class="pb-4 heading-3 flex items-center gap-2">
|
|
61
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
|
|
62
|
+
<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" />
|
|
63
|
+
<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" />
|
|
64
|
+
</svg>
|
|
65
|
+
|
|
66
|
+
Open revisions
|
|
67
|
+
</h4>
|
|
68
|
+
|
|
69
|
+
<table class="data-grid alt">
|
|
70
|
+
<thead>
|
|
71
|
+
<tr>
|
|
72
|
+
<th>Title</th>
|
|
73
|
+
<th>Editor</th>
|
|
74
|
+
<th>Last change</th>
|
|
75
|
+
<th> </th>
|
|
76
|
+
</tr>
|
|
77
|
+
</thead>
|
|
78
|
+
|
|
79
|
+
<tbody>
|
|
80
|
+
<% revisions.forEach((revision, idx)=> { %>
|
|
81
|
+
<tr class="border-b border-mono-25">
|
|
82
|
+
<td class="py-4 pl-2 w-full">
|
|
83
|
+
<div class="flex gap-1 items-center">
|
|
84
|
+
<% if (revision.meta && revision.meta.locked) { %>
|
|
85
|
+
<div title="<%= revision.meta.lockMessage %>">
|
|
86
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-4">
|
|
87
|
+
<path fill-rule="evenodd" d="M10 1a4.5 4.5 0 0 0-4.5 4.5V9H5a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2h-.5V5.5A4.5 4.5 0 0 0 10 1Zm3 8V5.5a3 3 0 1 0-6 0V9h6Z" clip-rule="evenodd" />
|
|
88
|
+
</svg>
|
|
89
|
+
</div>
|
|
90
|
+
<% } %>
|
|
91
|
+
|
|
92
|
+
<a href="/remote-login?redirect_to=/admin/article-revisions/<%= revision.id %>/builder" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
|
|
93
|
+
<%= revision.title %>
|
|
94
|
+
</a>
|
|
95
|
+
</div>
|
|
96
|
+
</td>
|
|
97
|
+
|
|
98
|
+
<td class="whitespace-nowrap">
|
|
99
|
+
<div class="body-3 text-raketa-foreground/50">
|
|
100
|
+
<div class="flex items-center gap-1" title="Yana Dimitrova">
|
|
101
|
+
<img src="<%= revision.meta.operatorMeta.avatar %>" class="size-4 rounded-full">
|
|
102
|
+
<%= revision.meta.operatorMeta.name %>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</td>
|
|
106
|
+
|
|
107
|
+
<td class="whitespace-nowrap">
|
|
108
|
+
<div class="body-3 text-raketa-foreground/50">
|
|
109
|
+
<div class="flex items-center gap-1">
|
|
110
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4 text-raketa-foreground">
|
|
111
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
|
112
|
+
</svg>
|
|
113
|
+
|
|
114
|
+
<%= (new Date(revision.insertedAt)).toLocaleString() %>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</td>
|
|
118
|
+
|
|
119
|
+
<td class="whitespace-nowrap">
|
|
120
|
+
<div class="actions-toolbar justify-end">
|
|
121
|
+
<a href="/remote-login?redirect_to=/admin/article-revisions/<%= revision.id %>/builder" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
|
|
122
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
123
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L6.832 19.82a4.5 4.5 0 0 1-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 0 1 1.13-1.897L16.863 4.487Zm0 0L19.5 7.125" />
|
|
124
|
+
</svg>
|
|
125
|
+
Edit content
|
|
126
|
+
</a>
|
|
127
|
+
|
|
128
|
+
<a href="<%= `/${_context.locale}/article_revisions/${revision.id}/publishes/new` %>" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
|
|
129
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
130
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15.59 14.37a6 6 0 0 1-5.84 7.38v-4.8m5.84-2.58a14.98 14.98 0 0 0 6.16-12.12A14.98 14.98 0 0 0 9.631 8.41m5.96 5.96a14.926 14.926 0 0 1-5.841 2.58m-.119-8.54a6 6 0 0 0-7.381 5.84h4.8m2.581-5.84a14.927 14.927 0 0 0-2.58 5.84m2.699 2.7c-.103.021-.207.041-.311.06a15.09 15.09 0 0 1-2.448-2.448 14.9 14.9 0 0 1 .06-.312m-2.24 2.39a4.493 4.493 0 0 0-1.757 4.306 4.493 4.493 0 0 0 4.306-1.758M16.5 9a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Z" />
|
|
131
|
+
</svg>
|
|
132
|
+
|
|
133
|
+
Publish
|
|
134
|
+
</a>
|
|
135
|
+
|
|
136
|
+
<details class="unstyled-details">
|
|
137
|
+
<summary class="cursor-pointer">
|
|
138
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
|
139
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 12.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 18.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z" />
|
|
140
|
+
</svg>
|
|
141
|
+
</summary>
|
|
142
|
+
|
|
143
|
+
<div class="absolute border bg-raketa-background p-4 right-4 z-20 mt-2 flex flex-col gap-4 shadow-md rounded dark:border-neutral-500">
|
|
144
|
+
<a href="<%= `/${_context.locale}/article_revisions/${revision.id}/general/edit` %>" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
|
|
145
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
146
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 0 1 1.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.559.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.894.149c-.424.07-.764.383-.929.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 0 1-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.398.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 0 1-.12-1.45l.527-.737c.25-.35.272-.806.108-1.204-.165-.397-.506-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.108-1.204l-.526-.738a1.125 1.125 0 0 1 .12-1.45l.773-.773a1.125 1.125 0 0 1 1.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894Z" />
|
|
147
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
|
148
|
+
</svg>
|
|
149
|
+
|
|
150
|
+
Edit settings
|
|
151
|
+
</a>
|
|
152
|
+
|
|
153
|
+
<a href="/remote-login?redirect_to=/admin/article-revisions/<%= revision.id %>/preview" target="_blank" class="btn-text has-icon <%= revision.meta && revision.meta.locked ? 'cursor-not-allowed text-gray-400 pointer-events-none' : '' %>">
|
|
154
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
155
|
+
<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" />
|
|
156
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
|
157
|
+
</svg>
|
|
158
|
+
|
|
159
|
+
Preview
|
|
160
|
+
</a>
|
|
161
|
+
|
|
162
|
+
<% if (revision.meta && revision.meta.locked) { %>
|
|
163
|
+
<form action="<%= `/${_context.locale}/article_revisions/${revision.id}/unlocks` %>" method="post" class="inline-flex gap-2 items-center">
|
|
164
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
165
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 10.5V6.75a4.5 4.5 0 1 1 9 0v3.75M3.75 21.75h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H3.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" />
|
|
166
|
+
</svg>
|
|
167
|
+
<%- f.submit('Unlock', { class: 'btn-text' }) %>
|
|
168
|
+
</form>
|
|
169
|
+
<% } else { %>
|
|
170
|
+
<a href="<%= `/${_context.locale}/article_revisions/${revision.id}/locks/new` %>" class="btn-text has-icon">
|
|
171
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
172
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z" />
|
|
173
|
+
</svg>
|
|
174
|
+
Lock
|
|
175
|
+
</a>
|
|
176
|
+
<% } %>
|
|
177
|
+
|
|
178
|
+
<button hx-delete="<%= `/${_context.locale}/article_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' : '' %>">
|
|
179
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
180
|
+
<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" />
|
|
181
|
+
</svg>
|
|
182
|
+
|
|
183
|
+
Delete
|
|
184
|
+
</button>
|
|
185
|
+
</div>
|
|
186
|
+
</details>
|
|
187
|
+
</div>
|
|
188
|
+
</td>
|
|
189
|
+
</tr>
|
|
190
|
+
<% }); %>
|
|
191
|
+
</tbody>
|
|
192
|
+
</table>
|
|
193
|
+
</div>
|
|
194
|
+
<% } %>
|
|
195
|
+
|
|
196
|
+
<div>
|
|
197
|
+
<h4 class="pb-4 heading-3 items-center gap-2 flex">
|
|
198
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-4 text-raketa-primary">
|
|
199
|
+
<path d="M3.375 3C2.339 3 1.5 3.84 1.5 4.875v.75c0 1.036.84 1.875 1.875 1.875h17.25c1.035 0 1.875-.84 1.875-1.875v-.75C22.5 3.839 21.66 3 20.625 3H3.375Z" />
|
|
200
|
+
<path fill-rule="evenodd" d="m3.087 9 .54 9.176A3 3 0 0 0 6.62 21h10.757a3 3 0 0 0 2.995-2.824L20.913 9H3.087Zm6.163 3.75A.75.75 0 0 1 10 12h4a.75.75 0 0 1 0 1.5h-4a.75.75 0 0 1-.75-.75Z" clip-rule="evenodd" />
|
|
201
|
+
</svg>
|
|
202
|
+
|
|
203
|
+
History of changes
|
|
204
|
+
</h4>
|
|
205
|
+
|
|
206
|
+
<table class="data-grid">
|
|
207
|
+
<thead>
|
|
208
|
+
<tr>
|
|
209
|
+
<th>Title</th>
|
|
210
|
+
<th>Date of change</th>
|
|
211
|
+
<th>Published by</th>
|
|
212
|
+
<th> </th>
|
|
213
|
+
</tr>
|
|
214
|
+
</thead>
|
|
215
|
+
|
|
216
|
+
<tbody>
|
|
217
|
+
<% const maxVersion = Math.max(...changes.map((ch) => ch.version)); %>
|
|
218
|
+
<% changes.forEach((change, idx)=> { %>
|
|
219
|
+
<tr class="border-b border-mono-25">
|
|
220
|
+
<td class="py-4 pl-2">
|
|
221
|
+
<div class="flex items-center gap-2">
|
|
222
|
+
<%= [change.title, change.description].filter(Boolean).join(": ") %>
|
|
223
|
+
|
|
224
|
+
<% if (change.source === "revert") { %>
|
|
225
|
+
<img src="/static/_assets/revert.svg" alt="Revert version" class="size-4">
|
|
226
|
+
<% } %>
|
|
227
|
+
</div>
|
|
228
|
+
</td>
|
|
229
|
+
|
|
230
|
+
<td class="whitespace-nowrap">
|
|
231
|
+
<div class="body-3 text-raketa-foreground/50">
|
|
232
|
+
<div class="flex items-center gap-1">
|
|
233
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4 text-raketa-foreground">
|
|
234
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
|
235
|
+
</svg>
|
|
236
|
+
|
|
237
|
+
<%= (new Date(change.insertedAt)).toLocaleString() %>
|
|
238
|
+
</div>
|
|
239
|
+
</div>
|
|
240
|
+
</td>
|
|
241
|
+
|
|
242
|
+
<td class="whitespace-nowrap">
|
|
243
|
+
<div class="body-3 text-raketa-foreground/50">
|
|
244
|
+
<div class="flex items-center gap-1" title="Yana Dimitrova">
|
|
245
|
+
<img src="<%= change.operatorMeta.avatar %>" class="size-4 rounded-full">
|
|
246
|
+
<%= change.operatorMeta.name %>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
</td>
|
|
250
|
+
|
|
251
|
+
<td>
|
|
252
|
+
<div class="actions-toolbar justify-end">
|
|
253
|
+
<% if (maxVersion !== change.version) { %>
|
|
254
|
+
<form method="POST" action="<%= `/${_context.locale}/articles/${article.id}/article_changes/reverts` %>" class="inline-block">
|
|
255
|
+
<input type="hidden" name="version" value=<%= change.version %>>
|
|
256
|
+
<button type="submit" class="btn-text has-icon">
|
|
257
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
258
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M9 15 3 9m0 0 6-6M3 9h12a6 6 0 0 1 0 12h-3" />
|
|
259
|
+
</svg>
|
|
260
|
+
|
|
261
|
+
Revert
|
|
262
|
+
</button>
|
|
263
|
+
</form>
|
|
264
|
+
<% } %>
|
|
265
|
+
|
|
266
|
+
<a href="#" class="btn-text has-icon">
|
|
267
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
268
|
+
<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" />
|
|
269
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
|
270
|
+
</svg>
|
|
271
|
+
|
|
272
|
+
Preview
|
|
273
|
+
</a>
|
|
274
|
+
</div>
|
|
275
|
+
</td>
|
|
276
|
+
</tr>
|
|
277
|
+
<% }); %>
|
|
278
|
+
</tbody>
|
|
279
|
+
</table>
|
|
280
|
+
</div>
|
|
281
|
+
</div>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<% form_for({ translation }, errors, (f) => { %>
|
|
2
|
+
<form action="<%= `/${_context.locale}/articles/${article.id}/translations` %>" method="post" class="form">
|
|
3
|
+
<input type="hidden" name="target_locale" value="<%= targetLocale %>" />
|
|
4
|
+
|
|
5
|
+
<%- f.field('translation.title', { required: true }) %>
|
|
6
|
+
<%- f.field('translation.slug', { label: "URL", required: true }) %>
|
|
7
|
+
<%- f.field('translation.publish_at', { required: true, type: 'datetime-local' }) %>
|
|
8
|
+
<%- f.field('translation.visibility', { as: 'select', required: true, options: visibilityOptions }) %>
|
|
9
|
+
|
|
10
|
+
<%- f.field('translation.username', { required: true }) %>
|
|
11
|
+
<%- f.field('translation.password', { required: true }) %>
|
|
12
|
+
|
|
13
|
+
<%- f.field('translation.layout', { as: 'select', required: true, options: [
|
|
14
|
+
["default", "Default"],
|
|
15
|
+
["landing", "Landing page"],
|
|
16
|
+
["headless", "Headless"],
|
|
17
|
+
] }) %>
|
|
18
|
+
|
|
19
|
+
<%- f.field('translation.meta_title', { required: true }) %>
|
|
20
|
+
<%- f.field('translation.meta_description', { as: "textarea", required: true }) %>
|
|
21
|
+
|
|
22
|
+
<raketa-image-picker name="translation[meta_image]" value="<%= JSON.stringify(translation.meta_image) %>"></raketa-image-picker>
|
|
23
|
+
|
|
24
|
+
<h6>Original tags:</h6>
|
|
25
|
+
<div><%= blueprint_tags.map((tag) => tag.name).join(", ")%></div>
|
|
26
|
+
|
|
27
|
+
<%- f.field('translation.tags', { as: 'checkbox_group', required: true, options: tags.map(tag => [tag.id, tag.name])}) %>
|
|
28
|
+
|
|
29
|
+
<div class="form-actions">
|
|
30
|
+
<div class="btn-toolbar">
|
|
31
|
+
<%- f.submit('Save record', { class: 'btn-primary' }) %>
|
|
32
|
+
|
|
33
|
+
<a href="<%= `/${_context.locale}/articles/${article.id}` %>" class="btn-secondary">Cancel</a>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</form>
|
|
37
|
+
<% }) %>
|
|
38
|
+
|
|
39
|
+
<div>
|
|
40
|
+
<div class="help">
|
|
41
|
+
<div class="flex items-center gap-1 mb-2">
|
|
42
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
43
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" />
|
|
44
|
+
</svg>
|
|
45
|
+
|
|
46
|
+
<h3 class="heading-3">Contextual help</h3>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempore nostrum fugit sint sunt distinctio ut cum, corrupti ad error, quo labore minima. Reprehenderit quasi maxime repudiandae voluptatum commodi saepe molestiae?</p>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
<script>
|
|
54
|
+
function onVisibilityChange(event) {
|
|
55
|
+
const newValue = event.target.value;
|
|
56
|
+
|
|
57
|
+
if (newValue === "protected") {
|
|
58
|
+
document.getElementById("f_username").parentElement.style.display = "block";
|
|
59
|
+
document.getElementById("f_username").required = true;
|
|
60
|
+
document.getElementById("f_password").parentElement.style.display = "block";
|
|
61
|
+
document.getElementById("f_password").required = true;
|
|
62
|
+
} else {
|
|
63
|
+
document.getElementById("f_username").parentElement.style.display = "none";
|
|
64
|
+
document.getElementById("f_username").required = false;
|
|
65
|
+
document.getElementById("f_password").parentElement.style.display = "none";
|
|
66
|
+
document.getElementById("f_password").required = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onVisibilityChange({
|
|
71
|
+
target: {
|
|
72
|
+
value: '<%= article.visibility %>'
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
document.getElementById("f_visibility").addEventListener("change", onVisibilityChange)
|
|
77
|
+
</script>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<div class="w-full">
|
|
2
|
+
<div class="flex items-center justify-between mt-6 mb-4">
|
|
3
|
+
<div class="flex items-center gap-2">
|
|
4
|
+
<h1 class="heading-1">Create page translation</h1>
|
|
5
|
+
</div>
|
|
6
|
+
</div>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="grid gap-4 md:grid-cols-3">
|
|
10
|
+
<%- include('_form.ejs') %>
|
|
11
|
+
</div>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<div class="page-wrapper">
|
|
2
|
+
<div class="page-title">
|
|
3
|
+
<h1 class="heading-1">Change URL</h1>
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<div class="grid gap-4 md:grid-cols-3">
|
|
7
|
+
<% form_for({ change }, errors, (f) => { %>
|
|
8
|
+
<form action="<%= `/${_context.locale}/articles/${change.id}/urls` %>" method="post" class="form">
|
|
9
|
+
<%- f.field('change.slug', { label: "URL", required: true }) %>
|
|
10
|
+
<%- f.field('change.redirect', { as: "checkbox", value: "1", label: "Create 301 redirect for the old URL" }) %>
|
|
11
|
+
|
|
12
|
+
<%- f.submit('Save record', { class: 'btn-primary' }) %>
|
|
13
|
+
<a href="<%=`/${_context.locale}/articles/${change.id}`%>" class="btn-secondary">Back</a>
|
|
14
|
+
</form>
|
|
15
|
+
<% }) %>
|
|
16
|
+
|
|
17
|
+
<div>
|
|
18
|
+
<div class="help">
|
|
19
|
+
<div class="flex items-center gap-1 mb-2">
|
|
20
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
21
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z" />
|
|
22
|
+
</svg>
|
|
23
|
+
|
|
24
|
+
<h3 class="heading-3">Contextual help</h3>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempore nostrum fugit sint sunt distinctio ut cum, corrupti ad error, quo labore minima. Reprehenderit quasi maxime repudiandae voluptatum commodi saepe molestiae?</p>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
package/test/factory.js
CHANGED
|
@@ -33,6 +33,27 @@ const PAGE = {
|
|
|
33
33
|
categories: [],
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
+
const ARTICLE = {
|
|
37
|
+
id: "2",
|
|
38
|
+
slug: "page-revision",
|
|
39
|
+
publishAt: "2024-08-30T19:05:00Z",
|
|
40
|
+
title: "Page Revision",
|
|
41
|
+
widgets: [],
|
|
42
|
+
settings: {
|
|
43
|
+
meta: {
|
|
44
|
+
title: "Open graph",
|
|
45
|
+
description: "Open graph???",
|
|
46
|
+
image: {},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
visibility: "public",
|
|
50
|
+
originalId: null,
|
|
51
|
+
insertedAt: "2024-08-30T19:05:00Z",
|
|
52
|
+
tags: [],
|
|
53
|
+
pageType: {},
|
|
54
|
+
categories: [],
|
|
55
|
+
};
|
|
56
|
+
|
|
36
57
|
const PAGE_CHANGE = {
|
|
37
58
|
version: "1",
|
|
38
59
|
title: "A cool page change",
|
|
@@ -46,6 +67,19 @@ const PAGE_CHANGE = {
|
|
|
46
67
|
insertedAt: "2024-08-30T19:05:00Z",
|
|
47
68
|
};
|
|
48
69
|
|
|
70
|
+
const ARTICLE_CHANGE = {
|
|
71
|
+
version: "1",
|
|
72
|
+
title: "A cool article change",
|
|
73
|
+
operator: "some-operator-id",
|
|
74
|
+
operatorMeta: {
|
|
75
|
+
id: "some-operator-id",
|
|
76
|
+
email: "john@example.com",
|
|
77
|
+
name: "John DOe",
|
|
78
|
+
},
|
|
79
|
+
description: "A cool article change description",
|
|
80
|
+
insertedAt: "2024-08-30T19:05:00Z",
|
|
81
|
+
};
|
|
82
|
+
|
|
49
83
|
const Tag = {
|
|
50
84
|
id: "42",
|
|
51
85
|
slug: "tag",
|
|
@@ -66,6 +100,9 @@ const FIXTURES = {
|
|
|
66
100
|
page: { ...PAGE },
|
|
67
101
|
page_revision: { ...PAGE, meta: { ...REVISION_META }, originalId: "1" },
|
|
68
102
|
page_change: { ...PAGE_CHANGE },
|
|
103
|
+
article: { ...ARTICLE },
|
|
104
|
+
article_revision: { ...ARTICLE, meta: { ...REVISION_META }, originalId: "1" },
|
|
105
|
+
article_change: { ...ARTICLE_CHANGE },
|
|
69
106
|
settings: { value: {} },
|
|
70
107
|
tag: Tag,
|
|
71
108
|
pagination: {
|