nucleus-core-ts 0.9.886 → 0.9.887

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.
Files changed (34) hide show
  1. package/dist/.build-ok +1 -1
  2. package/dist/fe/components/IntegrationsPage/components/ConnectionDelete.js +2 -1
  3. package/dist/fe/components/IntegrationsPage/components/ConnectionExport.js +7 -5
  4. package/dist/fe/components/IntegrationsPage/components/ConnectionForm.js +3 -2
  5. package/dist/fe/components/IntegrationsPage/components/ConnectionList.js +2 -1
  6. package/dist/fe/components/IntegrationsPage/components/ConnectionTest.js +3 -2
  7. package/dist/fe/components/IntegrationsPage/components/ConnectionTransfer.js +7 -5
  8. package/dist/fe/components/IntegrationsPage/components/CredentialFields.js +6 -5
  9. package/dist/fe/components/IntegrationsPage/components/CredentialSlotRow.js +2 -1
  10. package/dist/fe/components/IntegrationsPage/components/EndpointForm.js +5 -4
  11. package/dist/fe/components/IntegrationsPage/components/EndpointSample.js +2 -1
  12. package/dist/fe/components/IntegrationsPage/components/FieldMappingRows.js +12 -75
  13. package/dist/fe/components/IntegrationsPage/components/MappingAccountFields.js +19 -17
  14. package/dist/fe/components/IntegrationsPage/components/MappingEditor.js +4 -4
  15. package/dist/fe/components/IntegrationsPage/components/MappingList.js +3 -2
  16. package/dist/fe/components/IntegrationsPage/components/MappingPasswordField.js +8 -5
  17. package/dist/fe/components/IntegrationsPage/components/MappingScheduleFields.js +37 -29
  18. package/dist/fe/components/IntegrationsPage/components/MappingWriteModeFields.js +3 -3
  19. package/dist/fe/components/IntegrationsPage/components/MappingsTab.js +9 -9
  20. package/dist/fe/components/IntegrationsPage/components/PaginationFields.js +137 -124
  21. package/dist/fe/components/IntegrationsPage/components/ReferenceCheckRows.js +42 -39
  22. package/dist/fe/components/IntegrationsPage/components/RunConfirmStep.js +2 -2
  23. package/dist/fe/components/IntegrationsPage/components/RunHistory.js +1 -1
  24. package/dist/fe/components/IntegrationsPage/components/RunHistoryRow.js +4 -2
  25. package/dist/fe/components/IntegrationsPage/components/RunPanel.js +6 -6
  26. package/dist/fe/components/IntegrationsPage/components/RunPasswordField.js +4 -2
  27. package/dist/fe/components/IntegrationsPage/components/RunPlanSuggestions.js +9 -33
  28. package/dist/fe/components/IntegrationsPage/components/RunPlanSummary.js +1 -1
  29. package/dist/fe/components/IntegrationsPage/components/RunProgressBar.js +12 -10
  30. package/dist/fe/components/IntegrationsPage/components/RunRevertConflicts.js +3 -1
  31. package/dist/fe/components/IntegrationsPage/components/Skeletons.js +4 -3
  32. package/dist/fe/components/IntegrationsPage/text/index.d.ts +193 -0
  33. package/dist/fe/components/IntegrationsPage/text/index.js +171 -0
  34. package/package.json +1 -1
package/dist/.build-ok CHANGED
@@ -1 +1 @@
1
- 0.9.886
1
+ 0.9.887
@@ -7,6 +7,7 @@ import { integrationsPageTheme as theme } from '../theme';
7
7
  import { deleteIsConfirmed } from './deleteIsConfirmed';
8
8
  import { Notice } from './Primitives';
9
9
  export function ConnectionDelete({ actions, source, onDeleted }) {
10
+ const t = useLabels().errors;
10
11
  const labels = useLabels();
11
12
  const store = useIntegrationsStore();
12
13
  const [asking, setAsking] = useState(false);
@@ -30,7 +31,7 @@ export function ConnectionDelete({ actions, source, onDeleted }) {
30
31
  onDeleted?.();
31
32
  }).catch((error)=>{
32
33
  setBusy(false);
33
- store.setError(error instanceof Error ? error.message : 'The request failed.');
34
+ store.setError(error instanceof Error ? error.message : t.requestFailed);
34
35
  });
35
36
  };
36
37
  return /*#__PURE__*/ _jsxs("section", {
@@ -2,6 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from 'react';
4
4
  import { useIntegrationsStore } from '../store';
5
+ import { useLabels } from '../text/context';
5
6
  import { integrationsPageTheme as theme } from '../theme';
6
7
  import { Notice } from './Primitives';
7
8
  /**
@@ -29,6 +30,7 @@ import { Notice } from './Primitives';
29
30
  * is a confusing half hour otherwise.
30
31
  */ /** A filename somebody can still recognise a week later. */ const fileNameFor = (slug)=>`integration-${slug || 'connection'}.json`;
31
32
  export function ConnectionExport({ actions, source }) {
33
+ const t = useLabels().transfer;
32
34
  const store = useIntegrationsStore();
33
35
  const [busy, setBusy] = useState(false);
34
36
  const [note, setNote] = useState(null);
@@ -40,7 +42,7 @@ export function ConnectionExport({ actions, source }) {
40
42
  actions.exportConnection(source.id).then((document)=>{
41
43
  setBusy(false);
42
44
  if (!document) {
43
- store.setError('The connection could not be exported.');
45
+ store.setError(t.exportFailed);
44
46
  return;
45
47
  }
46
48
  // Written from the browser rather than served as a download, so the file
@@ -56,10 +58,10 @@ export function ConnectionExport({ actions, source }) {
56
58
  link.download = fileNameFor(source.slug);
57
59
  link.click();
58
60
  URL.revokeObjectURL(url);
59
- setNote('Exported. Credentials are not in the file — enter them wherever it lands.');
61
+ setNote(t.exported);
60
62
  }).catch((error)=>{
61
63
  setBusy(false);
62
- store.setError(error instanceof Error ? error.message : 'The request failed.');
64
+ store.setError(error instanceof Error ? error.message : t.requestFailed);
63
65
  });
64
66
  };
65
67
  return /*#__PURE__*/ _jsxs("section", {
@@ -70,7 +72,7 @@ export function ConnectionExport({ actions, source }) {
70
72
  children: [
71
73
  /*#__PURE__*/ _jsx("h3", {
72
74
  className: theme.card.title,
73
- children: "Take this connection elsewhere"
75
+ children: t.exportTitle
74
76
  }),
75
77
  /*#__PURE__*/ _jsx("button", {
76
78
  className: theme.button.secondary,
@@ -89,7 +91,7 @@ export function ConnectionExport({ actions, source }) {
89
91
  children: "One file holding this connection, its calls and its mappings — enough to rebuild the whole integration in another installation. Bring it in there with Import, on the connections screen."
90
92
  }),
91
93
  /*#__PURE__*/ _jsx(Notice, {
92
- title: "No secrets travel in the file",
94
+ title: t.noSecretsTitle,
93
95
  tone: "info",
94
96
  children: "Tokens, passwords and keys are left out on purpose. Whatever this connection authenticates with has to be entered again wherever the file lands."
95
97
  }),
@@ -18,6 +18,7 @@ import { CardSkeleton } from './Skeletons';
18
18
  * of what was stored and what is being typed.
19
19
  */ const theme = integrationsPageTheme;
20
20
  export function ConnectionForm({ actions, source, loading = false, onSaved }) {
21
+ const t = useLabels().errors;
21
22
  const labels = useLabels();
22
23
  const store = useIntegrationsStore();
23
24
  const [draft, setDraft] = useState(()=>source ? draftFromSource(source) : emptyConnectionDraft);
@@ -51,7 +52,7 @@ export function ConnectionForm({ actions, source, loading = false, onSaved }) {
51
52
  actions.saveSource(draftToSource(draft, source?.id)).then((saved)=>{
52
53
  setSaving(false);
53
54
  if (!saved) {
54
- store.setError('The connection was not saved. The server did not return the record.');
55
+ store.setError(t.connectionNotSaved);
55
56
  return;
56
57
  }
57
58
  // Told about the record BEFORE it is selected. The caller is what puts
@@ -84,7 +85,7 @@ export function ConnectionForm({ actions, source, loading = false, onSaved }) {
84
85
  if (!source) store.selectSource(saved.id);
85
86
  }).catch((reason)=>{
86
87
  setSaving(false);
87
- store.setError(errorText(reason, 'The connection could not be saved.'));
88
+ store.setError(errorText(reason, t.connectionSaveFailed));
88
89
  });
89
90
  };
90
91
  if (loading) return /*#__PURE__*/ _jsx(CardSkeleton, {});
@@ -20,6 +20,7 @@ import { useInfiniteList } from './useInfiniteList';
20
20
  const PAGE_SIZE = 20;
21
21
  const SEARCH_DEBOUNCE_MS = 300;
22
22
  export function ConnectionList({ actions, onNewConnection, reloadToken = 0 }) {
23
+ const t = useLabels().errors;
23
24
  const store = useIntegrationsStore();
24
25
  const labels = useLabels();
25
26
  const search = store.sourcesSearch;
@@ -200,7 +201,7 @@ export function ConnectionList({ actions, onNewConnection, reloadToken = 0 }) {
200
201
  }),
201
202
  list.loading && list.items.length > 0 ? /*#__PURE__*/ _jsx("p", {
202
203
  className: theme.field.hint,
203
- children: "Loading more…"
204
+ children: t.loadingMore
204
205
  }) : null
205
206
  ]
206
207
  }));
@@ -16,6 +16,7 @@ import { CardSkeleton } from './Skeletons';
16
16
  * sends the operator back to guessing.
17
17
  */ const theme = integrationsPageTheme;
18
18
  export function ConnectionTest({ actions, source, loading = false }) {
19
+ const t = useLabels().errors;
19
20
  const labels = useLabels();
20
21
  const [testing, setTesting] = useState(false);
21
22
  const [result, setResult] = useState(null);
@@ -62,7 +63,7 @@ export function ConnectionTest({ actions, source, loading = false }) {
62
63
  setTesting(false);
63
64
  setResult({
64
65
  ok: false,
65
- error: errorText(reason, 'The test could not be run.')
66
+ error: errorText(reason, t.testFailed)
66
67
  });
67
68
  });
68
69
  };
@@ -115,7 +116,7 @@ export function ConnectionTest({ actions, source, loading = false }) {
115
116
  tone: "danger",
116
117
  children: /*#__PURE__*/ _jsx("p", {
117
118
  className: cn(theme.notice.body, 'whitespace-pre-wrap break-words font-mono'),
118
- children: result.error ?? 'The server reported a failure without a message.'
119
+ children: result.error ?? t.testFailedNoMessage
119
120
  })
120
121
  }) : null
121
122
  ]
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useRef, useState } from 'react';
4
4
  import { cn } from '../../../utils/cn';
5
5
  import { useIntegrationsStore } from '../store';
6
+ import { useLabels } from '../text/context';
6
7
  import { integrationsPageTheme } from '../theme';
7
8
  import { Notice } from './Primitives';
8
9
  /**
@@ -24,8 +25,9 @@ import { Notice } from './Primitives';
24
25
  * see ConnectionExport. Importing is the one that belongs here, because
25
26
  * importing is what you do when you have nothing chosen yet.
26
27
  */ const theme = integrationsPageTheme;
27
- const messageOf = (error)=>error instanceof Error ? error.message : 'The request failed.';
28
+ const messageOf = (error, fallback)=>error instanceof Error ? error.message : fallback;
28
29
  export function ConnectionTransfer({ actions, onImported }) {
30
+ const t = useLabels().transfer;
29
31
  const store = useIntegrationsStore();
30
32
  const fileRef = useRef(null);
31
33
  const [busy, setBusy] = useState(false);
@@ -44,7 +46,7 @@ export function ConnectionTransfer({ actions, onImported }) {
44
46
  setProblems([
45
47
  {
46
48
  path: file.name,
47
- message: 'This file is not readable as JSON.'
49
+ message: t.notJson
48
50
  }
49
51
  ]);
50
52
  return;
@@ -65,7 +67,7 @@ export function ConnectionTransfer({ actions, onImported }) {
65
67
  });
66
68
  }).catch((error)=>{
67
69
  setBusy(false);
68
- store.setError(messageOf(error));
70
+ store.setError(messageOf(error, t.requestFailed));
69
71
  });
70
72
  };
71
73
  return /*#__PURE__*/ _jsxs("section", {
@@ -76,7 +78,7 @@ export function ConnectionTransfer({ actions, onImported }) {
76
78
  disabled: busy,
77
79
  onClick: ()=>fileRef.current?.click(),
78
80
  type: "button",
79
- children: busy ? 'Working…' : 'Import a connection file'
81
+ children: busy ? t.working : t.importButton
80
82
  }),
81
83
  /*#__PURE__*/ _jsx("input", {
82
84
  accept: "application/json,.json",
@@ -96,7 +98,7 @@ export function ConnectionTransfer({ actions, onImported }) {
96
98
  children: note
97
99
  }) : null,
98
100
  problems.length > 0 ? /*#__PURE__*/ _jsx(Notice, {
99
- title: "This file cannot be imported as it stands",
101
+ title: t.cannotImportTitle,
100
102
  tone: "danger",
101
103
  children: /*#__PURE__*/ _jsx("ul", {
102
104
  className: "flex flex-col gap-1",
@@ -19,6 +19,7 @@ import { CardSkeleton } from './Skeletons';
19
19
  * button per field.
20
20
  */ const theme = integrationsPageTheme;
21
21
  export function CredentialFields({ actions, source, loading = false }) {
22
+ const t = useLabels().errors;
22
23
  const labels = useLabels();
23
24
  const store = useIntegrationsStore();
24
25
  const [values, setValues] = useState({});
@@ -92,7 +93,7 @@ export function CredentialFields({ actions, source, loading = false }) {
92
93
  }
93
94
  }
94
95
  if (filled === 0) {
95
- setStatus('Nothing to save — every box is empty, so the stored values are untouched.');
96
+ setStatus(t.nothingToSave);
96
97
  return;
97
98
  }
98
99
  setBusy(true);
@@ -104,10 +105,10 @@ export function CredentialFields({ actions, source, loading = false }) {
104
105
  // stored can only ever be looked at as the mask below.
105
106
  setValues({});
106
107
  applyHints(result);
107
- setStatus('Saved. Only the masked hints below come back.');
108
+ setStatus(t.credentialsSaved);
108
109
  }).catch((reason)=>{
109
110
  setBusy(false);
110
- store.setError(errorText(reason, 'The credentials could not be saved.'));
111
+ store.setError(errorText(reason, t.credentialsSaveFailed));
111
112
  });
112
113
  };
113
114
  const handleClear = (slot)=>{
@@ -128,10 +129,10 @@ export function CredentialFields({ actions, source, loading = false }) {
128
129
  remember({
129
130
  [slot]: hintFromResult(result, slot) ?? null
130
131
  });
131
- setStatus('Cleared. Nothing is stored for that field any more.');
132
+ setStatus(t.credentialCleared);
132
133
  }).catch((reason)=>{
133
134
  setBusy(false);
134
- store.setError(errorText(reason, 'The credential could not be cleared.'));
135
+ store.setError(errorText(reason, t.credentialClearFailed));
135
136
  });
136
137
  };
137
138
  return /*#__PURE__*/ _jsxs("section", {
@@ -16,6 +16,7 @@ import { Badge, Field } from './Primitives';
16
16
  * accident, roughly once.
17
17
  */ const theme = integrationsPageTheme;
18
18
  export function CredentialSlotRow({ slot, source, value, maskedHint, disabled, onChange, onClear }) {
19
+ const t = useLabels().errors;
19
20
  const labels = useLabels();
20
21
  const id = `credential-${slot}`;
21
22
  const label = slotLabel(slot, source);
@@ -34,7 +35,7 @@ export function CredentialSlotRow({ slot, source, value, maskedHint, disabled, o
34
35
  disabled: disabled,
35
36
  id: id,
36
37
  onChange: (event)=>onChange(event.target.value),
37
- placeholder: stored ? 'Leave empty to keep the stored value' : 'Nothing stored yet',
38
+ placeholder: stored ? t.keepStored : t.nothingStored,
38
39
  type: "password",
39
40
  value: value
40
41
  })
@@ -19,6 +19,7 @@ import { pathParamNames } from './pathParams';
19
19
  * a list page arriving in the background.
20
20
  */ const theme = integrationsPageTheme;
21
21
  export function EndpointForm({ sourceId, endpoint, actions, onSaved, onDeleted, onCancel }) {
22
+ const t = useLabels().errors;
22
23
  const labels = useLabels();
23
24
  const store = useIntegrationsStore();
24
25
  const [saving, setSaving] = useState(false);
@@ -106,8 +107,8 @@ export function EndpointForm({ sourceId, endpoint, actions, onSaved, onDeleted,
106
107
  }).then((saved)=>{
107
108
  setSaving(false);
108
109
  if (saved) onSaved(saved);
109
- else store.setError('The server did not return the saved endpoint.');
110
- }).catch(fail('Saving the endpoint failed.'));
110
+ else store.setError(t.endpointNotReturned);
111
+ }).catch(fail(t.endpointSaveFailed));
111
112
  };
112
113
  const remove = ()=>{
113
114
  if (!endpoint) return;
@@ -116,8 +117,8 @@ export function EndpointForm({ sourceId, endpoint, actions, onSaved, onDeleted,
116
117
  actions.deleteEndpoint(endpoint.id).then((ok)=>{
117
118
  setDeleting(false);
118
119
  if (ok) onDeleted(endpoint.id);
119
- else store.setError('The endpoint was not deleted.');
120
- }).catch(fail('Deleting the endpoint failed.'));
120
+ else store.setError(t.endpointNotDeleted);
121
+ }).catch(fail(t.endpointDeleteFailed));
121
122
  };
122
123
  return /*#__PURE__*/ _jsxs("form", {
123
124
  className: theme.card.wrapper,
@@ -17,6 +17,7 @@ import { settlementOf } from './settleOwnership';
17
17
  * their own block here rather than being folded into a generic "no data".
18
18
  */ const theme = integrationsPageTheme;
19
19
  export function EndpointSample({ endpoint, actions }) {
20
+ const t = useLabels().errors;
20
21
  const labels = useLabels();
21
22
  const store = useIntegrationsStore();
22
23
  const [values, setValues] = useState({});
@@ -97,7 +98,7 @@ export function EndpointSample({ endpoint, actions }) {
97
98
  }).catch((error)=>{
98
99
  if (settleElsewhere(mine, requestedFor)) return;
99
100
  store.setSample(null, requestedFor);
100
- store.setError(error instanceof Error ? error.message : 'Sampling the endpoint failed.');
101
+ store.setError(error instanceof Error ? error.message : t.sampleFailed);
101
102
  });
102
103
  };
103
104
  return /*#__PURE__*/ _jsxs("section", {
@@ -44,13 +44,13 @@ export function FieldMappingRows({ rows, sourceFields, targetFields, disabled, o
44
44
  type: "button",
45
45
  children: labels.mappings.addField
46
46
  }),
47
- purpose: "Which incoming value becomes which column. The order is the order they are applied in.",
47
+ purpose: labels.sections.fieldsPurpose,
48
48
  title: labels.mappings.fieldsHeading,
49
49
  children: [
50
50
  sourceFields.length === 0 ? /*#__PURE__*/ _jsx(Notice, {
51
51
  title: labels.mappings.sampleFirstTitle,
52
52
  tone: "warning",
53
- children: "No field names are known yet. Sampling the selected endpoint lists what the response really returns; until then a source has to be typed from memory, and a typo shows up only as an empty column once the import has already run."
53
+ children: labels.mappings.sampleFirstBody
54
54
  }) : null,
55
55
  /*#__PURE__*/ _jsx("datalist", {
56
56
  id: listId,
@@ -60,7 +60,7 @@ export function FieldMappingRows({ rows, sourceFields, targetFields, disabled, o
60
60
  }),
61
61
  rows.length === 0 ? /*#__PURE__*/ _jsx("p", {
62
62
  className: theme.list.empty,
63
- children: "Nothing is mapped yet, so a run would write empty records. Add a field to begin."
63
+ children: labels.mappings.nothingMapped
64
64
  }) : /*#__PURE__*/ _jsxs(_Fragment, {
65
65
  children: [
66
66
  /*#__PURE__*/ _jsxs("div", {
@@ -73,7 +73,7 @@ export function FieldMappingRows({ rows, sourceFields, targetFields, disabled, o
73
73
  }, column)),
74
74
  /*#__PURE__*/ _jsx("span", {
75
75
  className: cn(theme.field.label, 'w-28'),
76
- children: "Order"
76
+ children: labels.errors.fieldOrder
77
77
  })
78
78
  ]
79
79
  }),
@@ -92,84 +92,21 @@ export function FieldMappingRows({ rows, sourceFields, targetFields, disabled, o
92
92
  targetFields: targetFields
93
93
  }, `field-mapping-${index}`))
94
94
  }),
95
- /*#__PURE__*/ _jsxs("p", {
95
+ /*#__PURE__*/ _jsx("p", {
96
96
  className: theme.field.hint,
97
- children: [
98
- "Prefix a source with ",
99
- /*#__PURE__*/ _jsx("strong", {
100
- children: PARENT_PREFIX
101
- }),
102
- " to take the value from the parent endpoint's record instead of this one."
103
- ]
97
+ children: labels.hints.parentPrefix(PARENT_PREFIX)
104
98
  }),
105
- /*#__PURE__*/ _jsxs("p", {
99
+ /*#__PURE__*/ _jsx("p", {
106
100
  className: theme.field.hint,
107
- children: [
108
- "Name several fields in ",
109
- /*#__PURE__*/ _jsx("strong", {
110
- children: '{braces}'
111
- }),
112
- " to build one value from them —",
113
- ' ',
114
- /*#__PURE__*/ _jsx("strong", {
115
- children: '{companyCode}-{organizationCode}'
116
- }),
117
- ". Use it when no single field is unique on its own, which is what the deduplication column needs."
118
- ]
101
+ children: labels.hints.braces
119
102
  }),
120
- /*#__PURE__*/ _jsxs("p", {
103
+ /*#__PURE__*/ _jsx("p", {
121
104
  className: theme.field.hint,
122
- children: [
123
- "A single field inside the braces can be shaped on its own with ",
124
- /*#__PURE__*/ _jsx("strong", {
125
- children: '|'
126
- }),
127
- ":",
128
- ' ',
129
- /*#__PURE__*/ _jsx("strong", {
130
- children: '{companyCode}-{departmentCode|pathLeaf}'
131
- }),
132
- " turns ",
133
- /*#__PURE__*/ _jsx("em", {
134
- children: "TAT"
135
- }),
136
- " and",
137
- ' ',
138
- /*#__PURE__*/ _jsx("em", {
139
- children: "050/285/204"
140
- }),
141
- " into ",
142
- /*#__PURE__*/ _jsx("em", {
143
- children: "TAT-204"
144
- }),
145
- ". The transform chosen beside the row still applies to the finished value."
146
- ]
105
+ children: labels.hints.perFieldTransform
147
106
  }),
148
- /*#__PURE__*/ _jsxs("p", {
107
+ /*#__PURE__*/ _jsx("p", {
149
108
  className: theme.field.hint,
150
- children: [
151
- /*#__PURE__*/ _jsx("strong", {
152
- children: "Fallback"
153
- }),
154
- " takes the same braces, so a record that arrives without an e-mail can still be given one: ",
155
- /*#__PURE__*/ _jsx("strong", {
156
- children: '{ad}.{soyad}@example.com'
157
- }),
158
- ". Pair it with the ",
159
- /*#__PURE__*/ _jsx("strong", {
160
- children: "E-mail safe"
161
- }),
162
- " transform and ",
163
- /*#__PURE__*/ _jsx("em", {
164
- children: "Ayşe Yılmaz"
165
- }),
166
- " becomes",
167
- ' ',
168
- /*#__PURE__*/ _jsx("em", {
169
- children: "ayse.yilmaz@example.com"
170
- }),
171
- ". Records that already carry an address keep it."
172
- ]
109
+ children: labels.hints.fallbackBraces
173
110
  })
174
111
  ]
175
112
  })
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useId } from 'react';
4
+ import { useLabels } from '../text/context';
4
5
  import { integrationsPageTheme } from '../theme';
5
6
  import { Field, Notice, Section } from './Primitives';
6
7
  /**
@@ -22,6 +23,7 @@ import { Field, Notice, Section } from './Primitives';
22
23
  /** Columns that plausibly hold a password, so the guess is a good one. */ const PASSWORD_LIKE = /password|passwd|sifre|şifre|parola/i;
23
24
  /** Columns that plausibly point at the account row. */ const LINK_LIKE = /^(user_?id|account_?id|login_?id)$/i;
24
25
  export function MappingAccountFields({ value, targetFields, targets, disabled, onChange }) {
26
+ const t = useLabels().account;
25
27
  const uid = useId();
26
28
  const accountEntity = targets.find((target)=>target.entity === value?.entity);
27
29
  const accountFields = accountEntity?.fields ?? [];
@@ -59,8 +61,8 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
59
61
  type: "button",
60
62
  children: value ? 'Turn off' : 'Turn on'
61
63
  }),
62
- purpose: "A directory carries people, not logins. Turned on, the account is created in the same import and linked to the record.",
63
- title: "Also create a login for each new record",
64
+ purpose: t.purpose,
65
+ title: t.title,
64
66
  children: value ? /*#__PURE__*/ _jsxs(_Fragment, {
65
67
  children: [
66
68
  /*#__PURE__*/ _jsxs("div", {
@@ -68,7 +70,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
68
70
  children: [
69
71
  /*#__PURE__*/ _jsx(Field, {
70
72
  htmlFor: `${uid}-entity`,
71
- label: "Accounts live in",
73
+ label: t.livesIn,
72
74
  children: /*#__PURE__*/ _jsxs("select", {
73
75
  className: theme.field.input,
74
76
  disabled: disabled,
@@ -84,7 +86,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
84
86
  children: [
85
87
  /*#__PURE__*/ _jsx("option", {
86
88
  value: "",
87
- children: "Not set"
89
+ children: t.notSet
88
90
  }),
89
91
  targets.map((target)=>/*#__PURE__*/ _jsx("option", {
90
92
  value: target.entity,
@@ -96,7 +98,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
96
98
  /*#__PURE__*/ _jsx(Field, {
97
99
  hint: "The column on the account that identifies it.",
98
100
  htmlFor: `${uid}-match-column`,
99
- label: "Identified by",
101
+ label: t.identifiedBy,
100
102
  children: /*#__PURE__*/ _jsxs("select", {
101
103
  className: theme.field.input,
102
104
  disabled: disabled || accountFields.length === 0,
@@ -108,7 +110,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
108
110
  children: [
109
111
  /*#__PURE__*/ _jsx("option", {
110
112
  value: "",
111
- children: "Not set"
113
+ children: t.notSet
112
114
  }),
113
115
  accountFields.map((field)=>/*#__PURE__*/ _jsx("option", {
114
116
  value: field,
@@ -120,7 +122,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
120
122
  /*#__PURE__*/ _jsx(Field, {
121
123
  hint: "Where the run's shared password is written.",
122
124
  htmlFor: `${uid}-password`,
123
- label: "Password goes into",
125
+ label: t.passwordInto,
124
126
  children: /*#__PURE__*/ _jsxs("select", {
125
127
  className: theme.field.input,
126
128
  disabled: disabled || accountFields.length === 0,
@@ -132,14 +134,14 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
132
134
  children: [
133
135
  /*#__PURE__*/ _jsx("option", {
134
136
  value: "",
135
- children: "Not set"
137
+ children: t.notSet
136
138
  }),
137
139
  accountFields.filter((field)=>PASSWORD_LIKE.test(field)).map((field)=>/*#__PURE__*/ _jsx("option", {
138
140
  value: field,
139
141
  children: field
140
142
  }, field)),
141
143
  accountFields.filter((field)=>!PASSWORD_LIKE.test(field)).length > 0 ? /*#__PURE__*/ _jsx("optgroup", {
142
- label: "Other columns",
144
+ label: t.otherColumns,
143
145
  children: accountFields.filter((field)=>!PASSWORD_LIKE.test(field)).map((field)=>/*#__PURE__*/ _jsx("option", {
144
146
  value: field,
145
147
  children: field
@@ -151,7 +153,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
151
153
  /*#__PURE__*/ _jsx(Field, {
152
154
  hint: "The imported record's column carrying that same value.",
153
155
  htmlFor: `${uid}-match-from`,
154
- label: "Matched from",
156
+ label: t.matchedFrom,
155
157
  children: /*#__PURE__*/ _jsxs("select", {
156
158
  className: theme.field.input,
157
159
  disabled: disabled,
@@ -163,7 +165,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
163
165
  children: [
164
166
  /*#__PURE__*/ _jsx("option", {
165
167
  value: "",
166
- children: "Not set"
168
+ children: t.notSet
167
169
  }),
168
170
  targetFields.map((field)=>/*#__PURE__*/ _jsx("option", {
169
171
  value: field,
@@ -175,7 +177,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
175
177
  /*#__PURE__*/ _jsx(Field, {
176
178
  hint: "Used only when the column above came back EMPTY, so nobody is left without a login. Name the record's own columns in braces — {firstName}.{sicilNo}@acme.com. Leave it blank to go on skipping those records.",
177
179
  htmlFor: `${uid}-email-format`,
178
- label: "Identifier for records that have none",
180
+ label: t.identifierFallback,
179
181
  children: /*#__PURE__*/ _jsx("input", {
180
182
  className: theme.field.input,
181
183
  disabled: disabled,
@@ -190,7 +192,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
190
192
  /*#__PURE__*/ _jsx(Field, {
191
193
  hint: "Filled with the new account's id, so the record and its login know each other.",
192
194
  htmlFor: `${uid}-id-column`,
193
- label: "Account id goes into",
195
+ label: t.accountIdInto,
194
196
  children: /*#__PURE__*/ _jsxs("select", {
195
197
  className: theme.field.input,
196
198
  disabled: disabled,
@@ -202,7 +204,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
202
204
  children: [
203
205
  /*#__PURE__*/ _jsx("option", {
204
206
  value: "",
205
- children: "Not set"
207
+ children: t.notSet
206
208
  }),
207
209
  targetFields.map((field)=>/*#__PURE__*/ _jsx("option", {
208
210
  value: field,
@@ -221,7 +223,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
221
223
  children: [
222
224
  /*#__PURE__*/ _jsx("span", {
223
225
  className: theme.field.label,
224
- children: "What each new account is a member of"
226
+ children: t.membership
225
227
  }),
226
228
  /*#__PURE__*/ _jsx("button", {
227
229
  className: theme.button.ghost,
@@ -272,7 +274,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
272
274
  children: [
273
275
  /*#__PURE__*/ _jsx("option", {
274
276
  value: "",
275
- children: "Membership table…"
277
+ children: t.membershipTable
276
278
  }),
277
279
  targets.map((target)=>/*#__PURE__*/ _jsx("option", {
278
280
  value: target.entity,
@@ -344,7 +346,7 @@ export function MappingAccountFields({ value, targetFields, targets, disabled, o
344
346
  ]
345
347
  }),
346
348
  /*#__PURE__*/ _jsx(Notice, {
347
- title: "One password, typed on the import screen",
349
+ title: t.sharedPasswordTitle,
348
350
  tone: "info",
349
351
  children: "Every account this run creates is given the same opening password — asked for once, when the import is started, and stored nowhere. People change it themselves afterwards. A record whose value already has an account is linked to that one instead, so running this import again does not create a second."
350
352
  })
@@ -77,8 +77,8 @@ export function MappingEditor({ mapping, targets, targetsLoading, endpoints, fre
77
77
  className: theme.card.body,
78
78
  children: [
79
79
  /*#__PURE__*/ _jsxs(Section, {
80
- purpose: "Which call this reads, what it is called, and which of your tables it writes into.",
81
- title: "What this import is",
80
+ purpose: labels.sections.whatThisIsPurpose,
81
+ title: labels.sections.whatThisIs,
82
82
  children: [
83
83
  /*#__PURE__*/ _jsx(Field, {
84
84
  hint: endpoints.length === 0 ? labels.mappings.noEndpointsBody : readsFrom?.path ?? labels.mappings.readsFromHint,
@@ -173,8 +173,8 @@ export function MappingEditor({ mapping, targets, targetsLoading, endpoints, fre
173
173
  ]
174
174
  }),
175
175
  /*#__PURE__*/ _jsx(Section, {
176
- purpose: "How a record already here is recognised, and what happens to the ones the source stops sending.",
177
- title: "Matching and writing",
176
+ purpose: labels.sections.matchingAndWritingPurpose,
177
+ title: labels.sections.matchingAndWriting,
178
178
  children: /*#__PURE__*/ _jsx(MappingWriteModeFields, {
179
179
  dedupConfigured: (draft.dedupTargetField ?? '').trim() !== '',
180
180
  disabled: busy,
@@ -28,6 +28,7 @@ function describeLastRun(value) {
28
28
  return Number.isNaN(when.getTime()) ? 'Never run' : `Last run ${when.toLocaleString()}`;
29
29
  }
30
30
  export function MappingList({ actions, sourceId, selectedId, reloadToken, onSelect, onRun }) {
31
+ const t = useLabels().errors;
31
32
  const labels = useLabels();
32
33
  const store = useIntegrationsStore();
33
34
  const uid = useId();
@@ -146,7 +147,7 @@ export function MappingList({ actions, sourceId, selectedId, reloadToken, onSele
146
147
  rows: 5
147
148
  }) : list.items.length === 0 && !list.error ? /*#__PURE__*/ _jsx("p", {
148
149
  className: theme.list.empty,
149
- children: store.endpointsTotal === 0 ? 'No endpoints on this connection yet. A mapping reads from one, so add an endpoint first.' : 'No mappings match. A mapping is what turns a response into rows.'
150
+ children: store.endpointsTotal === 0 ? t.noEndpointsForMapping : labels.mappings.empty
150
151
  }) : /*#__PURE__*/ _jsxs(_Fragment, {
151
152
  children: [
152
153
  /*#__PURE__*/ _jsxs("p", {
@@ -180,7 +181,7 @@ export function MappingList({ actions, sourceId, selectedId, reloadToken, onSele
180
181
  }),
181
182
  /*#__PURE__*/ _jsx("span", {
182
183
  className: theme.list.itemMeta,
183
- children: mapping.targetEntity || 'No target entity'
184
+ children: mapping.targetEntity || t.noTargetEntity
184
185
  }),
185
186
  /*#__PURE__*/ _jsxs("span", {
186
187
  className: "mt-1 flex flex-wrap items-center gap-1.5",