@translationstudio/translationstudio-strapi-extension 4.3.0 → 5.0.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.
package/dist/Types.d.ts CHANGED
@@ -171,15 +171,25 @@ export interface Entry {
171
171
  [key: string]: any;
172
172
  }
173
173
  export interface BulkTranslationMenuProps {
174
- historyData: HistoryDataMap;
174
+ groupedHistoryData: GroupedHistoryItem[];
175
175
  isLoadingHistory: boolean;
176
176
  onTranslationComplete?: () => void;
177
177
  }
178
178
  export interface BulkTranslationPanelProps {
179
179
  contentType: ContentType | undefined;
180
180
  selectedEntries: string[];
181
+ onClose: () => void;
181
182
  onTranslationComplete: () => void;
182
183
  }
183
184
  export interface EntryHistoryProps {
184
185
  entryUid?: string;
185
186
  }
187
+ export type TranslationStatus = "translated" | "intranslation" | "queued";
188
+ export type GroupedHistoryItem = {
189
+ "element-name": string;
190
+ 'element-uid': string;
191
+ timeUpdated: number;
192
+ targetLanguage: string;
193
+ status: TranslationStatus;
194
+ id: string;
195
+ };
@@ -5,16 +5,16 @@ const admin = require("@strapi/strapi/admin");
5
5
  const reactRouterDom = require("react-router-dom");
6
6
  const designSystem = require("@strapi/design-system");
7
7
  const react = require("react");
8
- const index = require("./index-Dgpsawos.js");
8
+ const index = require("./index-rTLjDSHt.js");
9
9
  const apiService = {
10
10
  async loadLicense(get) {
11
11
  try {
12
12
  const response = await get("/translationstudio/getLicense");
13
- return response.data?.license || "";
13
+ return response.status === 204;
14
14
  } catch (err) {
15
15
  console.error(err);
16
- return "";
17
16
  }
17
+ return false;
18
18
  },
19
19
  async loadDevUrl(get) {
20
20
  try {
@@ -79,6 +79,8 @@ const SettingsPage = () => {
79
79
  const [showAlert, setShowAlert] = react.useState(false);
80
80
  const [alertType, setAlertType] = react.useState("success");
81
81
  const [alertMessage, setAlertMessage] = react.useState("");
82
+ const [originalLicense, setOriginalLicense] = react.useState(false);
83
+ const [hasToken, setHasToken] = react.useState(false);
82
84
  const { get, post } = admin.getFetchClient();
83
85
  const displayAlert = react.useCallback((variant, message) => {
84
86
  const defaultMessage = variant === "success" ? "License saved" : "Error saving license";
@@ -95,7 +97,8 @@ const SettingsPage = () => {
95
97
  apiService.loadLicense(get),
96
98
  apiService.loadDevUrl(get)
97
99
  ]);
98
- if (license) setLicenseValue(license);
100
+ if (license)
101
+ setOriginalLicense(license);
99
102
  if (devUrlData) {
100
103
  setDevUrl(devUrlData);
101
104
  setShowDevOptions(true);
@@ -107,13 +110,13 @@ const SettingsPage = () => {
107
110
  }
108
111
  };
109
112
  loadInitialData();
110
- }, [setIsLoading, setDevUrl, setLicenseValue, setShowDevOptions]);
113
+ }, [setIsLoading, setDevUrl, setShowDevOptions, setOriginalLicense]);
111
114
  react.useEffect(() => {
112
115
  const fetchToken = async () => {
113
116
  setIsLoadingToken(true);
114
117
  try {
115
118
  const response = await get("/translationstudio/getToken");
116
- setTokenValue(response.data?.token || "");
119
+ setHasToken(response.data?.token ? true : false);
117
120
  } catch (err) {
118
121
  console.error(err);
119
122
  } finally {
@@ -121,7 +124,7 @@ const SettingsPage = () => {
121
124
  }
122
125
  };
123
126
  fetchToken();
124
- }, []);
127
+ }, [setIsLoadingToken, setHasToken]);
125
128
  const handleLicenseChange = react.useCallback((e) => {
126
129
  setLicenseValue(e.target.value.trim());
127
130
  }, []);
@@ -129,11 +132,12 @@ const SettingsPage = () => {
129
132
  try {
130
133
  await post("/translationstudio/setLicense", { license: licenseValue });
131
134
  displayAlert("success");
135
+ setOriginalLicense(true);
132
136
  } catch (err) {
133
137
  console.error(err);
134
138
  displayAlert("danger");
135
139
  }
136
- }, [post, licenseValue, displayAlert]);
140
+ }, [post, licenseValue, setOriginalLicense, displayAlert]);
137
141
  const handleGenerateToken = react.useCallback(async () => {
138
142
  setIsLoadingToken(true);
139
143
  try {
@@ -178,7 +182,6 @@ const SettingsPage = () => {
178
182
  onClick,
179
183
  disabled,
180
184
  loading,
181
- style: styles.button,
182
185
  size: "L",
183
186
  startIcon: icon,
184
187
  children
@@ -215,6 +218,7 @@ const SettingsPage = () => {
215
218
  " ",
216
219
  /* @__PURE__ */ jsxRuntime.jsx(LinkText, { href: "https://account.translationstudio.tech/", children: "account.translationstudio.tech" })
217
220
  ] }) }),
221
+ originalLicense && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 12, style: { paddingBottom: "2em" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: "License is available." }) }),
218
222
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 10, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "block", width: "95%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
219
223
  designSystem.TextInput,
220
224
  {
@@ -227,11 +231,11 @@ const SettingsPage = () => {
227
231
  style: styles.textInput
228
232
  }
229
233
  ) }) }),
230
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
234
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(
231
235
  ActionButton,
232
236
  {
233
237
  onClick: handleSaveLicense,
234
- disabled: isLoading,
238
+ disabled: isLoading || licenseValue.length < 30,
235
239
  icon: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
236
240
  "path",
237
241
  {
@@ -239,25 +243,17 @@ const SettingsPage = () => {
239
243
  fill: "currentColor"
240
244
  }
241
245
  ) }),
242
- children: "Save license"
246
+ children: [
247
+ originalLicense ? "Update" : "Save",
248
+ " license"
249
+ ]
243
250
  }
244
251
  ) }),
245
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 12, style: { paddingTop: "3em" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: "Authorize translationstudio requests" }) }),
246
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 12, style: { paddingBottom: "1em" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "charlie", children: "When translationstudio connects with this plugin it will use the following access key to authorize itself." }) }),
247
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 10, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "block", width: "95%" }, children: /* @__PURE__ */ jsxRuntime.jsx(
248
- designSystem.TextInput,
249
- {
250
- name: "access-token",
251
- label: "Access Key",
252
- placeholder: "Generate an access key to validate incoming requests",
253
- value: tokenValue,
254
- onChange: () => {
255
- },
256
- disabled: true,
257
- style: styles.textInput
258
- }
259
- ) }) }),
260
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
252
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 10, style: { paddingTop: "5em" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
253
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: "Authorize translationstudio requests" }) }),
254
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "charlie", style: { paddingBottom: "1em" }, children: "When translationstudio connects with this plugin it will use the following access key to authorize itself." }) })
255
+ ] }) }),
256
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 2, style: { textAlign: "right", paddingTop: "5em" }, children: /* @__PURE__ */ jsxRuntime.jsx(
261
257
  ActionButton,
262
258
  {
263
259
  onClick: handleGenerateToken,
@@ -270,9 +266,10 @@ const SettingsPage = () => {
270
266
  fill: "currentColor"
271
267
  }
272
268
  ) }),
273
- children: isLoadingToken ? "Generating..." : tokenValue ? "New access key" : "Create access key"
269
+ children: isLoadingToken ? "Generating..." : "Generate new access key"
274
270
  }
275
271
  ) }),
272
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 12, style: { paddingTop: "2em" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { style: { overflow: "hidden" }, children: tokenValue ? tokenValue : hasToken ? "Your existing access token will remain a secret" : "Generate an access key to validate incoming requests" }) }),
276
273
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 12, style: { paddingTop: "5em" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: "Customization" }) }),
277
274
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 12, style: { paddingBottom: "1em" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "charlie", children: "You will not need these settings, but you might want to customize your translationstudio instance." }) }),
278
275
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { xs: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -1,18 +1,18 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { getFetchClient, Page } from "@strapi/strapi/admin";
3
3
  import { Routes, Route } from "react-router-dom";
4
- import { Main, Box, Alert, Grid, Typography, TextInput, Switch, Button } from "@strapi/design-system";
4
+ import { Main, Box, Alert, Grid, Typography, Badge, TextInput, Switch, Button } from "@strapi/design-system";
5
5
  import { useState, useCallback, useEffect } from "react";
6
- import { T as TranslationstudioLogo } from "./index-Csx0xlBL.mjs";
6
+ import { T as TranslationstudioLogo } from "./index-DZinmQcT.mjs";
7
7
  const apiService = {
8
8
  async loadLicense(get) {
9
9
  try {
10
10
  const response = await get("/translationstudio/getLicense");
11
- return response.data?.license || "";
11
+ return response.status === 204;
12
12
  } catch (err) {
13
13
  console.error(err);
14
- return "";
15
14
  }
15
+ return false;
16
16
  },
17
17
  async loadDevUrl(get) {
18
18
  try {
@@ -77,6 +77,8 @@ const SettingsPage = () => {
77
77
  const [showAlert, setShowAlert] = useState(false);
78
78
  const [alertType, setAlertType] = useState("success");
79
79
  const [alertMessage, setAlertMessage] = useState("");
80
+ const [originalLicense, setOriginalLicense] = useState(false);
81
+ const [hasToken, setHasToken] = useState(false);
80
82
  const { get, post } = getFetchClient();
81
83
  const displayAlert = useCallback((variant, message) => {
82
84
  const defaultMessage = variant === "success" ? "License saved" : "Error saving license";
@@ -93,7 +95,8 @@ const SettingsPage = () => {
93
95
  apiService.loadLicense(get),
94
96
  apiService.loadDevUrl(get)
95
97
  ]);
96
- if (license) setLicenseValue(license);
98
+ if (license)
99
+ setOriginalLicense(license);
97
100
  if (devUrlData) {
98
101
  setDevUrl(devUrlData);
99
102
  setShowDevOptions(true);
@@ -105,13 +108,13 @@ const SettingsPage = () => {
105
108
  }
106
109
  };
107
110
  loadInitialData();
108
- }, [setIsLoading, setDevUrl, setLicenseValue, setShowDevOptions]);
111
+ }, [setIsLoading, setDevUrl, setShowDevOptions, setOriginalLicense]);
109
112
  useEffect(() => {
110
113
  const fetchToken = async () => {
111
114
  setIsLoadingToken(true);
112
115
  try {
113
116
  const response = await get("/translationstudio/getToken");
114
- setTokenValue(response.data?.token || "");
117
+ setHasToken(response.data?.token ? true : false);
115
118
  } catch (err) {
116
119
  console.error(err);
117
120
  } finally {
@@ -119,7 +122,7 @@ const SettingsPage = () => {
119
122
  }
120
123
  };
121
124
  fetchToken();
122
- }, []);
125
+ }, [setIsLoadingToken, setHasToken]);
123
126
  const handleLicenseChange = useCallback((e) => {
124
127
  setLicenseValue(e.target.value.trim());
125
128
  }, []);
@@ -127,11 +130,12 @@ const SettingsPage = () => {
127
130
  try {
128
131
  await post("/translationstudio/setLicense", { license: licenseValue });
129
132
  displayAlert("success");
133
+ setOriginalLicense(true);
130
134
  } catch (err) {
131
135
  console.error(err);
132
136
  displayAlert("danger");
133
137
  }
134
- }, [post, licenseValue, displayAlert]);
138
+ }, [post, licenseValue, setOriginalLicense, displayAlert]);
135
139
  const handleGenerateToken = useCallback(async () => {
136
140
  setIsLoadingToken(true);
137
141
  try {
@@ -176,7 +180,6 @@ const SettingsPage = () => {
176
180
  onClick,
177
181
  disabled,
178
182
  loading,
179
- style: styles.button,
180
183
  size: "L",
181
184
  startIcon: icon,
182
185
  children
@@ -213,6 +216,7 @@ const SettingsPage = () => {
213
216
  " ",
214
217
  /* @__PURE__ */ jsx(LinkText, { href: "https://account.translationstudio.tech/", children: "account.translationstudio.tech" })
215
218
  ] }) }),
219
+ originalLicense && /* @__PURE__ */ jsx(Grid.Item, { xs: 12, style: { paddingBottom: "2em" }, children: /* @__PURE__ */ jsx(Badge, { children: "License is available." }) }),
216
220
  /* @__PURE__ */ jsx(Grid.Item, { xs: 10, children: /* @__PURE__ */ jsx("div", { style: { display: "block", width: "95%" }, children: /* @__PURE__ */ jsx(
217
221
  TextInput,
218
222
  {
@@ -225,11 +229,11 @@ const SettingsPage = () => {
225
229
  style: styles.textInput
226
230
  }
227
231
  ) }) }),
228
- /* @__PURE__ */ jsx(Grid.Item, { xs: 2, children: /* @__PURE__ */ jsx(
232
+ /* @__PURE__ */ jsx(Grid.Item, { xs: 2, children: /* @__PURE__ */ jsxs(
229
233
  ActionButton,
230
234
  {
231
235
  onClick: handleSaveLicense,
232
- disabled: isLoading,
236
+ disabled: isLoading || licenseValue.length < 30,
233
237
  icon: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
234
238
  "path",
235
239
  {
@@ -237,25 +241,17 @@ const SettingsPage = () => {
237
241
  fill: "currentColor"
238
242
  }
239
243
  ) }),
240
- children: "Save license"
244
+ children: [
245
+ originalLicense ? "Update" : "Save",
246
+ " license"
247
+ ]
241
248
  }
242
249
  ) }),
243
- /* @__PURE__ */ jsx(Grid.Item, { xs: 12, style: { paddingTop: "3em" }, children: /* @__PURE__ */ jsx(Typography, { variant: "beta", children: "Authorize translationstudio requests" }) }),
244
- /* @__PURE__ */ jsx(Grid.Item, { xs: 12, style: { paddingBottom: "1em" }, children: /* @__PURE__ */ jsx(Typography, { variant: "charlie", children: "When translationstudio connects with this plugin it will use the following access key to authorize itself." }) }),
245
- /* @__PURE__ */ jsx(Grid.Item, { xs: 10, children: /* @__PURE__ */ jsx("div", { style: { display: "block", width: "95%" }, children: /* @__PURE__ */ jsx(
246
- TextInput,
247
- {
248
- name: "access-token",
249
- label: "Access Key",
250
- placeholder: "Generate an access key to validate incoming requests",
251
- value: tokenValue,
252
- onChange: () => {
253
- },
254
- disabled: true,
255
- style: styles.textInput
256
- }
257
- ) }) }),
258
- /* @__PURE__ */ jsx(Grid.Item, { xs: 2, children: /* @__PURE__ */ jsx(
250
+ /* @__PURE__ */ jsx(Grid.Item, { xs: 10, style: { paddingTop: "5em" }, children: /* @__PURE__ */ jsxs(Box, { children: [
251
+ /* @__PURE__ */ jsx("h2", { children: /* @__PURE__ */ jsx(Typography, { variant: "beta", children: "Authorize translationstudio requests" }) }),
252
+ /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx(Typography, { variant: "charlie", style: { paddingBottom: "1em" }, children: "When translationstudio connects with this plugin it will use the following access key to authorize itself." }) })
253
+ ] }) }),
254
+ /* @__PURE__ */ jsx(Grid.Item, { xs: 2, style: { textAlign: "right", paddingTop: "5em" }, children: /* @__PURE__ */ jsx(
259
255
  ActionButton,
260
256
  {
261
257
  onClick: handleGenerateToken,
@@ -268,9 +264,10 @@ const SettingsPage = () => {
268
264
  fill: "currentColor"
269
265
  }
270
266
  ) }),
271
- children: isLoadingToken ? "Generating..." : tokenValue ? "New access key" : "Create access key"
267
+ children: isLoadingToken ? "Generating..." : "Generate new access key"
272
268
  }
273
269
  ) }),
270
+ /* @__PURE__ */ jsx(Grid.Item, { xs: 12, style: { paddingTop: "2em" }, children: /* @__PURE__ */ jsx(Badge, { style: { overflow: "hidden" }, children: tokenValue ? tokenValue : hasToken ? "Your existing access token will remain a secret" : "Generate an access key to validate incoming requests" }) }),
274
271
  /* @__PURE__ */ jsx(Grid.Item, { xs: 12, style: { paddingTop: "5em" }, children: /* @__PURE__ */ jsx(Typography, { variant: "beta", children: "Customization" }) }),
275
272
  /* @__PURE__ */ jsx(Grid.Item, { xs: 12, style: { paddingBottom: "1em" }, children: /* @__PURE__ */ jsx(Typography, { variant: "charlie", children: "You will not need these settings, but you might want to customize your translationstudio instance." }) }),
276
273
  /* @__PURE__ */ jsx(Grid.Item, { xs: 12, children: /* @__PURE__ */ jsx(