strapi-relation-names 1.1.0 → 1.2.1
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/README.md +1 -0
- package/dist/admin/{SettingsPage-CaBXOirN.js → SettingsPage-BebR4ghK.js} +86 -16
- package/dist/admin/{SettingsPage-CpTyZSvB.mjs → SettingsPage-DFZP5CZs.mjs} +86 -18
- package/dist/admin/{de-a3KtzZ7N.mjs → de-Bc81LkbY.mjs} +1 -1
- package/dist/admin/{de-BBrO1tf0.js → de-CsBvOsWR.js} +1 -1
- package/dist/admin/{en-8w3y1FSw.mjs → en-Bk-HIXNd.mjs} +1 -1
- package/dist/admin/{en-DlY6ZGdo.js → en-DT4g6X2H.js} +1 -1
- package/dist/admin/{index-DGXo1dxk.mjs → index-CiS6cuI9.mjs} +2 -2
- package/dist/admin/{index-CKaZcnCM.js → index-DfSAe961.js} +2 -2
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/utils/template.d.ts +2 -0
- package/dist/server/index.js +32 -6
- package/dist/server/index.mjs +32 -6
- package/dist/server/src/services/relation-labels.d.ts +4 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -171,6 +171,7 @@ The default label is also used when:
|
|
|
171
171
|
- [ ] Live label previews while editing templates
|
|
172
172
|
- [ ] Define default relation templates in plugin configuration
|
|
173
173
|
- [x] Support nested field paths in templates
|
|
174
|
+
- [x] Support nested relation fields in templates
|
|
174
175
|
- [ ] Import and export relation-label settings
|
|
175
176
|
- [ ] Conditional labels and configurable fallback rules
|
|
176
177
|
- [ ] Support label transformation functions (e.g., `toUpperCase`, `toLowerCase`, `capitalize`, etc.)
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const designSystem = require("@strapi/design-system");
|
|
5
|
+
const styled = require("styled-components");
|
|
5
6
|
const react = require("react");
|
|
6
7
|
const reactIntl = require("react-intl");
|
|
7
8
|
const admin = require("@strapi/strapi/admin");
|
|
8
|
-
const index = require("./index-
|
|
9
|
+
const index = require("./index-DfSAe961.js");
|
|
10
|
+
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
11
|
+
const styled__default = /* @__PURE__ */ _interopDefault(styled);
|
|
9
12
|
const FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
10
13
|
"string",
|
|
11
14
|
"text",
|
|
@@ -31,6 +34,15 @@ const SYSTEM_SCALAR_FIELDS = [
|
|
|
31
34
|
"status"
|
|
32
35
|
];
|
|
33
36
|
const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
37
|
+
const getNestedSchemaUid = (attribute) => {
|
|
38
|
+
if (attribute.type === "component") {
|
|
39
|
+
return attribute.component;
|
|
40
|
+
}
|
|
41
|
+
if (attribute.type === "relation") {
|
|
42
|
+
return attribute.targetModel ?? attribute.target;
|
|
43
|
+
}
|
|
44
|
+
return void 0;
|
|
45
|
+
};
|
|
34
46
|
const getPlaceholders = (template) => {
|
|
35
47
|
if (!template.trim()) {
|
|
36
48
|
return null;
|
|
@@ -74,10 +86,11 @@ const validateTemplate = (template, attributes, schemas) => {
|
|
|
74
86
|
if (isLastSegment) {
|
|
75
87
|
return !FIELD_TYPES.has(attribute.type ?? "");
|
|
76
88
|
}
|
|
77
|
-
|
|
89
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
90
|
+
if (!nestedSchemaUid) {
|
|
78
91
|
return true;
|
|
79
92
|
}
|
|
80
|
-
currentAttributes = schemas?.get(
|
|
93
|
+
currentAttributes = schemas?.get(nestedSchemaUid)?.attributes;
|
|
81
94
|
}
|
|
82
95
|
return true;
|
|
83
96
|
});
|
|
@@ -95,20 +108,36 @@ const getAvailableFields = (schema, schemas, prefix = "", ancestors = /* @__PURE
|
|
|
95
108
|
if (FIELD_TYPES.has(attribute.type ?? "")) {
|
|
96
109
|
return [path];
|
|
97
110
|
}
|
|
98
|
-
|
|
111
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
112
|
+
if (!nestedSchemaUid || ancestors.has(nestedSchemaUid)) {
|
|
99
113
|
return [];
|
|
100
114
|
}
|
|
101
115
|
return getAvailableFields(
|
|
102
|
-
schemas.get(
|
|
116
|
+
schemas.get(nestedSchemaUid),
|
|
103
117
|
schemas,
|
|
104
118
|
`${path}.`,
|
|
105
|
-
/* @__PURE__ */ new Set([...ancestors,
|
|
119
|
+
/* @__PURE__ */ new Set([...ancestors, nestedSchemaUid])
|
|
106
120
|
);
|
|
107
121
|
});
|
|
108
122
|
const systemFields = prefix === "" ? SYSTEM_SCALAR_FIELDS : [];
|
|
109
123
|
return [...systemFields, ...fields.filter((field) => !systemFields.includes(field))];
|
|
110
124
|
};
|
|
111
125
|
const PLUGIN_SETTINGS_PATH = "/strapi-relation-names/settings";
|
|
126
|
+
const AvailableField = styled__default.default(designSystem.Typography)`
|
|
127
|
+
display: inline-block;
|
|
128
|
+
padding: 1px 4px;
|
|
129
|
+
border: 1px solid transparent;
|
|
130
|
+
border-radius: 4px;
|
|
131
|
+
background: transparent;
|
|
132
|
+
color: inherit;
|
|
133
|
+
cursor: pointer;
|
|
134
|
+
font: inherit;
|
|
135
|
+
|
|
136
|
+
&:hover,
|
|
137
|
+
&[aria-pressed='true'] {
|
|
138
|
+
border-color: currentColor;
|
|
139
|
+
}
|
|
140
|
+
`;
|
|
112
141
|
const getRelationTarget = (attribute) => attribute.targetModel ?? attribute.target;
|
|
113
142
|
const SettingsPage = () => {
|
|
114
143
|
const { formatMessage } = reactIntl.useIntl();
|
|
@@ -190,7 +219,24 @@ const SettingsPage = () => {
|
|
|
190
219
|
};
|
|
191
220
|
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { "aria-labelledby": "relation-names-title", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 8, children: [
|
|
192
221
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", tag: "h1", id: "relation-names-title", children: formatMessage({ id: index.getTranslation("settings.title") }) }),
|
|
193
|
-
/* @__PURE__ */ jsxRuntime.
|
|
222
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
223
|
+
designSystem.Flex,
|
|
224
|
+
{
|
|
225
|
+
gap: 2,
|
|
226
|
+
width: "100%",
|
|
227
|
+
paddingBottom: 6,
|
|
228
|
+
style: {
|
|
229
|
+
"justify-content": "space-between",
|
|
230
|
+
position: "sticky",
|
|
231
|
+
top: ".5rem",
|
|
232
|
+
zIndex: 1
|
|
233
|
+
},
|
|
234
|
+
children: [
|
|
235
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: formatMessage({ id: index.getTranslation("settings.description") }) }),
|
|
236
|
+
!isLoading && rows.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { loading: isSaving, disabled: isSaving, onClick: () => void save(), children: formatMessage({ id: index.getTranslation("settings.save") }) }) : null
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
),
|
|
194
240
|
isLoading ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({ id: index.getTranslation("settings.loading") }) }) : null,
|
|
195
241
|
error ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", tag: "p", children: error }) : null,
|
|
196
242
|
!isLoading && rows.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({ id: index.getTranslation("settings.noRelations") }) }) : null,
|
|
@@ -198,6 +244,12 @@ const SettingsPage = () => {
|
|
|
198
244
|
const targetAttributes = target?.attributes ?? {};
|
|
199
245
|
const template = settings.relations[source.uid]?.[fieldName] ?? "";
|
|
200
246
|
const validationError = template ? validateTemplate(template, targetAttributes, schemaMap) : null;
|
|
247
|
+
const availableFields = getAvailableFields(target, schemaMap);
|
|
248
|
+
const toggleField = (field) => {
|
|
249
|
+
const placeholder = `{${field}}`;
|
|
250
|
+
const nextTemplate = template.includes(placeholder) ? template.replaceAll(placeholder, "").replace(/\s{2,}/g, " ").trim() : `${template.trim()}${template.trim() ? " " : ""}${placeholder}`;
|
|
251
|
+
updateTemplate(source.uid, fieldName, nextTemplate);
|
|
252
|
+
};
|
|
201
253
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
202
254
|
designSystem.Box,
|
|
203
255
|
{
|
|
@@ -222,7 +274,9 @@ const SettingsPage = () => {
|
|
|
222
274
|
error: validationError ?? void 0,
|
|
223
275
|
name: `${source.uid}.${fieldName}`,
|
|
224
276
|
children: [
|
|
225
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
|
|
277
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
|
|
278
|
+
id: index.getTranslation("settings.template")
|
|
279
|
+
}) }),
|
|
226
280
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
227
281
|
designSystem.TextInput,
|
|
228
282
|
{
|
|
@@ -236,18 +290,34 @@ const SettingsPage = () => {
|
|
|
236
290
|
]
|
|
237
291
|
}
|
|
238
292
|
),
|
|
239
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
293
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Root, { collapsible: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: "available-fields", children: [
|
|
294
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { children: formatMessage({
|
|
295
|
+
id: index.getTranslation("settings.availableFields")
|
|
296
|
+
}) }) }),
|
|
297
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: availableFields.map((field, index2) => {
|
|
298
|
+
const placeholder = `{${field}}`;
|
|
299
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
300
|
+
index2 > 0 ? ", " : null,
|
|
301
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
302
|
+
AvailableField,
|
|
303
|
+
{
|
|
304
|
+
as: "button",
|
|
305
|
+
type: "button",
|
|
306
|
+
variant: "pi",
|
|
307
|
+
textColor: "neutral600",
|
|
308
|
+
"aria-pressed": template.includes(placeholder),
|
|
309
|
+
onClick: () => toggleField(field),
|
|
310
|
+
children: field
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
] }, field);
|
|
314
|
+
}) }) })
|
|
315
|
+
] }) }) })
|
|
245
316
|
]
|
|
246
317
|
},
|
|
247
318
|
`${source.uid}.${fieldName}`
|
|
248
319
|
);
|
|
249
|
-
}) : null
|
|
250
|
-
!isLoading && rows.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", paddingTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { loading: isSaving, disabled: isSaving, onClick: () => void save(), children: formatMessage({ id: index.getTranslation("settings.save") }) }) }) : null
|
|
320
|
+
}) : null
|
|
251
321
|
] }) });
|
|
252
322
|
};
|
|
253
323
|
exports.SettingsPage = SettingsPage;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Main, Box, Typography, Field, TextInput,
|
|
3
|
-
import
|
|
2
|
+
import { Main, Box, Typography, Flex, Button, Field, TextInput, Accordion } from "@strapi/design-system";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { useState, useCallback, useEffect, useMemo, Fragment } from "react";
|
|
4
5
|
import { useIntl } from "react-intl";
|
|
5
6
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
6
|
-
import { g as getTranslation } from "./index-
|
|
7
|
+
import { g as getTranslation } from "./index-CiS6cuI9.mjs";
|
|
7
8
|
const FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
8
9
|
"string",
|
|
9
10
|
"text",
|
|
@@ -29,6 +30,15 @@ const SYSTEM_SCALAR_FIELDS = [
|
|
|
29
30
|
"status"
|
|
30
31
|
];
|
|
31
32
|
const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
33
|
+
const getNestedSchemaUid = (attribute) => {
|
|
34
|
+
if (attribute.type === "component") {
|
|
35
|
+
return attribute.component;
|
|
36
|
+
}
|
|
37
|
+
if (attribute.type === "relation") {
|
|
38
|
+
return attribute.targetModel ?? attribute.target;
|
|
39
|
+
}
|
|
40
|
+
return void 0;
|
|
41
|
+
};
|
|
32
42
|
const getPlaceholders = (template) => {
|
|
33
43
|
if (!template.trim()) {
|
|
34
44
|
return null;
|
|
@@ -72,10 +82,11 @@ const validateTemplate = (template, attributes, schemas) => {
|
|
|
72
82
|
if (isLastSegment) {
|
|
73
83
|
return !FIELD_TYPES.has(attribute.type ?? "");
|
|
74
84
|
}
|
|
75
|
-
|
|
85
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
86
|
+
if (!nestedSchemaUid) {
|
|
76
87
|
return true;
|
|
77
88
|
}
|
|
78
|
-
currentAttributes = schemas?.get(
|
|
89
|
+
currentAttributes = schemas?.get(nestedSchemaUid)?.attributes;
|
|
79
90
|
}
|
|
80
91
|
return true;
|
|
81
92
|
});
|
|
@@ -93,20 +104,36 @@ const getAvailableFields = (schema, schemas, prefix = "", ancestors = /* @__PURE
|
|
|
93
104
|
if (FIELD_TYPES.has(attribute.type ?? "")) {
|
|
94
105
|
return [path];
|
|
95
106
|
}
|
|
96
|
-
|
|
107
|
+
const nestedSchemaUid = getNestedSchemaUid(attribute);
|
|
108
|
+
if (!nestedSchemaUid || ancestors.has(nestedSchemaUid)) {
|
|
97
109
|
return [];
|
|
98
110
|
}
|
|
99
111
|
return getAvailableFields(
|
|
100
|
-
schemas.get(
|
|
112
|
+
schemas.get(nestedSchemaUid),
|
|
101
113
|
schemas,
|
|
102
114
|
`${path}.`,
|
|
103
|
-
/* @__PURE__ */ new Set([...ancestors,
|
|
115
|
+
/* @__PURE__ */ new Set([...ancestors, nestedSchemaUid])
|
|
104
116
|
);
|
|
105
117
|
});
|
|
106
118
|
const systemFields = prefix === "" ? SYSTEM_SCALAR_FIELDS : [];
|
|
107
119
|
return [...systemFields, ...fields.filter((field) => !systemFields.includes(field))];
|
|
108
120
|
};
|
|
109
121
|
const PLUGIN_SETTINGS_PATH = "/strapi-relation-names/settings";
|
|
122
|
+
const AvailableField = styled(Typography)`
|
|
123
|
+
display: inline-block;
|
|
124
|
+
padding: 1px 4px;
|
|
125
|
+
border: 1px solid transparent;
|
|
126
|
+
border-radius: 4px;
|
|
127
|
+
background: transparent;
|
|
128
|
+
color: inherit;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
font: inherit;
|
|
131
|
+
|
|
132
|
+
&:hover,
|
|
133
|
+
&[aria-pressed='true'] {
|
|
134
|
+
border-color: currentColor;
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
110
137
|
const getRelationTarget = (attribute) => attribute.targetModel ?? attribute.target;
|
|
111
138
|
const SettingsPage = () => {
|
|
112
139
|
const { formatMessage } = useIntl();
|
|
@@ -188,7 +215,24 @@ const SettingsPage = () => {
|
|
|
188
215
|
};
|
|
189
216
|
return /* @__PURE__ */ jsx(Main, { "aria-labelledby": "relation-names-title", children: /* @__PURE__ */ jsxs(Box, { padding: 8, children: [
|
|
190
217
|
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", id: "relation-names-title", children: formatMessage({ id: getTranslation("settings.title") }) }),
|
|
191
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ jsxs(
|
|
219
|
+
Flex,
|
|
220
|
+
{
|
|
221
|
+
gap: 2,
|
|
222
|
+
width: "100%",
|
|
223
|
+
paddingBottom: 6,
|
|
224
|
+
style: {
|
|
225
|
+
"justify-content": "space-between",
|
|
226
|
+
position: "sticky",
|
|
227
|
+
top: ".5rem",
|
|
228
|
+
zIndex: 1
|
|
229
|
+
},
|
|
230
|
+
children: [
|
|
231
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: formatMessage({ id: getTranslation("settings.description") }) }),
|
|
232
|
+
!isLoading && rows.length > 0 ? /* @__PURE__ */ jsx(Button, { loading: isSaving, disabled: isSaving, onClick: () => void save(), children: formatMessage({ id: getTranslation("settings.save") }) }) : null
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
),
|
|
192
236
|
isLoading ? /* @__PURE__ */ jsx(Typography, { children: formatMessage({ id: getTranslation("settings.loading") }) }) : null,
|
|
193
237
|
error ? /* @__PURE__ */ jsx(Typography, { textColor: "danger600", tag: "p", children: error }) : null,
|
|
194
238
|
!isLoading && rows.length === 0 ? /* @__PURE__ */ jsx(Typography, { children: formatMessage({ id: getTranslation("settings.noRelations") }) }) : null,
|
|
@@ -196,6 +240,12 @@ const SettingsPage = () => {
|
|
|
196
240
|
const targetAttributes = target?.attributes ?? {};
|
|
197
241
|
const template = settings.relations[source.uid]?.[fieldName] ?? "";
|
|
198
242
|
const validationError = template ? validateTemplate(template, targetAttributes, schemaMap) : null;
|
|
243
|
+
const availableFields = getAvailableFields(target, schemaMap);
|
|
244
|
+
const toggleField = (field) => {
|
|
245
|
+
const placeholder = `{${field}}`;
|
|
246
|
+
const nextTemplate = template.includes(placeholder) ? template.replaceAll(placeholder, "").replace(/\s{2,}/g, " ").trim() : `${template.trim()}${template.trim() ? " " : ""}${placeholder}`;
|
|
247
|
+
updateTemplate(source.uid, fieldName, nextTemplate);
|
|
248
|
+
};
|
|
199
249
|
return /* @__PURE__ */ jsxs(
|
|
200
250
|
Box,
|
|
201
251
|
{
|
|
@@ -220,7 +270,9 @@ const SettingsPage = () => {
|
|
|
220
270
|
error: validationError ?? void 0,
|
|
221
271
|
name: `${source.uid}.${fieldName}`,
|
|
222
272
|
children: [
|
|
223
|
-
/* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
|
|
273
|
+
/* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
|
|
274
|
+
id: getTranslation("settings.template")
|
|
275
|
+
}) }),
|
|
224
276
|
/* @__PURE__ */ jsx(
|
|
225
277
|
TextInput,
|
|
226
278
|
{
|
|
@@ -234,18 +286,34 @@ const SettingsPage = () => {
|
|
|
234
286
|
]
|
|
235
287
|
}
|
|
236
288
|
),
|
|
237
|
-
/* @__PURE__ */ jsx(Box, { paddingTop: 2, children: /* @__PURE__ */
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
289
|
+
/* @__PURE__ */ jsx(Box, { paddingTop: 2, children: /* @__PURE__ */ jsx(Accordion.Root, { collapsible: true, children: /* @__PURE__ */ jsxs(Accordion.Item, { value: "available-fields", children: [
|
|
290
|
+
/* @__PURE__ */ jsx(Accordion.Header, { children: /* @__PURE__ */ jsx(Accordion.Trigger, { children: formatMessage({
|
|
291
|
+
id: getTranslation("settings.availableFields")
|
|
292
|
+
}) }) }),
|
|
293
|
+
/* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: availableFields.map((field, index) => {
|
|
294
|
+
const placeholder = `{${field}}`;
|
|
295
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
296
|
+
index > 0 ? ", " : null,
|
|
297
|
+
/* @__PURE__ */ jsx(
|
|
298
|
+
AvailableField,
|
|
299
|
+
{
|
|
300
|
+
as: "button",
|
|
301
|
+
type: "button",
|
|
302
|
+
variant: "pi",
|
|
303
|
+
textColor: "neutral600",
|
|
304
|
+
"aria-pressed": template.includes(placeholder),
|
|
305
|
+
onClick: () => toggleField(field),
|
|
306
|
+
children: field
|
|
307
|
+
}
|
|
308
|
+
)
|
|
309
|
+
] }, field);
|
|
310
|
+
}) }) })
|
|
311
|
+
] }) }) })
|
|
243
312
|
]
|
|
244
313
|
},
|
|
245
314
|
`${source.uid}.${fieldName}`
|
|
246
315
|
);
|
|
247
|
-
}) : null
|
|
248
|
-
!isLoading && rows.length > 0 ? /* @__PURE__ */ jsx(Flex, { justifyContent: "flex-end", paddingTop: 4, children: /* @__PURE__ */ jsx(Button, { loading: isSaving, disabled: isSaving, onClick: () => void save(), children: formatMessage({ id: getTranslation("settings.save") }) }) }) : null
|
|
316
|
+
}) : null
|
|
249
317
|
] }) });
|
|
250
318
|
};
|
|
251
319
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const de = {
|
|
2
2
|
"plugin.name": "Relationsnamen",
|
|
3
3
|
"settings.title": "Relationsnamen",
|
|
4
|
-
"settings.description": "Legen Sie fest, wie verknüpfte Einträge
|
|
4
|
+
"settings.description": "Legen Sie fest, wie verknüpfte Einträge beschriftet werden, z. B. mit Vor- und Nachname.",
|
|
5
5
|
"settings.target": "Verknüpfter Inhalt: {target}",
|
|
6
6
|
"settings.template": "Bezeichnungsvorlage",
|
|
7
7
|
"settings.availableFields": "Verfügbare Felder",
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const de = {
|
|
4
4
|
"plugin.name": "Relationsnamen",
|
|
5
5
|
"settings.title": "Relationsnamen",
|
|
6
|
-
"settings.description": "Legen Sie fest, wie verknüpfte Einträge
|
|
6
|
+
"settings.description": "Legen Sie fest, wie verknüpfte Einträge beschriftet werden, z. B. mit Vor- und Nachname.",
|
|
7
7
|
"settings.target": "Verknüpfter Inhalt: {target}",
|
|
8
8
|
"settings.template": "Bezeichnungsvorlage",
|
|
9
9
|
"settings.availableFields": "Verfügbare Felder",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const en = {
|
|
2
2
|
"plugin.name": "Relation Names",
|
|
3
3
|
"settings.title": "Relation Names",
|
|
4
|
-
"settings.description": "Choose how related entries are
|
|
4
|
+
"settings.description": "Choose how related entries are labeled, using fields such as first and last name.",
|
|
5
5
|
"settings.target": "Related content: {target}",
|
|
6
6
|
"settings.template": "Label template",
|
|
7
7
|
"settings.availableFields": "Available fields",
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const en = {
|
|
4
4
|
"plugin.name": "Relation Names",
|
|
5
5
|
"settings.title": "Relation Names",
|
|
6
|
-
"settings.description": "Choose how related entries are
|
|
6
|
+
"settings.description": "Choose how related entries are labeled, using fields such as first and last name.",
|
|
7
7
|
"settings.target": "Related content: {target}",
|
|
8
8
|
"settings.template": "Label template",
|
|
9
9
|
"settings.availableFields": "Available fields",
|
|
@@ -88,7 +88,7 @@ const plugin = {
|
|
|
88
88
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
89
89
|
defaultMessage: "Relation Names"
|
|
90
90
|
},
|
|
91
|
-
Component: () => import("./SettingsPage-
|
|
91
|
+
Component: () => import("./SettingsPage-DFZP5CZs.mjs").then((module) => ({ default: module.SettingsPage })),
|
|
92
92
|
permissions: []
|
|
93
93
|
});
|
|
94
94
|
app.registerPlugin({
|
|
@@ -105,7 +105,7 @@ const plugin = {
|
|
|
105
105
|
return Promise.all(
|
|
106
106
|
locales.map(async (locale) => {
|
|
107
107
|
try {
|
|
108
|
-
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-
|
|
108
|
+
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => import("./de-Bc81LkbY.mjs"), "./translations/en.json": () => import("./en-Bk-HIXNd.mjs") }), `./translations/${locale}.json`, 3);
|
|
109
109
|
const newData = {};
|
|
110
110
|
const keys = Object.keys(data);
|
|
111
111
|
for (const key of keys) {
|
|
@@ -89,7 +89,7 @@ const plugin = {
|
|
|
89
89
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
90
90
|
defaultMessage: "Relation Names"
|
|
91
91
|
},
|
|
92
|
-
Component: () => Promise.resolve().then(() => require("./SettingsPage-
|
|
92
|
+
Component: () => Promise.resolve().then(() => require("./SettingsPage-BebR4ghK.js")).then((module2) => ({ default: module2.SettingsPage })),
|
|
93
93
|
permissions: []
|
|
94
94
|
});
|
|
95
95
|
app.registerPlugin({
|
|
@@ -106,7 +106,7 @@ const plugin = {
|
|
|
106
106
|
return Promise.all(
|
|
107
107
|
locales.map(async (locale) => {
|
|
108
108
|
try {
|
|
109
|
-
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => Promise.resolve().then(() => require("./de-
|
|
109
|
+
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/de.json": () => Promise.resolve().then(() => require("./de-CsBvOsWR.js")), "./translations/en.json": () => Promise.resolve().then(() => require("./en-DT4g6X2H.js")) }), `./translations/${locale}.json`, 3);
|
|
110
110
|
const newData = {};
|
|
111
111
|
const keys = Object.keys(data);
|
|
112
112
|
for (const key of keys) {
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -164,6 +164,9 @@ const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)
|
|
|
164
164
|
const isRecord$1 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
165
165
|
const getPathValue = (value, path) => {
|
|
166
166
|
return path.split(".").reduce((current, segment) => {
|
|
167
|
+
if (Array.isArray(current)) {
|
|
168
|
+
return current.map((item) => isRecord$1(item) ? item[segment] : void 0).filter((item) => item !== void 0);
|
|
169
|
+
}
|
|
167
170
|
return isRecord$1(current) ? current[segment] : void 0;
|
|
168
171
|
}, value);
|
|
169
172
|
};
|
|
@@ -215,10 +218,11 @@ const compileTemplate = (template, targetSchema, resolveSchema) => {
|
|
|
215
218
|
if (isLastSegment) {
|
|
216
219
|
return SCALAR_TYPES.has(attribute.type ?? "");
|
|
217
220
|
}
|
|
218
|
-
|
|
221
|
+
const nestedSchemaUid = attribute.type === "component" ? attribute.component : attribute.type === "relation" ? attribute.target : void 0;
|
|
222
|
+
if (!nestedSchemaUid || !resolveSchema) {
|
|
219
223
|
return false;
|
|
220
224
|
}
|
|
221
|
-
schema = resolveSchema(
|
|
225
|
+
schema = resolveSchema(nestedSchemaUid);
|
|
222
226
|
if (!schema) {
|
|
223
227
|
return false;
|
|
224
228
|
}
|
|
@@ -329,10 +333,32 @@ const getRuntime = async (strapi, settings2, sourceUid, targetField, userAbility
|
|
|
329
333
|
};
|
|
330
334
|
};
|
|
331
335
|
const buildPopulate = (placeholders) => {
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
+
const populate = {};
|
|
337
|
+
for (const placeholder of placeholders) {
|
|
338
|
+
const segments = placeholder.split(".");
|
|
339
|
+
if (segments.length < 2) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
let current = populate;
|
|
343
|
+
for (const [index2, segment] of segments.slice(0, -1).entries()) {
|
|
344
|
+
const existing = current[segment];
|
|
345
|
+
if (existing === true) {
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
if (index2 === segments.length - 2) {
|
|
349
|
+
current[segment] = existing ?? true;
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
if (!existing) {
|
|
353
|
+
current[segment] = { populate: {} };
|
|
354
|
+
}
|
|
355
|
+
const next = current[segment];
|
|
356
|
+
if (next !== true) {
|
|
357
|
+
current = next.populate;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return Object.keys(populate).length > 0 ? populate : void 0;
|
|
336
362
|
};
|
|
337
363
|
const hydrateValues = async (strapi, ctx, runtime, values) => {
|
|
338
364
|
const targetSchema = strapi.getModel(runtime.targetUid);
|
package/dist/server/index.mjs
CHANGED
|
@@ -162,6 +162,9 @@ const PLACEHOLDER_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)
|
|
|
162
162
|
const isRecord$1 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
163
163
|
const getPathValue = (value, path) => {
|
|
164
164
|
return path.split(".").reduce((current, segment) => {
|
|
165
|
+
if (Array.isArray(current)) {
|
|
166
|
+
return current.map((item) => isRecord$1(item) ? item[segment] : void 0).filter((item) => item !== void 0);
|
|
167
|
+
}
|
|
165
168
|
return isRecord$1(current) ? current[segment] : void 0;
|
|
166
169
|
}, value);
|
|
167
170
|
};
|
|
@@ -213,10 +216,11 @@ const compileTemplate = (template, targetSchema, resolveSchema) => {
|
|
|
213
216
|
if (isLastSegment) {
|
|
214
217
|
return SCALAR_TYPES.has(attribute.type ?? "");
|
|
215
218
|
}
|
|
216
|
-
|
|
219
|
+
const nestedSchemaUid = attribute.type === "component" ? attribute.component : attribute.type === "relation" ? attribute.target : void 0;
|
|
220
|
+
if (!nestedSchemaUid || !resolveSchema) {
|
|
217
221
|
return false;
|
|
218
222
|
}
|
|
219
|
-
schema = resolveSchema(
|
|
223
|
+
schema = resolveSchema(nestedSchemaUid);
|
|
220
224
|
if (!schema) {
|
|
221
225
|
return false;
|
|
222
226
|
}
|
|
@@ -327,10 +331,32 @@ const getRuntime = async (strapi, settings2, sourceUid, targetField, userAbility
|
|
|
327
331
|
};
|
|
328
332
|
};
|
|
329
333
|
const buildPopulate = (placeholders) => {
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
+
const populate = {};
|
|
335
|
+
for (const placeholder of placeholders) {
|
|
336
|
+
const segments = placeholder.split(".");
|
|
337
|
+
if (segments.length < 2) {
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
let current = populate;
|
|
341
|
+
for (const [index2, segment] of segments.slice(0, -1).entries()) {
|
|
342
|
+
const existing = current[segment];
|
|
343
|
+
if (existing === true) {
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
if (index2 === segments.length - 2) {
|
|
347
|
+
current[segment] = existing ?? true;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
if (!existing) {
|
|
351
|
+
current[segment] = { populate: {} };
|
|
352
|
+
}
|
|
353
|
+
const next = current[segment];
|
|
354
|
+
if (next !== true) {
|
|
355
|
+
current = next.populate;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return Object.keys(populate).length > 0 ? populate : void 0;
|
|
334
360
|
};
|
|
335
361
|
const hydrateValues = async (strapi, ctx, runtime, values) => {
|
|
336
362
|
const targetSchema = strapi.getModel(runtime.targetUid);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Core } from '@strapi/strapi';
|
|
2
2
|
import { SchemaLike } from './utils/relation-labels';
|
|
3
|
-
|
|
3
|
+
type Populate = Record<string, true | {
|
|
4
|
+
populate: Populate;
|
|
5
|
+
}>;
|
|
6
|
+
declare const buildPopulate: (placeholders: string[]) => Populate | undefined;
|
|
4
7
|
declare const relationLabels: ({ strapi }: {
|
|
5
8
|
strapi: Core.Strapi;
|
|
6
9
|
}) => {
|