@raketa-cloud/admin 1.8.10 → 1.8.11
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/dist/application.css +109 -0
- package/package.json +4 -2
- package/src/HonoAdapter.js +22 -13
- package/src/Logger.js +7 -8
- package/src/RaketaContext.js +1 -0
- package/src/cipher.js +2 -2
- package/src/cloud/ContentTasks.js +31 -0
- package/src/cloud/RaketaClient.js +1 -1
- package/src/cloud/Redirects.js +2 -2
- package/src/cloud/ResourceChanges.js +1 -1
- package/src/cloud/ResourceRevisions.js +2 -2
- package/src/cloud/Resources.js +28 -12
- package/src/cloud/Tags.js +4 -4
- package/src/cloud/documents/common.js +16 -0
- package/src/cloud/documents/contentTasksDocuments.js +59 -0
- package/src/cloud/documents/resourcesDocuments.js +12 -0
- package/src/filters.js +3 -3
- package/src/handlers/TagsHandler.js +2 -2
- package/src/handlers/_shared/getResourceUpdateDestination.js +1 -1
- package/src/handlers/categories/index.js +3 -3
- package/src/handlers/content_tasks/ContentTasksHandler.js +32 -0
- package/src/handlers/resource_revisions/LocksHandler.js +4 -1
- package/src/handlers/resources/ClonesHandler.js +1 -3
- package/src/handlers/resources/ExportsHandler.js +1 -5
- package/src/handlers/resources/ResourcesHandler.js +1 -1
- package/src/handlers/resources/TranslationsHandler.js +28 -19
- package/src/handlers/resources/URLsHandler.js +3 -1
- package/src/helpers/AuthHelper.js +1 -1
- package/src/helpers/FormBuilder.js +14 -14
- package/src/helpers/Pagination.js +5 -5
- package/src/helpers/historyUtils.js +3 -3
- package/src/helpers/utils.js +6 -1
- package/src/index.js +1 -0
- package/src/routeMember.js +9 -4
- package/src/routeNestedCollection.js +14 -29
- package/src/routeNestedMember.js +17 -6
- package/src/routeStandard.js +5 -1
- package/src/setupAuthentication.js +1 -1
- package/src/setupCloud.js +5 -0
- package/src/tests/Adapter.test.js +2 -2
- package/src/tests/HonoAdapter.coverage.test.js +44 -22
- package/src/tests/HonoAdapter.filter.test.js +28 -18
- package/src/tests/HonoAdapter.test.js +3 -3
- package/src/tests/RaketaClient.test.js +427 -413
- package/src/tests/RaketaContext.test.js +1 -1
- package/src/tests/buildResourcePath.test.js +1 -1
- package/src/tests/cipher.test.js +16 -16
- package/src/tests/filters.test.js +24 -24
- package/src/tests/handlers/RedirectsHandler.test/destroy.test.js +1 -1
- package/src/tests/handlers/TagsHandler.test/create.test.js +2 -2
- package/src/tests/handlers/TagsHandler.test/destroy.test.js +1 -1
- package/src/tests/handlers/TagsHandler.test/update.test.js +2 -2
- package/src/tests/handlers/categories/create.test.js +2 -2
- package/src/tests/handlers/categories/destroy.test.js +1 -1
- package/src/tests/handlers/content_tasks/ContentTasksHandler.test/index.test.js +161 -0
- package/src/tests/handlers/resource_revisions/CancelSchedulesHandler.test/create.test.js +2 -2
- package/src/tests/handlers/resource_revisions/CodeHandler.test/update.test.js +1 -1
- package/src/tests/handlers/resource_revisions/GeneralHandler.test/update.test.js +1 -1
- package/src/tests/handlers/resource_revisions/LocksHandler.test/create.test.js +5 -5
- package/src/tests/handlers/resource_revisions/LocksHandler.test/create_form.test.js +6 -2
- package/src/tests/handlers/resource_revisions/MetaHandler.test/update.test.js +1 -1
- package/src/tests/handlers/resource_revisions/PublishesHandler.test/create.test.js +5 -5
- package/src/tests/handlers/resource_revisions/ResourceRevisionsHandler.test/create.test.js +2 -2
- package/src/tests/handlers/resource_revisions/ResourceRevisionsHandler.test/destroy.test.js +1 -1
- package/src/tests/handlers/resource_revisions/RevertsHandler.test/create.test.js +18 -3
- package/src/tests/handlers/resource_revisions/TagHandler.test/update.test.js +1 -1
- package/src/tests/handlers/resource_revisions/UnlocksHandler.test/create.test.js +2 -2
- package/src/tests/handlers/resource_revisions/VisualHandler.test/update.test.js +1 -1
- package/src/tests/handlers/resource_revisions/WidgetHandler.test/update.test.js +2 -2
- package/src/tests/handlers/resources/ChangeHandler.test/show.test.js +7 -2
- package/src/tests/handlers/resources/ClonesHandler.test/create.test.js +1 -3
- package/src/tests/handlers/resources/ExportsHandler.test/index.test.js +8 -8
- package/src/tests/handlers/resources/HistoryHandler.test/index.test.js +1 -1
- package/src/tests/handlers/resources/ResourcesAPIHandler.test/index.test.js +1 -5
- package/src/tests/handlers/resources/ResourcesHandler.test/create.test.js +2 -2
- package/src/tests/handlers/resources/ResourcesHandler.test/show.test.js +1 -1
- package/src/tests/handlers/resources/TranslationsHandler.test/create.test.js +24 -14
- package/src/tests/handlers/resources/TranslationsHandler.test/create_form.test.js +1 -1
- package/src/tests/handlers/resources/TranslationsHandler.test/index.test.js +3 -3
- package/src/tests/handlers/resources/URLsHandler.test/create.test.js +4 -6
- package/src/tests/helpers/AuthHelper.test.js +11 -12
- package/src/tests/helpers/CSVExportHelper.test.js +3 -3
- package/src/tests/helpers/FormBuilder.test.js +21 -21
- package/src/tests/helpers/HTMLBuilder.test.js +4 -4
- package/src/tests/helpers/Inflector.test.js +1 -1
- package/src/tests/helpers/Pagination.test.js +1 -1
- package/src/tests/helpers/utils.test.js +46 -0
- package/src/tests/routeCategoriesModule.test.js +10 -5
- package/src/tests/routeCollection.test.js +1 -1
- package/src/tests/routeMember.test.js +2 -2
- package/src/tests/routeNestedCollection.test.js +3 -3
- package/src/tests/routeNestedMember.test.js +3 -3
- package/src/tests/routeResourceModule.test.js +15 -16
- package/src/tests/routeSettings.test.js +3 -3
- package/src/tests/routeStandard.test.js +27 -9
- package/src/tests/setupAuthentication.test.js +9 -6
- package/src/tests/support/factory.js +33 -0
- package/src/tests/utils.test.js +19 -19
- package/src/views/content_tasks/index.ejs +191 -0
- package/src/views/layouts/application.ejs +2 -1
- package/src/views/resources/_shared/_toolbar.ejs +33 -2
- package/src/views/resources/_shared/_translations_strip.ejs +71 -0
- package/src/views/resources/index.ejs +5 -0
- package/src/views/resources/show.ejs +1 -29
- package/src/views/resources/translations/create_form.ejs +13 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
<div class="page-wrapper">
|
|
2
|
+
<div class="page-title">
|
|
3
|
+
<h1 class="heading-1">Content Tasks</h1>
|
|
4
|
+
|
|
5
|
+
<div class="actions-toolbar">
|
|
6
|
+
<button type="button" data-toggle-sidebar="1" class="p-2.5 rounded hover:bg-neutral-200 transition-all duration-300 ease-in-out dark:hover:bg-neutral-700">
|
|
7
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
8
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
|
9
|
+
</svg>
|
|
10
|
+
</button>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<table class="data-grid">
|
|
15
|
+
<thead>
|
|
16
|
+
<tr>
|
|
17
|
+
<th>Resource</th>
|
|
18
|
+
<th>Locale</th>
|
|
19
|
+
<th>Workflow</th>
|
|
20
|
+
<th>Started at</th>
|
|
21
|
+
<th>Finished at</th>
|
|
22
|
+
<th>Status</th>
|
|
23
|
+
</tr>
|
|
24
|
+
</thead>
|
|
25
|
+
|
|
26
|
+
<tbody>
|
|
27
|
+
<% if (items && items.list && items.list.length > 0) { %>
|
|
28
|
+
<% items.list.forEach(task => { %>
|
|
29
|
+
<tr>
|
|
30
|
+
<td class="w-1/3">
|
|
31
|
+
<% if (task.resource) { %>
|
|
32
|
+
<a href="<%= buildResourceUrl(task.resource) %>" target="_blank" class="btn-text">
|
|
33
|
+
<%= task.resource.title %>
|
|
34
|
+
</a>
|
|
35
|
+
<div class="body-3 text-raketa-foreground/50 mt-1">
|
|
36
|
+
<strong>Type:</strong> <%= Inflector.humanize(Inflector.capitalize(task.resource.resourceType)) %>
|
|
37
|
+
</div>
|
|
38
|
+
<% } else { %>
|
|
39
|
+
<span class="text-raketa-foreground/50">—</span>
|
|
40
|
+
<% } %>
|
|
41
|
+
</td>
|
|
42
|
+
|
|
43
|
+
<td>
|
|
44
|
+
<% if (task.resource && _context.locales[task.resource.locale]) { %>
|
|
45
|
+
<% const { name, flag } = _context.locales[task.resource.locale] %>
|
|
46
|
+
<img title="<%= name %>" src="<%= flag %>" alt="<%= name %>" class="size-6 rounded-full border dark:border-neutral-700" />
|
|
47
|
+
<% } else { %>
|
|
48
|
+
<span class="text-raketa-foreground/50">—</span>
|
|
49
|
+
<% } %>
|
|
50
|
+
</td>
|
|
51
|
+
|
|
52
|
+
<td>
|
|
53
|
+
<span class="body-2">
|
|
54
|
+
<%= Inflector.capitalize(task.workflow) %>
|
|
55
|
+
</span>
|
|
56
|
+
</td>
|
|
57
|
+
|
|
58
|
+
<td>
|
|
59
|
+
<div class="body-3 text-raketa-foreground/50">
|
|
60
|
+
<div class="flex items-center gap-1 mb-0.5">
|
|
61
|
+
<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">
|
|
62
|
+
<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" />
|
|
63
|
+
</svg>
|
|
64
|
+
<time data-pretty-datetime datetime="<%= task.insertedAt %>"><%= utils.formattedDateTime(task.insertedAt) %></time>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="flex items-center gap-1" title="<%= task.operatorMeta?.name %>">
|
|
68
|
+
<% if (task.operatorMeta?.avatar) { %>
|
|
69
|
+
<img src="<%= task.operatorMeta?.avatar %>" class="size-4 rounded-full" alt="<%= task.operatorMeta?.name %>">
|
|
70
|
+
<% } else { %>
|
|
71
|
+
<div class="size-4 rounded-full"></div>
|
|
72
|
+
<% } %>
|
|
73
|
+
<%= task.operatorMeta?.name %>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</td>
|
|
77
|
+
|
|
78
|
+
<td>
|
|
79
|
+
<% if (task.completedAt || task.failedAt || task.rejectedAt) { %>
|
|
80
|
+
<div class="body-3 text-raketa-foreground/50">
|
|
81
|
+
<div class="flex items-center gap-1">
|
|
82
|
+
<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">
|
|
83
|
+
<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" />
|
|
84
|
+
</svg>
|
|
85
|
+
<time data-pretty-datetime datetime="<%= task.completedAt || task.failedAt || task.rejectedAt %>">
|
|
86
|
+
<%= utils.formattedDateTime(task.completedAt || task.failedAt || task.rejectedAt) %>
|
|
87
|
+
</time>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
<% } else { %>
|
|
91
|
+
<span class="text-raketa-foreground/50">—</span>
|
|
92
|
+
<% } %>
|
|
93
|
+
</td>
|
|
94
|
+
|
|
95
|
+
<td>
|
|
96
|
+
<% if (task.completedAt) { %>
|
|
97
|
+
<span class="bg-emerald-100 chip text-emerald-700 dark:bg-emerald-900/50 dark:text-emerald-300">
|
|
98
|
+
Completed
|
|
99
|
+
</span>
|
|
100
|
+
<% } else if (task.failedAt) { %>
|
|
101
|
+
<span class="bg-red-100 chip text-red-700 dark:bg-red-900/50 dark:text-red-300">
|
|
102
|
+
Failed
|
|
103
|
+
</span>
|
|
104
|
+
<% } else if (task.rejectedAt) { %>
|
|
105
|
+
<span class="bg-orange-100 chip text-orange-700 dark:bg-orange-900/50 dark:text-orange-300">
|
|
106
|
+
Rejected
|
|
107
|
+
</span>
|
|
108
|
+
<% } else { %>
|
|
109
|
+
<span class="bg-blue-100 chip text-blue-700 dark:bg-blue-900/50 dark:text-blue-300">
|
|
110
|
+
In Progress
|
|
111
|
+
</span>
|
|
112
|
+
<% } %>
|
|
113
|
+
</td>
|
|
114
|
+
</tr>
|
|
115
|
+
<% }) %>
|
|
116
|
+
<% } %>
|
|
117
|
+
</tbody>
|
|
118
|
+
</table>
|
|
119
|
+
|
|
120
|
+
<% if (!items || !items.list || items.list.length === 0) { %>
|
|
121
|
+
<div class="empty-state">
|
|
122
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-12">
|
|
123
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75 2.25 2.25 0 0 0-.1-.664m-5.8 0A2.251 2.251 0 0 1 13.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25ZM6.75 12h.008v.008H6.75V12Zm0 3h.008v.008H6.75V15Zm0 3h.008v.008H6.75V18Z" />
|
|
124
|
+
</svg>
|
|
125
|
+
<h3 class="heading-3 mt-4">No content tasks</h3>
|
|
126
|
+
<p class="body-2 text-raketa-foreground/70 mt-2">
|
|
127
|
+
<% if (Object.keys(_context.query).some(k => k.startsWith('f:'))) { %>
|
|
128
|
+
No tasks match the selected filters. Try adjusting your filters.
|
|
129
|
+
<% } else { %>
|
|
130
|
+
No translation workflow tasks have been created yet.
|
|
131
|
+
<% } %>
|
|
132
|
+
</p>
|
|
133
|
+
</div>
|
|
134
|
+
<% } %>
|
|
135
|
+
|
|
136
|
+
<%- pagination(items.pagination, _context) %>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<div data-sidebar="1" class="search-sidebar <%= Object.keys(_context.query).some(k => k.startsWith('f:')) ? '' : 'hidden' %>">
|
|
140
|
+
<span class="heading-2">Filter by</span>
|
|
141
|
+
|
|
142
|
+
<form action="/<%= _context.locale %>/content_tasks" method="GET" class="form mt-4">
|
|
143
|
+
<input type="hidden" name="order_direction" value="<%= _context.query.order_direction %>" />
|
|
144
|
+
<input type="hidden" name="order_by" value="<%= _context.query.order_by %>" />
|
|
145
|
+
|
|
146
|
+
<div class="mb-4">
|
|
147
|
+
<label for="f:locale" class="font-semibold hover:cursor-pointer body-3">Locale</label>
|
|
148
|
+
<select name="f:locale" id="f:locale">
|
|
149
|
+
<option value="">All Locales</option>
|
|
150
|
+
<% Object.keys(_context.locales).forEach(key => { %>
|
|
151
|
+
<option value="<%= key %>" <%= _context.query['f:locale'] === key ? 'selected' : '' %>>
|
|
152
|
+
<%= _context.locales[key].name %> (<%= key.toUpperCase() %>)
|
|
153
|
+
</option>
|
|
154
|
+
<% }) %>
|
|
155
|
+
</select>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div class="mb-4">
|
|
159
|
+
<label for="f:author" class="font-semibold hover:cursor-pointer body-3">Author</label>
|
|
160
|
+
<select name="f:author" id="f:author">
|
|
161
|
+
<option value="">All Authors</option>
|
|
162
|
+
<% editors.forEach(editor => { %>
|
|
163
|
+
<option value="<%= editor.id %>" <%= _context.query['f:author'] === editor.id ? 'selected' : '' %>>
|
|
164
|
+
<%= editor.name %>
|
|
165
|
+
</option>
|
|
166
|
+
<% }) %>
|
|
167
|
+
</select>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<div class="mb-4">
|
|
171
|
+
<label for="f:status" class="font-semibold hover:cursor-pointer body-3">Status</label>
|
|
172
|
+
<select name="f:status" id="f:status">
|
|
173
|
+
<option value="">All Statuses</option>
|
|
174
|
+
<option value="IN_PROGRESS" <%= _context.query['f:status'] === 'IN_PROGRESS' ? 'selected' : '' %>>
|
|
175
|
+
In Progress
|
|
176
|
+
</option>
|
|
177
|
+
<option value="COMPLETED" <%= _context.query['f:status'] === 'COMPLETED' ? 'selected' : '' %>>
|
|
178
|
+
Completed
|
|
179
|
+
</option>
|
|
180
|
+
<option value="FAILED" <%= _context.query['f:status'] === 'FAILED' ? 'selected' : '' %>>
|
|
181
|
+
Failed
|
|
182
|
+
</option>
|
|
183
|
+
</select>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<div class="btn-toolbar">
|
|
187
|
+
<button type="submit" class="btn-primary">Filter</button>
|
|
188
|
+
<a href="/<%= _context.locale %>/content_tasks" class="btn-text">Clear filters</a>
|
|
189
|
+
</div>
|
|
190
|
+
</form>
|
|
191
|
+
</div>
|
|
@@ -66,7 +66,8 @@
|
|
|
66
66
|
|
|
67
67
|
<div class="my-4">
|
|
68
68
|
<% _context.layout.sidebar.forEach((menu, idx) => { %>
|
|
69
|
-
<% if (menu
|
|
69
|
+
<% if (!menu) { %>
|
|
70
|
+
<% } else if (menu.submenus) { %>
|
|
70
71
|
<% const pathMatchesMenuItem = menu.submenus.some(item => _context.path.includes(item.link)) %>
|
|
71
72
|
|
|
72
73
|
<div class="relative group-[.expanded]:hidden group/item">
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<div>
|
|
2
|
+
<%
|
|
3
|
+
const hasActiveContentTask = utils.feature("contentTasks", _context) &&
|
|
4
|
+
resource.activeContentTask &&
|
|
5
|
+
!resource.activeContentTask.completedAt &&
|
|
6
|
+
!resource.activeContentTask.failedAt &&
|
|
7
|
+
!resource.activeContentTask.rejectedAt;
|
|
8
|
+
%>
|
|
2
9
|
<div class="actions-toolbar">
|
|
3
10
|
<form method="POST" action="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/${_context.resourceConfig.resourceType}_revisions` %>" class="inline-block">
|
|
4
|
-
<% if (resource.revisionsCount >= _context?.maxOpenRevisions) { %>
|
|
11
|
+
<% if (resource.revisionsCount >= _context?.maxOpenRevisions || hasActiveContentTask) { %>
|
|
5
12
|
<button type="submit" class="btn-primary" disabled style="opacity: 50%;">
|
|
6
13
|
Start revision
|
|
7
14
|
</button>
|
|
@@ -12,6 +19,15 @@
|
|
|
12
19
|
<% } %>
|
|
13
20
|
</form>
|
|
14
21
|
|
|
22
|
+
<% if (hasActiveContentTask) { %>
|
|
23
|
+
<button type="button" class="btn-text has-icon" disabled style="opacity: 50%; cursor: not-allowed;">
|
|
24
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
25
|
+
<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" />
|
|
26
|
+
</svg>
|
|
27
|
+
|
|
28
|
+
Change URL
|
|
29
|
+
</button>
|
|
30
|
+
<% } else { %>
|
|
15
31
|
<a href="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/urls/new` %>" class="btn-text has-icon">
|
|
16
32
|
<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
33
|
<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" />
|
|
@@ -19,9 +35,10 @@
|
|
|
19
35
|
|
|
20
36
|
Change URL
|
|
21
37
|
</a>
|
|
38
|
+
<% } %>
|
|
22
39
|
|
|
23
40
|
<form action="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/clones` %>" method="post" class="inline-block">
|
|
24
|
-
<button type="submit" class="btn-text has-icon"
|
|
41
|
+
<button type="submit" class="btn-text has-icon" <%= hasActiveContentTask ? 'disabled style="opacity: 50%;"' : '' %>>
|
|
25
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">
|
|
26
43
|
<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
44
|
</svg>
|
|
@@ -30,6 +47,15 @@
|
|
|
30
47
|
</button>
|
|
31
48
|
</form>
|
|
32
49
|
|
|
50
|
+
<% if (hasActiveContentTask) { %>
|
|
51
|
+
<button type="button" class="btn-danger has-icon" disabled style="opacity: 50%; cursor: not-allowed;">
|
|
52
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
53
|
+
<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" />
|
|
54
|
+
</svg>
|
|
55
|
+
|
|
56
|
+
Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.resourceType)) %>
|
|
57
|
+
</button>
|
|
58
|
+
<% } else { %>
|
|
33
59
|
<a href="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/deletes/new` %>" class="btn-danger has-icon">
|
|
34
60
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
|
35
61
|
<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" />
|
|
@@ -37,9 +63,14 @@
|
|
|
37
63
|
|
|
38
64
|
Delete <%= Inflector.humanize(Inflector.downcase(_context.resourceConfig.resourceType)) %>
|
|
39
65
|
</a>
|
|
66
|
+
<% } %>
|
|
40
67
|
</div>
|
|
41
68
|
|
|
42
69
|
<% if (_context.query?.revisions_count_error) { %>
|
|
43
70
|
<div class="text-red-600">Cannot open a new revision. Current limit is <%= _context.maxOpenRevisions %>. </div>
|
|
44
71
|
<% } %>
|
|
72
|
+
|
|
73
|
+
<% if (hasActiveContentTask) { %>
|
|
74
|
+
<div class="text-orange-700 mt-2 dark:text-orange-300">Actions are disabled while a content task is in progress.</div>
|
|
75
|
+
<% } %>
|
|
45
76
|
</div>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<div class="flex flex-wrap items-center gap-1 mb-6 -my-4">
|
|
2
|
+
<%
|
|
3
|
+
const availableLocales = Object.keys(_context.locales);
|
|
4
|
+
const totalPossibleTranslations = availableLocales.length - 1;
|
|
5
|
+
const existingTranslationsCount = Object.keys(resource.translations).length;
|
|
6
|
+
const canBeTranslated = existingTranslationsCount < totalPossibleTranslations;
|
|
7
|
+
%>
|
|
8
|
+
|
|
9
|
+
<% Object.keys(_context.locales).forEach(key => { %>
|
|
10
|
+
<% const { name, _code, flag} = _context.locales[key] %>
|
|
11
|
+
<% if (key === _context.locale) { %>
|
|
12
|
+
<%
|
|
13
|
+
const currentHasActiveTask = utils.feature("contentTasks", _context) &&
|
|
14
|
+
resource.activeContentTask &&
|
|
15
|
+
!resource.activeContentTask.completedAt &&
|
|
16
|
+
!resource.activeContentTask.failedAt &&
|
|
17
|
+
!resource.activeContentTask.rejectedAt;
|
|
18
|
+
|
|
19
|
+
const contentTaskMessage = currentHasActiveTask ? `${name}: ${Inflector.capitalize(resource.activeContentTask.workflow)} task in progress` : '';
|
|
20
|
+
%>
|
|
21
|
+
|
|
22
|
+
<span class="relative inline-block" title="<%= currentHasActiveTask ? contentTaskMessage : "" %>">
|
|
23
|
+
<img
|
|
24
|
+
title="<%= currentHasActiveTask ? contentTaskMessage : name %>"
|
|
25
|
+
src="<%= flag %>"
|
|
26
|
+
alt="<%= name %>"
|
|
27
|
+
class="border rounded-full size-6 dark:border-neutral-700"
|
|
28
|
+
/>
|
|
29
|
+
|
|
30
|
+
<% if (currentHasActiveTask) { %>
|
|
31
|
+
<span class="absolute -top-0.5 -right-0.5 flex h-3 w-3">
|
|
32
|
+
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-raketa-primary opacity-75"></span>
|
|
33
|
+
<span class="relative inline-flex rounded-full h-3 w-3 bg-raketa-primary"></span>
|
|
34
|
+
</span>
|
|
35
|
+
<% } %>
|
|
36
|
+
</span>
|
|
37
|
+
<% } else if (resource.translations[key]) { %>
|
|
38
|
+
<% const hasActiveTask = resource.translations[key].active_content_task; %>
|
|
39
|
+
<% const contentTaskMessage = hasActiveTask ? `${name}: ${Inflector.capitalize(resource.translations[key].active_content_task.workflow)} task in progress` : ""; %>
|
|
40
|
+
<a
|
|
41
|
+
href="<%= `/${key}/${_context.resourceConfig.resourceTypePlural}/${resource.translations[key].id}` %>"
|
|
42
|
+
class="relative inline-block"
|
|
43
|
+
title="<%= hasActiveTask ? contentTaskMessage : "" %>"
|
|
44
|
+
>
|
|
45
|
+
<img
|
|
46
|
+
title="<%= hasActiveTask ? contentTaskMessage : name %>"
|
|
47
|
+
src="<%= flag %>"
|
|
48
|
+
alt="<%= name %>"
|
|
49
|
+
class="border rounded-full size-6 dark:border-neutral-700"
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<% if (hasActiveTask) { %>
|
|
53
|
+
<span class="absolute -top-0.5 -right-0.5 flex h-3 w-3">
|
|
54
|
+
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-raketa-primary opacity-75"></span>
|
|
55
|
+
<span class="relative inline-flex rounded-full h-3 w-3 bg-raketa-primary"></span>
|
|
56
|
+
</span>
|
|
57
|
+
<% } %>
|
|
58
|
+
</a>
|
|
59
|
+
<% } else { %>
|
|
60
|
+
<a href="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/translations/new?target_locale=${key}` %>">
|
|
61
|
+
<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(" ") %>" />
|
|
62
|
+
</a>
|
|
63
|
+
<% } %>
|
|
64
|
+
<% }); %>
|
|
65
|
+
|
|
66
|
+
<% if (canBeTranslated) { %>
|
|
67
|
+
<a href="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/translations/new` %>" class="ml-2 btn-text">
|
|
68
|
+
Translate
|
|
69
|
+
</a>
|
|
70
|
+
<% } %>
|
|
71
|
+
</div>
|
|
@@ -40,6 +40,11 @@
|
|
|
40
40
|
<% if (item.revisionsCount > 0) { %>
|
|
41
41
|
<span class="bg-orange-100 chip text-orange-700 dark:bg-orange-900/50 dark:text-orange-300"><%= item.revisionsCount !== 1 ? `${item.revisionsCount} open revisions` : 'Open revision' %></span>
|
|
42
42
|
<% } %>
|
|
43
|
+
<% if (utils.feature("contentTasks", _context) && item.activeContentTask && !item.activeContentTask.completedAt && !item.activeContentTask.failedAt && !item.activeContentTask.rejectedAt) { %>
|
|
44
|
+
<span class="bg-blue-100 chip text-blue-700 dark:bg-blue-900/50 dark:text-blue-300" title="<%= item.activeContentTask.workflow ? `${item.activeContentTask.workflow} workflow` : 'Translation in progress' %>">
|
|
45
|
+
Content task in progress
|
|
46
|
+
</span>
|
|
47
|
+
<% } %>
|
|
43
48
|
|
|
44
49
|
<% if (item.visibility !== "private") { %>
|
|
45
50
|
<div class="mt-1">
|
|
@@ -4,35 +4,7 @@
|
|
|
4
4
|
<%- render_partial('./_shared/_toolbar.ejs') %>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
<%
|
|
9
|
-
const availableLocales = Object.keys(_context.locales);
|
|
10
|
-
const totalPossibleTranslations = availableLocales.length - 1;
|
|
11
|
-
const existingTranslationsCount = Object.keys(resource.translations).length;
|
|
12
|
-
const canBeTranslated = existingTranslationsCount < totalPossibleTranslations;
|
|
13
|
-
%>
|
|
14
|
-
|
|
15
|
-
<% Object.keys(_context.locales).forEach(key => { %>
|
|
16
|
-
<% const { name, _code, flag} = _context.locales[key] %>
|
|
17
|
-
<% if (key === _context.locale) { %>
|
|
18
|
-
<img title="<%= name %>" src="<%= flag %>" alt="<%= name %>" class="border rounded-full size-6 dark:border-neutral-700" />
|
|
19
|
-
<% } else if (resource.translations[key]) { %>
|
|
20
|
-
<a href="<%= `/${key}/${_context.resourceConfig.resourceTypePlural}/${resource.translations[key].id}` %>">
|
|
21
|
-
<img title="<%= name %>" src="<%= flag %>" alt="<%= name %>" class="border rounded-full size-6 dark:border-neutral-700" />
|
|
22
|
-
</a>
|
|
23
|
-
<% } else { %>
|
|
24
|
-
<a href="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/translations/new?target_locale=${key}` %>">
|
|
25
|
-
<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(" ") %>" />
|
|
26
|
-
</a>
|
|
27
|
-
<% } %>
|
|
28
|
-
<% }); %>
|
|
29
|
-
|
|
30
|
-
<% if (canBeTranslated) { %>
|
|
31
|
-
<a href="<%= `/${_context.locale}/${_context.resourceConfig.resourceTypePlural}/${resource.id}/translations/new` %>" class="ml-2 btn-text">
|
|
32
|
-
Translate
|
|
33
|
-
</a>
|
|
34
|
-
<% } %>
|
|
35
|
-
</div>
|
|
7
|
+
<%- render_partial('./_shared/_translations_strip.ejs') %>
|
|
36
8
|
|
|
37
9
|
<%
|
|
38
10
|
const openedRevisions = []
|
|
@@ -30,6 +30,19 @@
|
|
|
30
30
|
<% }) %>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
|
+
<% if (utils.feature("contentTasks", _context) && _context.locale === _context.defaultLocale) { %>
|
|
34
|
+
<div class="mb-4">
|
|
35
|
+
<label for="workflow" class="font-semibold hover:cursor-pointer body-3">Translation workflow</label>
|
|
36
|
+
<select name="resource[workflow]" id="workflow">
|
|
37
|
+
<option value="">Default (no workflow)</option>
|
|
38
|
+
<option value="lokalise" <%= resource.workflow === 'lokalise' ? 'selected' : '' %>>Lokalise workflow</option>
|
|
39
|
+
</select>
|
|
40
|
+
<p class="text-sm text-raketa-foreground/50 mt-1">
|
|
41
|
+
Select a workflow for the translation process. Lokalise workflow initiates a content task for external translation.
|
|
42
|
+
</p>
|
|
43
|
+
</div>
|
|
44
|
+
<% } %>
|
|
45
|
+
|
|
33
46
|
<% if (errors?.resource && targetLocale) { %>
|
|
34
47
|
<div>
|
|
35
48
|
<% if (targetLocale !== _context.locale) { %>
|