@deenruv/reviews-plugin 1.0.17-dev.4 → 1.0.17-dev.40
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/plugin-server/zeus/const.js +825 -849
- package/dist/plugin-server/zeus/index.d.ts +5161 -3981
- package/dist/plugin-server/zeus/index.js +85 -67
- package/dist/plugin-ui/components/ReviewCustomer.js +4 -2
- package/dist/plugin-ui/components/ReviewOrder.d.ts +2 -0
- package/dist/plugin-ui/components/ReviewOrder.js +15 -3
- package/dist/plugin-ui/index.js +2 -1
- package/dist/plugin-ui/pages/Review.js +5 -1
- package/dist/plugin-ui/pages/Reviews.js +2 -1
- package/dist/plugin-ui/translations.spec.d.ts +1 -0
- package/dist/plugin-ui/translations.spec.js +44 -0
- package/dist/plugin-ui/zeus/const.js +825 -849
- package/dist/plugin-ui/zeus/index.d.ts +5161 -3981
- package/dist/plugin-ui/zeus/index.js +85 -67
- package/dist/plugin-ui/zeus/typedDocumentNode.d.ts +2 -2
- package/dist/plugin-ui/zeus/typedDocumentNode.js +2 -2
- package/package.json +7 -7
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
import { AllTypesProps, ReturnTypes, Ops } from
|
|
3
|
-
export const HOST = "
|
|
2
|
+
import { AllTypesProps, ReturnTypes, Ops } from "./const.js";
|
|
3
|
+
export const HOST = "Specify host";
|
|
4
4
|
export const HEADERS = {};
|
|
5
5
|
export const apiSubscription = (options) => (query) => {
|
|
6
6
|
var _a, _b, _c;
|
|
7
7
|
try {
|
|
8
|
-
const queryString = options[0] +
|
|
9
|
-
const wsString = queryString.replace(
|
|
8
|
+
const queryString = options[0] + "?query=" + encodeURIComponent(query);
|
|
9
|
+
const wsString = queryString.replace("http", "ws");
|
|
10
10
|
const host = (options.length > 1 && ((_b = (_a = options[1]) === null || _a === void 0 ? void 0 : _a.websocket) === null || _b === void 0 ? void 0 : _b[0])) || wsString;
|
|
11
11
|
const webSocketOptions = ((_c = options[1]) === null || _c === void 0 ? void 0 : _c.websocket) || [host];
|
|
12
12
|
const ws = new WebSocket(...webSocketOptions);
|
|
@@ -33,7 +33,7 @@ export const apiSubscription = (options) => (query) => {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
catch (_d) {
|
|
36
|
-
throw new Error(
|
|
36
|
+
throw new Error("No websockets implemented");
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
39
|
const handleFetchResponse = (response) => {
|
|
@@ -56,7 +56,7 @@ const handleFetchResponse = (response) => {
|
|
|
56
56
|
};
|
|
57
57
|
export const apiFetch = (options) => (query, variables = {}) => {
|
|
58
58
|
const fetchOptions = options[1] || {};
|
|
59
|
-
if (fetchOptions.method && fetchOptions.method ===
|
|
59
|
+
if (fetchOptions.method && fetchOptions.method === "GET") {
|
|
60
60
|
return fetch(`${options[0]}?query=${encodeURIComponent(query)}`, fetchOptions)
|
|
61
61
|
.then(handleFetchResponse)
|
|
62
62
|
.then((response) => {
|
|
@@ -66,8 +66,8 @@ export const apiFetch = (options) => (query, variables = {}) => {
|
|
|
66
66
|
return response.data;
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
return fetch(`${options[0]}`, Object.assign({ body: JSON.stringify({ query, variables }), method:
|
|
70
|
-
|
|
69
|
+
return fetch(`${options[0]}`, Object.assign({ body: JSON.stringify({ query, variables }), method: "POST", headers: {
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
71
|
} }, fetchOptions))
|
|
72
72
|
.then(handleFetchResponse)
|
|
73
73
|
.then((response) => {
|
|
@@ -78,17 +78,17 @@ export const apiFetch = (options) => (query, variables = {}) => {
|
|
|
78
78
|
});
|
|
79
79
|
};
|
|
80
80
|
export const InternalsBuildQuery = ({ ops, props, returns, options, scalars, }) => {
|
|
81
|
-
const ibb = (k, o, p =
|
|
81
|
+
const ibb = (k, o, p = "", root = true, vars = []) => {
|
|
82
82
|
var _a;
|
|
83
83
|
const keyForPath = purifyGraphQLKey(k);
|
|
84
84
|
const newPath = [p, keyForPath].join(SEPARATOR);
|
|
85
85
|
if (!o) {
|
|
86
|
-
return
|
|
86
|
+
return "";
|
|
87
87
|
}
|
|
88
|
-
if (typeof o ===
|
|
88
|
+
if (typeof o === "boolean" || typeof o === "number") {
|
|
89
89
|
return k;
|
|
90
90
|
}
|
|
91
|
-
if (typeof o ===
|
|
91
|
+
if (typeof o === "string") {
|
|
92
92
|
return `${k} ${o}`;
|
|
93
93
|
}
|
|
94
94
|
if (Array.isArray(o)) {
|
|
@@ -101,29 +101,32 @@ export const InternalsBuildQuery = ({ ops, props, returns, options, scalars, })
|
|
|
101
101
|
})(o[0], newPath);
|
|
102
102
|
return `${ibb(args ? `${k}(${args})` : k, o[1], p, false, vars)}`;
|
|
103
103
|
}
|
|
104
|
-
if (k ===
|
|
104
|
+
if (k === "__alias") {
|
|
105
105
|
return Object.entries(o)
|
|
106
106
|
.map(([alias, objectUnderAlias]) => {
|
|
107
|
-
if (typeof objectUnderAlias !==
|
|
108
|
-
|
|
107
|
+
if (typeof objectUnderAlias !== "object" ||
|
|
108
|
+
Array.isArray(objectUnderAlias)) {
|
|
109
|
+
throw new Error("Invalid alias it should be __alias:{ YOUR_ALIAS_NAME: { OPERATION_NAME: { ...selectors }}}");
|
|
109
110
|
}
|
|
110
111
|
const operationName = Object.keys(objectUnderAlias)[0];
|
|
111
112
|
const operation = objectUnderAlias[operationName];
|
|
112
113
|
return ibb(`${alias}:${operationName}`, operation, p, false, vars);
|
|
113
114
|
})
|
|
114
|
-
.join(
|
|
115
|
+
.join("\n");
|
|
115
116
|
}
|
|
116
|
-
const hasOperationName = root && (options === null || options === void 0 ? void 0 : options.operationName) ?
|
|
117
|
-
const keyForDirectives = (_a = o.__directives) !== null && _a !== void 0 ? _a :
|
|
117
|
+
const hasOperationName = root && (options === null || options === void 0 ? void 0 : options.operationName) ? " " + options.operationName : "";
|
|
118
|
+
const keyForDirectives = (_a = o.__directives) !== null && _a !== void 0 ? _a : "";
|
|
118
119
|
const query = `{${Object.entries(o)
|
|
119
|
-
.filter(([k]) => k !==
|
|
120
|
+
.filter(([k]) => k !== "__directives")
|
|
120
121
|
.map((e) => ibb(...e, [p, `field<>${keyForPath}`].join(SEPARATOR), false, vars))
|
|
121
|
-
.join(
|
|
122
|
+
.join("\n")}}`;
|
|
122
123
|
if (!root) {
|
|
123
124
|
return `${k} ${keyForDirectives}${hasOperationName} ${query}`;
|
|
124
125
|
}
|
|
125
|
-
const varsString = vars
|
|
126
|
-
|
|
126
|
+
const varsString = vars
|
|
127
|
+
.map((v) => `${v.name}: ${v.graphQLType}`)
|
|
128
|
+
.join(", ");
|
|
129
|
+
return `${k} ${keyForDirectives}${hasOperationName}${varsString ? `(${varsString})` : ""} ${query}`;
|
|
127
130
|
};
|
|
128
131
|
return ibb;
|
|
129
132
|
};
|
|
@@ -183,7 +186,7 @@ export const ZeusSelect = () => ((t) => t);
|
|
|
183
186
|
export const Selector = (key) => key && ZeusSelect();
|
|
184
187
|
export const TypeFromSelector = (key) => key && ZeusSelect();
|
|
185
188
|
export const Gql = Chain(HOST, {
|
|
186
|
-
headers: Object.assign({
|
|
189
|
+
headers: Object.assign({ "Content-Type": "application/json" }, HEADERS),
|
|
187
190
|
});
|
|
188
191
|
export const ZeusScalars = ZeusSelect();
|
|
189
192
|
export const decodeScalarsInResponse = ({ response, scalars, returns, ops, initialZeusQuery, initialOp, }) => {
|
|
@@ -213,12 +216,15 @@ export const traverseResponse = ({ resolvers, scalarPaths, }) => {
|
|
|
213
216
|
const scalarPathString = p.join(SEPARATOR);
|
|
214
217
|
const currentScalarString = scalarPaths[scalarPathString];
|
|
215
218
|
if (currentScalarString) {
|
|
216
|
-
const currentDecoder = (_a = resolvers[currentScalarString.split(
|
|
219
|
+
const currentDecoder = (_a = resolvers[currentScalarString.split(".")[1]]) === null || _a === void 0 ? void 0 : _a.decode;
|
|
217
220
|
if (currentDecoder) {
|
|
218
221
|
return currentDecoder(o);
|
|
219
222
|
}
|
|
220
223
|
}
|
|
221
|
-
if (typeof o ===
|
|
224
|
+
if (typeof o === "boolean" ||
|
|
225
|
+
typeof o === "number" ||
|
|
226
|
+
typeof o === "string" ||
|
|
227
|
+
!o) {
|
|
222
228
|
return o;
|
|
223
229
|
}
|
|
224
230
|
const entries = Object.entries(o).map(([k, v]) => [k, ibb(k, v, [...p, purifyGraphQLKey(k)])]);
|
|
@@ -230,15 +236,15 @@ export const traverseResponse = ({ resolvers, scalarPaths, }) => {
|
|
|
230
236
|
};
|
|
231
237
|
return ibb;
|
|
232
238
|
};
|
|
233
|
-
export const SEPARATOR =
|
|
239
|
+
export const SEPARATOR = "|";
|
|
234
240
|
export class GraphQLError extends Error {
|
|
235
241
|
constructor(response) {
|
|
236
|
-
super(
|
|
242
|
+
super("");
|
|
237
243
|
this.response = response;
|
|
238
244
|
console.error(response);
|
|
239
245
|
}
|
|
240
246
|
toString() {
|
|
241
|
-
return
|
|
247
|
+
return "GraphQL Response Error";
|
|
242
248
|
}
|
|
243
249
|
}
|
|
244
250
|
const ExtractScalar = (mappedParts, returns) => {
|
|
@@ -247,7 +253,7 @@ const ExtractScalar = (mappedParts, returns) => {
|
|
|
247
253
|
}
|
|
248
254
|
const oKey = mappedParts[0];
|
|
249
255
|
const returnP1 = returns[oKey];
|
|
250
|
-
if (typeof returnP1 ===
|
|
256
|
+
if (typeof returnP1 === "object") {
|
|
251
257
|
const returnP2 = returnP1[mappedParts[1]];
|
|
252
258
|
if (returnP2) {
|
|
253
259
|
return ExtractScalar([returnP2, ...mappedParts.slice(2)], returns);
|
|
@@ -256,15 +262,17 @@ const ExtractScalar = (mappedParts, returns) => {
|
|
|
256
262
|
}
|
|
257
263
|
return returnP1;
|
|
258
264
|
};
|
|
259
|
-
export const PrepareScalarPaths = ({ ops, returns }) => {
|
|
265
|
+
export const PrepareScalarPaths = ({ ops, returns, }) => {
|
|
260
266
|
const ibb = (k, originalKey, o, p = [], pOriginals = [], root = true) => {
|
|
261
267
|
if (!o) {
|
|
262
268
|
return;
|
|
263
269
|
}
|
|
264
|
-
if (typeof o ===
|
|
270
|
+
if (typeof o === "boolean" ||
|
|
271
|
+
typeof o === "number" ||
|
|
272
|
+
typeof o === "string") {
|
|
265
273
|
const extractionArray = [...pOriginals, originalKey];
|
|
266
274
|
const isScalar = ExtractScalar(extractionArray, returns);
|
|
267
|
-
if (isScalar === null || isScalar === void 0 ? void 0 : isScalar.startsWith(
|
|
275
|
+
if (isScalar === null || isScalar === void 0 ? void 0 : isScalar.startsWith("scalar")) {
|
|
268
276
|
const partOfTree = {
|
|
269
277
|
[[...p, k].join(SEPARATOR)]: isScalar,
|
|
270
278
|
};
|
|
@@ -275,11 +283,12 @@ export const PrepareScalarPaths = ({ ops, returns }) => {
|
|
|
275
283
|
if (Array.isArray(o)) {
|
|
276
284
|
return ibb(k, k, o[1], p, pOriginals, false);
|
|
277
285
|
}
|
|
278
|
-
if (k ===
|
|
286
|
+
if (k === "__alias") {
|
|
279
287
|
return Object.entries(o)
|
|
280
288
|
.map(([alias, objectUnderAlias]) => {
|
|
281
|
-
if (typeof objectUnderAlias !==
|
|
282
|
-
|
|
289
|
+
if (typeof objectUnderAlias !== "object" ||
|
|
290
|
+
Array.isArray(objectUnderAlias)) {
|
|
291
|
+
throw new Error("Invalid alias it should be __alias:{ YOUR_ALIAS_NAME: { OPERATION_NAME: { ...selectors }}}");
|
|
283
292
|
}
|
|
284
293
|
const operationName = Object.keys(objectUnderAlias)[0];
|
|
285
294
|
const operation = objectUnderAlias[operationName];
|
|
@@ -289,57 +298,61 @@ export const PrepareScalarPaths = ({ ops, returns }) => {
|
|
|
289
298
|
}
|
|
290
299
|
const keyName = root ? ops[k] : k;
|
|
291
300
|
return Object.entries(o)
|
|
292
|
-
.filter(([k]) => k !==
|
|
301
|
+
.filter(([k]) => k !== "__directives")
|
|
293
302
|
.map(([k, v]) => {
|
|
294
303
|
// Inline fragments shouldn't be added to the path as they aren't a field
|
|
295
304
|
const isInlineFragment = originalKey.match(/^...\s*on/) != null;
|
|
296
|
-
return ibb(k, k, v, isInlineFragment ? p : [...p, purifyGraphQLKey(keyName || k)], isInlineFragment
|
|
305
|
+
return ibb(k, k, v, isInlineFragment ? p : [...p, purifyGraphQLKey(keyName || k)], isInlineFragment
|
|
306
|
+
? pOriginals
|
|
307
|
+
: [...pOriginals, purifyGraphQLKey(originalKey)], false);
|
|
297
308
|
})
|
|
298
309
|
.reduce((a, b) => (Object.assign(Object.assign({}, a), b)));
|
|
299
310
|
};
|
|
300
311
|
return ibb;
|
|
301
312
|
};
|
|
302
|
-
export const purifyGraphQLKey = (k) => k.replace(/\([^)]*\)/g,
|
|
313
|
+
export const purifyGraphQLKey = (k) => k.replace(/\([^)]*\)/g, "").replace(/^[^:]*\:/g, "");
|
|
303
314
|
const mapPart = (p) => {
|
|
304
|
-
const [isArg, isField] = p.split(
|
|
315
|
+
const [isArg, isField] = p.split("<>");
|
|
305
316
|
if (isField) {
|
|
306
317
|
return {
|
|
307
318
|
v: isField,
|
|
308
|
-
__type:
|
|
319
|
+
__type: "field",
|
|
309
320
|
};
|
|
310
321
|
}
|
|
311
322
|
return {
|
|
312
323
|
v: isArg,
|
|
313
|
-
__type:
|
|
324
|
+
__type: "arg",
|
|
314
325
|
};
|
|
315
326
|
};
|
|
316
327
|
export const ResolveFromPath = (props, returns, ops) => {
|
|
317
328
|
const ResolvePropsType = (mappedParts) => {
|
|
318
329
|
const oKey = ops[mappedParts[0].v];
|
|
319
330
|
const propsP1 = oKey ? props[oKey] : props[mappedParts[0].v];
|
|
320
|
-
if (propsP1 ===
|
|
321
|
-
return
|
|
331
|
+
if (propsP1 === "enum" && mappedParts.length === 1) {
|
|
332
|
+
return "enum";
|
|
322
333
|
}
|
|
323
|
-
if (typeof propsP1 ===
|
|
334
|
+
if (typeof propsP1 === "string" &&
|
|
335
|
+
propsP1.startsWith("scalar.") &&
|
|
336
|
+
mappedParts.length === 1) {
|
|
324
337
|
return propsP1;
|
|
325
338
|
}
|
|
326
|
-
if (typeof propsP1 ===
|
|
339
|
+
if (typeof propsP1 === "object") {
|
|
327
340
|
if (mappedParts.length < 2) {
|
|
328
|
-
return
|
|
341
|
+
return "not";
|
|
329
342
|
}
|
|
330
343
|
const propsP2 = propsP1[mappedParts[1].v];
|
|
331
|
-
if (typeof propsP2 ===
|
|
344
|
+
if (typeof propsP2 === "string") {
|
|
332
345
|
return rpp(`${propsP2}${SEPARATOR}${mappedParts
|
|
333
346
|
.slice(2)
|
|
334
347
|
.map((mp) => mp.v)
|
|
335
348
|
.join(SEPARATOR)}`);
|
|
336
349
|
}
|
|
337
|
-
if (typeof propsP2 ===
|
|
350
|
+
if (typeof propsP2 === "object") {
|
|
338
351
|
if (mappedParts.length < 3) {
|
|
339
|
-
return
|
|
352
|
+
return "not";
|
|
340
353
|
}
|
|
341
354
|
const propsP3 = propsP2[mappedParts[2].v];
|
|
342
|
-
if (propsP3 && mappedParts[2].__type ===
|
|
355
|
+
if (propsP3 && mappedParts[2].__type === "arg") {
|
|
343
356
|
return rpp(`${propsP3}${SEPARATOR}${mappedParts
|
|
344
357
|
.slice(3)
|
|
345
358
|
.map((mp) => mp.v)
|
|
@@ -350,13 +363,13 @@ export const ResolveFromPath = (props, returns, ops) => {
|
|
|
350
363
|
};
|
|
351
364
|
const ResolveReturnType = (mappedParts) => {
|
|
352
365
|
if (mappedParts.length === 0) {
|
|
353
|
-
return
|
|
366
|
+
return "not";
|
|
354
367
|
}
|
|
355
368
|
const oKey = ops[mappedParts[0].v];
|
|
356
369
|
const returnP1 = oKey ? returns[oKey] : returns[mappedParts[0].v];
|
|
357
|
-
if (typeof returnP1 ===
|
|
370
|
+
if (typeof returnP1 === "object") {
|
|
358
371
|
if (mappedParts.length < 2)
|
|
359
|
-
return
|
|
372
|
+
return "not";
|
|
360
373
|
const returnP2 = returnP1[mappedParts[1].v];
|
|
361
374
|
if (returnP2) {
|
|
362
375
|
return rpp(`${returnP2}${SEPARATOR}${mappedParts
|
|
@@ -377,16 +390,18 @@ export const ResolveFromPath = (props, returns, ops) => {
|
|
|
377
390
|
if (returnP1) {
|
|
378
391
|
return returnP1;
|
|
379
392
|
}
|
|
380
|
-
return
|
|
393
|
+
return "not";
|
|
381
394
|
};
|
|
382
395
|
return rpp;
|
|
383
396
|
};
|
|
384
397
|
export const InternalArgsBuilt = ({ props, ops, returns, scalars, vars, }) => {
|
|
385
|
-
const arb = (a, p =
|
|
398
|
+
const arb = (a, p = "", root = true) => {
|
|
386
399
|
var _a, _b;
|
|
387
|
-
if (typeof a ===
|
|
400
|
+
if (typeof a === "string") {
|
|
388
401
|
if (a.startsWith(START_VAR_NAME)) {
|
|
389
|
-
const [varName, graphQLType] = a
|
|
402
|
+
const [varName, graphQLType] = a
|
|
403
|
+
.replace(START_VAR_NAME, "$")
|
|
404
|
+
.split(GRAPHQL_TYPE_SEPARATOR);
|
|
390
405
|
const v = vars.find((v) => v.name === varName);
|
|
391
406
|
if (!v) {
|
|
392
407
|
vars.push({
|
|
@@ -403,29 +418,29 @@ export const InternalArgsBuilt = ({ props, ops, returns, scalars, vars, }) => {
|
|
|
403
418
|
}
|
|
404
419
|
}
|
|
405
420
|
const checkType = ResolveFromPath(props, returns, ops)(p);
|
|
406
|
-
if (checkType.startsWith(
|
|
421
|
+
if (checkType.startsWith("scalar.")) {
|
|
407
422
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
408
|
-
const [_, ...splittedScalar] = checkType.split(
|
|
409
|
-
const scalarKey = splittedScalar.join(
|
|
423
|
+
const [_, ...splittedScalar] = checkType.split(".");
|
|
424
|
+
const scalarKey = splittedScalar.join(".");
|
|
410
425
|
return ((_b = (_a = scalars === null || scalars === void 0 ? void 0 : scalars[scalarKey]) === null || _a === void 0 ? void 0 : _a.encode) === null || _b === void 0 ? void 0 : _b.call(_a, a)) || JSON.stringify(a);
|
|
411
426
|
}
|
|
412
427
|
if (Array.isArray(a)) {
|
|
413
|
-
return `[${a.map((arr) => arb(arr, p, false)).join(
|
|
428
|
+
return `[${a.map((arr) => arb(arr, p, false)).join(", ")}]`;
|
|
414
429
|
}
|
|
415
|
-
if (typeof a ===
|
|
416
|
-
if (checkType ===
|
|
430
|
+
if (typeof a === "string") {
|
|
431
|
+
if (checkType === "enum") {
|
|
417
432
|
return a;
|
|
418
433
|
}
|
|
419
434
|
return `${JSON.stringify(a)}`;
|
|
420
435
|
}
|
|
421
|
-
if (typeof a ===
|
|
436
|
+
if (typeof a === "object") {
|
|
422
437
|
if (a === null) {
|
|
423
438
|
return `null`;
|
|
424
439
|
}
|
|
425
440
|
const returnedObjectString = Object.entries(a)
|
|
426
|
-
.filter(([, v]) => typeof v !==
|
|
441
|
+
.filter(([, v]) => typeof v !== "undefined")
|
|
427
442
|
.map(([k, v]) => `${k}: ${arb(v, [p, k].join(SEPARATOR), false)}`)
|
|
428
|
-
.join(
|
|
443
|
+
.join(",\n");
|
|
429
444
|
if (!root) {
|
|
430
445
|
return `{${returnedObjectString}}`;
|
|
431
446
|
}
|
|
@@ -439,5 +454,8 @@ export const resolverFor = (type, field, fn) => fn;
|
|
|
439
454
|
export const START_VAR_NAME = `$ZEUS_VAR`;
|
|
440
455
|
export const GRAPHQL_TYPE_SEPARATOR = `__$GRAPHQL__`;
|
|
441
456
|
export const $ = (name, graphqlType) => {
|
|
442
|
-
return (START_VAR_NAME +
|
|
457
|
+
return (START_VAR_NAME +
|
|
458
|
+
name +
|
|
459
|
+
GRAPHQL_TYPE_SEPARATOR +
|
|
460
|
+
graphqlType);
|
|
443
461
|
};
|
|
@@ -6,7 +6,7 @@ import { REVIEWS_ROUTES } from "../index.js";
|
|
|
6
6
|
import { Check, ReplaceAllIcon, ReplaceIcon } from "lucide-react";
|
|
7
7
|
import { UniversalSelectDialog } from "./UniversalSelectDialog";
|
|
8
8
|
export const ReviewCustomer = () => {
|
|
9
|
-
const { t } = useTranslation(TRANSLATION_NAMESPACE);
|
|
9
|
+
const { t, i18n } = useTranslation(TRANSLATION_NAMESPACE);
|
|
10
10
|
const [fetch] = useLazyQuery(ListReviewQuery);
|
|
11
11
|
const [changeReviewState] = useMutation(ChangeReviewStateMutation);
|
|
12
12
|
const [changeReviewsState] = useMutation(ChangeReviewsStateMutation);
|
|
@@ -136,7 +136,9 @@ export const ReviewCustomer = () => {
|
|
|
136
136
|
const responseCreatedAt = row.original.responseCreatedAt;
|
|
137
137
|
return (React.createElement("div", null, responseCreatedAt
|
|
138
138
|
? t("list.responseCreatedAtValue", {
|
|
139
|
-
date: formatDate(responseCreatedAt
|
|
139
|
+
date: formatDate(responseCreatedAt, {
|
|
140
|
+
locale: i18n.resolvedLanguage ?? i18n.language,
|
|
141
|
+
}),
|
|
140
142
|
})
|
|
141
143
|
: t("list.noResponse")));
|
|
142
144
|
},
|
|
@@ -23,8 +23,18 @@ const getStatusColor = (status) => {
|
|
|
23
23
|
return "bg-gray-100 text-gray-800 border-gray-200";
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
|
+
export const getReviewStateLabel = (state, translate) => {
|
|
27
|
+
switch (state) {
|
|
28
|
+
case "PENDING" /* ReviewState.PENDING */:
|
|
29
|
+
return translate("state.pending");
|
|
30
|
+
case "ACCEPTED" /* ReviewState.ACCEPTED */:
|
|
31
|
+
return translate("state.accepted");
|
|
32
|
+
case "DECLINED" /* ReviewState.DECLINED */:
|
|
33
|
+
return translate("state.declined");
|
|
34
|
+
}
|
|
35
|
+
};
|
|
26
36
|
export const ReviewOrder = () => {
|
|
27
|
-
const { t } = useTranslation(TRANSLATION_NAMESPACE);
|
|
37
|
+
const { t, i18n } = useTranslation(TRANSLATION_NAMESPACE);
|
|
28
38
|
const { order } = useOrder();
|
|
29
39
|
const [getReviewForOrder, { data }] = useLazyQuery(GetReviewForOrderQuery);
|
|
30
40
|
useEffect(() => {
|
|
@@ -41,7 +51,7 @@ export const ReviewOrder = () => {
|
|
|
41
51
|
React.createElement(CardTitle, { className: "flex items-center gap-2" },
|
|
42
52
|
React.createElement(MessageSquare, { className: "h-5 w-5 text-orange-500" }),
|
|
43
53
|
t("reviewOrder.titleWithId", { orderId: order.id }))),
|
|
44
|
-
React.createElement(Badge, { className: getStatusColor(data.getReviewForOrder.state) }, data.getReviewForOrder.state))),
|
|
54
|
+
React.createElement(Badge, { className: getStatusColor(data.getReviewForOrder.state) }, getReviewStateLabel(data.getReviewForOrder.state, t)))),
|
|
45
55
|
React.createElement(CardContent, { className: "space-y-4 p-0" },
|
|
46
56
|
React.createElement("div", { className: "space-y-4" },
|
|
47
57
|
React.createElement("div", { className: "flex items-center justify-between" },
|
|
@@ -50,5 +60,7 @@ export const ReviewOrder = () => {
|
|
|
50
60
|
React.createElement("p", { className: "text-sm leading-relaxed text-foreground" }, data.getReviewForOrder.body)),
|
|
51
61
|
React.createElement("div", { className: "flex items-center gap-4 pt-2 border-t text-xs text-muted-foreground" }, data.getReviewForOrder.createdAt && (React.createElement("div", { className: "flex items-center gap-1" },
|
|
52
62
|
React.createElement(Calendar, { className: "h-3 w-3" }),
|
|
53
|
-
formatDate(data.getReviewForOrder.createdAt
|
|
63
|
+
formatDate(data.getReviewForOrder.createdAt, {
|
|
64
|
+
locale: i18n.resolvedLanguage ?? i18n.language,
|
|
65
|
+
}))))))));
|
|
54
66
|
};
|
package/dist/plugin-ui/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { createDeenruvUIPlugin, DEENRUV_UI_VERSION } from "@deenruv/react-ui-devkit";
|
|
2
|
+
import { createDeenruvUIPlugin, DEENRUV_UI_VERSION, } from "@deenruv/react-ui-devkit";
|
|
3
3
|
import { Reviews } from "./pages/Reviews";
|
|
4
4
|
import { ListIcon } from "lucide-react";
|
|
5
5
|
import { Review } from "./pages/Review";
|
|
@@ -46,6 +46,7 @@ export const ReviewsUIPlugin = createDeenruvUIPlugin({
|
|
|
46
46
|
id: "customers-detail-view",
|
|
47
47
|
name: "reviews",
|
|
48
48
|
label: "Reviews",
|
|
49
|
+
labelId: "nav.reviews",
|
|
49
50
|
component: React.createElement(ReviewCustomer, null),
|
|
50
51
|
hideSidebar: true,
|
|
51
52
|
},
|
|
@@ -9,7 +9,7 @@ import { TRANSLATION_NAMESPACE } from "../constants";
|
|
|
9
9
|
import { toast } from "sonner";
|
|
10
10
|
import { ReviewStateChange } from "../components/ReviewStateChange";
|
|
11
11
|
export const Review = () => {
|
|
12
|
-
const { t } = useTranslation(TRANSLATION_NAMESPACE);
|
|
12
|
+
const { t, i18n } = useTranslation(TRANSLATION_NAMESPACE);
|
|
13
13
|
const { id } = useParams();
|
|
14
14
|
const { data: config } = useQuery(GetReviewsConfigQuery);
|
|
15
15
|
const [get] = useLazyQuery(GetReviewQuery);
|
|
@@ -178,6 +178,7 @@ export const Review = () => {
|
|
|
178
178
|
React.createElement("div", { className: "flex items-center gap-2 text-sm text-gray-600" },
|
|
179
179
|
React.createElement(Calendar, { className: "w-4 h-4" }),
|
|
180
180
|
formatDate(review.createdAt, {
|
|
181
|
+
locale: i18n.language,
|
|
181
182
|
dateStyle: "medium",
|
|
182
183
|
timeStyle: "short",
|
|
183
184
|
})),
|
|
@@ -198,6 +199,7 @@ export const Review = () => {
|
|
|
198
199
|
React.createElement("div", { className: "flex items-center gap-2 mb-2" },
|
|
199
200
|
React.createElement(Label, { className: "text-base font-semibold text-secondary" }, t("detail.businessResponse")),
|
|
200
201
|
React.createElement(Badge, { variant: "outline", className: "text-xs text-secondary" }, formatDate(review.responseCreatedAt, {
|
|
202
|
+
locale: i18n.language,
|
|
201
203
|
dateStyle: "medium",
|
|
202
204
|
timeStyle: "short",
|
|
203
205
|
}))),
|
|
@@ -209,6 +211,7 @@ export const Review = () => {
|
|
|
209
211
|
":"),
|
|
210
212
|
" ",
|
|
211
213
|
formatDate(review.createdAt, {
|
|
214
|
+
locale: i18n.language,
|
|
212
215
|
dateStyle: "medium",
|
|
213
216
|
timeStyle: "short",
|
|
214
217
|
})),
|
|
@@ -218,6 +221,7 @@ export const Review = () => {
|
|
|
218
221
|
":"),
|
|
219
222
|
" ",
|
|
220
223
|
formatDate(review.updatedAt, {
|
|
224
|
+
locale: i18n.language,
|
|
221
225
|
dateStyle: "medium",
|
|
222
226
|
timeStyle: "short",
|
|
223
227
|
}))))) : (React.createElement("div", { className: "text-center py-8" },
|
|
@@ -7,7 +7,7 @@ import { Check, ReplaceIcon, ReplaceAllIcon } from "lucide-react";
|
|
|
7
7
|
import { UniversalSelectDialog } from "../components/UniversalSelectDialog.js";
|
|
8
8
|
import { ChangeReviewsStateMutation, ChangeReviewStateMutation, } from "../graphql/mutations.js";
|
|
9
9
|
export const Reviews = () => {
|
|
10
|
-
const { t } = useTranslation(TRANSLATION_NAMESPACE);
|
|
10
|
+
const { t, i18n } = useTranslation(TRANSLATION_NAMESPACE);
|
|
11
11
|
const [fetch] = useLazyQuery(ListReviewQuery);
|
|
12
12
|
const [changeReviewState] = useMutation(ChangeReviewStateMutation);
|
|
13
13
|
const [changeReviewsState] = useMutation(ChangeReviewsStateMutation);
|
|
@@ -142,6 +142,7 @@ export const Reviews = () => {
|
|
|
142
142
|
return (React.createElement("div", null, responseCreatedAt
|
|
143
143
|
? t("list.responseCreatedAtValue", {
|
|
144
144
|
date: formatDate(responseCreatedAt, {
|
|
145
|
+
locale: i18n.resolvedLanguage ?? i18n.language,
|
|
145
146
|
dateStyle: "medium",
|
|
146
147
|
timeStyle: "short",
|
|
147
148
|
}),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import en from "./locales/en/reviews.json";
|
|
3
|
+
import pl from "./locales/pl/reviews.json";
|
|
4
|
+
import { getReviewStateLabel } from "./components/ReviewOrder";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import { fileURLToPath, URL } from "node:url";
|
|
7
|
+
const leafKeys = (value, prefix = "") => Object.entries(value).flatMap(([key, child]) => {
|
|
8
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
9
|
+
return child && typeof child === "object"
|
|
10
|
+
? leafKeys(child, path)
|
|
11
|
+
: [path];
|
|
12
|
+
});
|
|
13
|
+
describe("Reviews admin translations", () => {
|
|
14
|
+
it("keeps English and Polish locale keys in parity", () => {
|
|
15
|
+
expect(leafKeys(en).sort()).toEqual(leafKeys(pl).sort());
|
|
16
|
+
});
|
|
17
|
+
it("localizes every backend review state without changing enum values", () => {
|
|
18
|
+
const translate = (key) => `translated:${key}`;
|
|
19
|
+
expect(getReviewStateLabel("PENDING" /* ReviewState.PENDING */, translate)).toBe("translated:state.pending");
|
|
20
|
+
expect(getReviewStateLabel("ACCEPTED" /* ReviewState.ACCEPTED */, translate)).toBe("translated:state.accepted");
|
|
21
|
+
expect(getReviewStateLabel("DECLINED" /* ReviewState.DECLINED */, translate)).toBe("translated:state.declined");
|
|
22
|
+
});
|
|
23
|
+
it("declares an SSR-safe customer tab translation key", async () => {
|
|
24
|
+
const { ReviewsUIPlugin } = await import("./index");
|
|
25
|
+
expect(ReviewsUIPlugin.tabs?.[0]).toMatchObject({
|
|
26
|
+
name: "reviews",
|
|
27
|
+
label: "Reviews",
|
|
28
|
+
labelId: "nav.reviews",
|
|
29
|
+
});
|
|
30
|
+
expect(globalThis.window).toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
it("formats every visible review date in the active UI language", () => {
|
|
33
|
+
const sources = [
|
|
34
|
+
"./pages/Review.tsx",
|
|
35
|
+
"./pages/Reviews.tsx",
|
|
36
|
+
"./components/ReviewCustomer.tsx",
|
|
37
|
+
"./components/ReviewOrder.tsx",
|
|
38
|
+
].map((path) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), "utf8"));
|
|
39
|
+
expect(sources.reduce((count, source) => count + (source.match(/formatDate\(/g)?.length ?? 0), 0)).toBe(7);
|
|
40
|
+
for (const source of sources) {
|
|
41
|
+
expect(source.match(/locale: i18n\.(?:resolvedLanguage|language)/g)).toHaveLength(source.match(/formatDate\(/g)?.length ?? 0);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|