@raketa-cloud/admin 1.9.7 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1694,6 +1694,10 @@ select {
1694
1694
  top: 0.125rem;
1695
1695
  }
1696
1696
 
1697
+ .top-4 {
1698
+ top: 1rem;
1699
+ }
1700
+
1697
1701
  .top-6 {
1698
1702
  top: 1.5rem;
1699
1703
  }
@@ -1755,10 +1759,6 @@ select {
1755
1759
  margin-left: 0.375rem;
1756
1760
  }
1757
1761
 
1758
- .ml-10 {
1759
- margin-left: 2.5rem;
1760
- }
1761
-
1762
1762
  .ml-2 {
1763
1763
  margin-left: 0.5rem;
1764
1764
  }
@@ -2039,10 +2039,6 @@ select {
2039
2039
  align-items: center;
2040
2040
  }
2041
2041
 
2042
- .justify-start {
2043
- justify-content: flex-start;
2044
- }
2045
-
2046
2042
  .justify-end {
2047
2043
  justify-content: flex-end;
2048
2044
  }
@@ -2075,6 +2071,10 @@ select {
2075
2071
  gap: 1.5rem;
2076
2072
  }
2077
2073
 
2074
+ .gap-8 {
2075
+ gap: 2rem;
2076
+ }
2077
+
2078
2078
  .overflow-hidden {
2079
2079
  overflow: hidden;
2080
2080
  }
@@ -3440,6 +3440,14 @@ body {
3440
3440
  .md\:grid-cols-3 {
3441
3441
  grid-template-columns: repeat(3, minmax(0, 1fr));
3442
3442
  }
3443
+
3444
+ .md\:border-l {
3445
+ border-left-width: 1px;
3446
+ }
3447
+
3448
+ .md\:pl-8 {
3449
+ padding-left: 2rem;
3450
+ }
3443
3451
  }
3444
3452
 
3445
3453
  @media (min-width: 1024px) {
@@ -3455,6 +3463,10 @@ body {
3455
3463
  display: flex;
3456
3464
  }
3457
3465
 
3466
+ .lg\:grid-cols-2 {
3467
+ grid-template-columns: repeat(2, minmax(0, 1fr));
3468
+ }
3469
+
3458
3470
  .lg\:grid-cols-3 {
3459
3471
  grid-template-columns: repeat(3, minmax(0, 1fr));
3460
3472
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raketa-cloud/admin",
3
- "version": "1.9.7",
3
+ "version": "1.10.0",
4
4
  "main": "src/index.js",
5
5
  "files": [
6
6
  "src/",
@@ -1,7 +1,7 @@
1
1
  const WORKFLOWS_MAP = {
2
- lokalise_to_ai_rt_hum: "Lokalise: AI translation (DeepL) & Human review",
2
+ lokalise_tt_ai_rt_hum: "Lokalise: AI translation (Pro AI) & Human review",
3
3
  lokalise_tt_hum: "Lokalise: Human translation",
4
- lokalise_tt_ai: "Lokalise: AI translation",
4
+ lokalise_tt_ai: "Lokalise: AI translation (Pro AI)",
5
5
  };
6
6
 
7
7
  export const workflowsMap = (workflowType) => {
@@ -8,13 +8,15 @@ import {
8
8
  describe("content_tasks_helper", () => {
9
9
  describe("workflowsMap", () => {
10
10
  test("returns correct workflow name for known type", () => {
11
- expect(workflowsMap("lokalise_to_ai_rt_hum")).toBe(
12
- "Lokalise: AI translation (DeepL) & Human review",
11
+ expect(workflowsMap("lokalise_tt_ai_rt_hum")).toBe(
12
+ "Lokalise: AI translation (Pro AI) & Human review",
13
13
  );
14
14
  expect(workflowsMap("lokalise_tt_hum")).toBe(
15
15
  "Lokalise: Human translation",
16
16
  );
17
- expect(workflowsMap("lokalise_tt_ai")).toBe("Lokalise: AI translation");
17
+ expect(workflowsMap("lokalise_tt_ai")).toBe(
18
+ "Lokalise: AI translation (Pro AI)",
19
+ );
18
20
  });
19
21
 
20
22
  test("returns 'Unknown workflow' for unknown type", () => {
@@ -1,5 +1,26 @@
1
1
  <% form_for({ resource }, errors, (f) => { %>
2
- <form action="<%= `/${_context.locale}/${_context.resourceConfig.resourceType}_revisions/${resource.id}/meta` %>" method="POST" class="form">
2
+ <form
3
+ action="<%= `/${_context.locale}/${_context.resourceConfig.resourceType}_revisions/${resource.id}/meta` %>"
4
+ method="POST"
5
+ class="form"
6
+ hx-on:input="
7
+ const title = this.querySelector('[name*=\'[title]\']')?.value || '';
8
+ const desc = this.querySelector('[name*=\'[description]\']')?.value || '';
9
+ document.querySelectorAll('web-opengraph-google, web-opengraph-linkedin, web-opengraph-x').forEach(el => {
10
+ el.setAttribute('title', title);
11
+ el.setAttribute('description', desc);
12
+ });
13
+ "
14
+ hx-on:image-changed="
15
+ try {
16
+ const data = typeof event.detail === 'string' ? JSON.parse(event.detail) : (event.detail || {});
17
+ const imgUrl = data?.image?.urls?.original || data?.urls?.original || '';
18
+ document.querySelectorAll('web-opengraph-google, web-opengraph-linkedin, web-opengraph-x').forEach(el => {
19
+ el.setAttribute('image', imgUrl);
20
+ });
21
+ } catch(e) {}
22
+ "
23
+ >
3
24
  <%- f.field('resource.settings.meta.title', { required: true, label: "Meta title", hint: "Used for both meta and OpenGraph" }) %>
4
25
  <%- f.field('resource.settings.meta.description', { as: "textarea", required: true, label: "Meta description", hint: "Used for both meta and OpenGraph" }) %>
5
26
 
@@ -14,3 +35,27 @@
14
35
  </div>
15
36
  </form>
16
37
  <% }) %>
38
+
39
+ <script>
40
+ document.addEventListener('DOMContentLoaded', () => {
41
+ const hookPicker = () => {
42
+ const picker = document.querySelector('raketa-image-picker');
43
+ if (!picker) return;
44
+ const hiddenInput = picker.hiddenInput || document.querySelector('input[type="hidden"][name="resource[settings][meta][image]"]');
45
+ if (hiddenInput && !hiddenInput._hooked) {
46
+ hiddenInput._hooked = true;
47
+ const originalDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
48
+ Object.defineProperty(hiddenInput, 'value', {
49
+ get() { return originalDescriptor.get.call(hiddenInput); },
50
+ set(val) {
51
+ originalDescriptor.set.call(hiddenInput, val);
52
+ hiddenInput.setAttribute('value', val);
53
+ hiddenInput.dispatchEvent(new CustomEvent('image-changed', { bubbles: true, detail: val }));
54
+ }
55
+ });
56
+ }
57
+ };
58
+ hookPicker();
59
+ setTimeout(hookPicker, 300);
60
+ });
61
+ </script>
@@ -8,9 +8,75 @@
8
8
 
9
9
  <%- render_partial('../_nav.ejs', { resource, active: 'meta' }) %>
10
10
 
11
- <div class="grid gap-4 md:grid-cols-3">
11
+ <%
12
+ const ogConfig = _context.globalConfig?.openGraphPreviews;
13
+ const networks = ogConfig?.networks || [];
14
+ const showSidebar = Array.isArray(networks) && networks.length > 0;
15
+ %>
16
+
17
+ <div class="<%= showSidebar ? 'grid gap-8 lg:grid-cols-2 items-start' : '' %>">
12
18
  <div>
13
19
  <%- render_partial('_form.ejs') %>
14
20
  </div>
21
+ <% if (showSidebar) { %>
22
+ <div class="sticky top-4 pb-8 md:border-l md:pl-8" id="meta-previews">
23
+ <h3 class="heading-2 mb-4 flex gap-1 items-center">
24
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6 text-raketa-primary">
25
+ <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" />
26
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
27
+ </svg>
28
+
29
+ Previews
30
+ </h3>
31
+
32
+ <% const pageURL = _context.remoteConfig.resourceUrl(resource, _context.resourceConfig.resourceType, _context.locale); %>
33
+ <% networks.forEach((network, index) => { %>
34
+ <% if (network === 'google') { %>
35
+ <h4 class="heading-3 mb-4">Google Search Result</h4>
36
+ <web-opengraph-google
37
+ title="<%= resource.settings?.meta?.title || '' %>"
38
+ description="<%= resource.settings?.meta?.description || '' %>"
39
+ url="<%= pageURL %>"
40
+ image="<%= resource.settings?.meta?.image?.image?.urls?.original || resource.settings?.meta?.image?.urls?.original || '' %>"
41
+ site-name="<%= ogConfig?.siteName || '' %>"
42
+ favicon="<%= ogConfig?.faviconURL || '' %>"
43
+ date="Today"
44
+ ></web-opengraph-google>
45
+ <% } else if (network === 'linkedin') { %>
46
+ <h4 class="heading-3 mb-4">LinkedIn</h4>
47
+ <web-opengraph-linkedin
48
+ title="<%= resource.settings?.meta?.title || '' %>"
49
+ description="<%= resource.settings?.meta?.description || '' %>"
50
+ url="<%= pageURL %>"
51
+ image="<%= resource.settings?.meta?.image?.image?.urls?.original || resource.settings?.meta?.image?.urls?.original || '' %>"
52
+ ></web-opengraph-linkedin>
53
+ <% } else if (network === 'twitter') { %>
54
+ <h4 class="heading-3 mb-4">X/Twitter</h4>
55
+ <web-opengraph-x
56
+ title="<%= resource.settings?.meta?.title || '' %>"
57
+ description="<%= resource.settings?.meta?.description || '' %>"
58
+ url="<%= pageURL %>"
59
+ image="<%= resource.settings?.meta?.image?.image?.urls?.original || resource.settings?.meta?.image?.urls?.original || '' %>"
60
+ ></web-opengraph-x>
61
+ <% } %>
62
+
63
+ <% if (index < networks.length - 1) { %>
64
+ <hr class="my-4" />
65
+ <% } %>
66
+ <% }); %>
67
+ </div>
68
+ <% } %>
15
69
  </div>
16
70
  </div>
71
+
72
+ <% if (showSidebar) { %>
73
+ <% if (networks.includes('google')) { %>
74
+ <script src="https://storage.googleapis.com/cdn-raketa-cloud/js/raketa-opengraph-google-webcomponent.umd.js?cache=20260925-2"></script>
75
+ <% } %>
76
+ <% if (networks.includes('linkedin')) { %>
77
+ <script src="https://storage.googleapis.com/cdn-raketa-cloud/js/raketa-opengraph-linkedin-webcomponent.umd.js?cache=20260925-2"></script>
78
+ <% } %>
79
+ <% if (networks.includes('twitter')) { %>
80
+ <script src="https://storage.googleapis.com/cdn-raketa-cloud/js/raketa-opengraph-x-webcomponent.umd.js?cache=20260925-2"></script>
81
+ <% } %>
82
+ <% } %>
@@ -36,8 +36,8 @@
36
36
  <select name="resource[workflow][type]" id="workflow">
37
37
  <option value="">Default (no workflow)</option>
38
38
 
39
- <option value="LOKALISE_TO_AI_RT_HUM" <%= resource.workflow?.type === 'LOKALISE_TO_AI_RT_HUM' ? 'selected' : '' %>>
40
- <%= content_tasks.workflowsMap("LOKALISE_TO_AI_RT_HUM".toLowerCase()) %>
39
+ <option value="LOKALISE_TT_AI_RT_HUM" <%= resource.workflow?.type === 'LOKALISE_TT_AI_RT_HUM' ? 'selected' : '' %>>
40
+ <%= content_tasks.workflowsMap("LOKALISE_TT_AI_RT_HUM".toLowerCase()) %>
41
41
  </option>
42
42
 
43
43
  <option value="LOKALISE_TT_HUM" <%= resource.workflow?.type === 'LOKALISE_TT_HUM' ? 'selected' : '' %>>