nucleus-core-ts 0.9.885 → 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.
- package/dist/.build-ok +1 -1
- package/dist/fe/components/Captcha/components/Captcha.d.ts +1 -1
- package/dist/fe/components/Captcha/components/Captcha.js +26 -24
- package/dist/fe/components/Captcha/index.d.ts +1 -0
- package/dist/fe/components/Captcha/index.js +1 -0
- package/dist/fe/components/Captcha/labels.d.ts +44 -0
- package/dist/fe/components/Captcha/labels.js +33 -0
- package/dist/fe/components/Captcha/types.d.ts +4 -0
- package/dist/fe/components/IntegrationsPage/components/ConnectionDelete.js +2 -1
- package/dist/fe/components/IntegrationsPage/components/ConnectionExport.js +7 -5
- package/dist/fe/components/IntegrationsPage/components/ConnectionForm.js +3 -2
- package/dist/fe/components/IntegrationsPage/components/ConnectionList.js +2 -1
- package/dist/fe/components/IntegrationsPage/components/ConnectionTest.js +3 -2
- package/dist/fe/components/IntegrationsPage/components/ConnectionTransfer.js +7 -5
- package/dist/fe/components/IntegrationsPage/components/CredentialFields.js +6 -5
- package/dist/fe/components/IntegrationsPage/components/CredentialSlotRow.js +2 -1
- package/dist/fe/components/IntegrationsPage/components/EndpointForm.js +5 -4
- package/dist/fe/components/IntegrationsPage/components/EndpointSample.js +2 -1
- package/dist/fe/components/IntegrationsPage/components/FieldMappingRows.js +12 -75
- package/dist/fe/components/IntegrationsPage/components/MappingAccountFields.js +19 -17
- package/dist/fe/components/IntegrationsPage/components/MappingEditor.js +4 -4
- package/dist/fe/components/IntegrationsPage/components/MappingList.js +3 -2
- package/dist/fe/components/IntegrationsPage/components/MappingPasswordField.js +8 -5
- package/dist/fe/components/IntegrationsPage/components/MappingScheduleFields.js +37 -29
- package/dist/fe/components/IntegrationsPage/components/MappingWriteModeFields.js +3 -3
- package/dist/fe/components/IntegrationsPage/components/MappingsTab.js +9 -9
- package/dist/fe/components/IntegrationsPage/components/PaginationFields.js +137 -124
- package/dist/fe/components/IntegrationsPage/components/ReferenceCheckRows.js +42 -39
- package/dist/fe/components/IntegrationsPage/components/RunConfirmStep.js +2 -2
- package/dist/fe/components/IntegrationsPage/components/RunHistory.js +1 -1
- package/dist/fe/components/IntegrationsPage/components/RunHistoryRow.js +4 -2
- package/dist/fe/components/IntegrationsPage/components/RunPanel.js +6 -6
- package/dist/fe/components/IntegrationsPage/components/RunPasswordField.js +4 -2
- package/dist/fe/components/IntegrationsPage/components/RunPlanSuggestions.js +9 -33
- package/dist/fe/components/IntegrationsPage/components/RunPlanSummary.js +1 -1
- package/dist/fe/components/IntegrationsPage/components/RunProgressBar.js +12 -10
- package/dist/fe/components/IntegrationsPage/components/RunRevertConflicts.js +3 -1
- package/dist/fe/components/IntegrationsPage/components/Skeletons.js +4 -3
- package/dist/fe/components/IntegrationsPage/text/index.d.ts +193 -0
- package/dist/fe/components/IntegrationsPage/text/index.js +171 -0
- package/dist/fe/index.d.ts +2 -2
- package/dist/fe/index.js +1 -1
- package/package.json +1 -1
package/dist/.build-ok
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.9.
|
|
1
|
+
0.9.887
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ReactElement } from 'react';
|
|
2
2
|
import type { CaptchaProps } from '../types';
|
|
3
|
-
export declare function Captcha({ generateAction, config, onChallengeLoad, onAnswerChange, disabled, autoGenerate, className, label, errorMessage, themeOverride, }: CaptchaProps): ReactElement;
|
|
3
|
+
export declare function Captcha({ generateAction, config, onChallengeLoad, onAnswerChange, disabled, autoGenerate, className, label, labels: labelOverrides, errorMessage, themeOverride, }: CaptchaProps): ReactElement;
|
|
@@ -4,6 +4,7 @@ import { useGSAP } from '@gsap/react';
|
|
|
4
4
|
import gsap from 'gsap';
|
|
5
5
|
import { useEffect, useEffectEvent, useRef, useState } from 'react';
|
|
6
6
|
import { cn } from '../../../utils/cn';
|
|
7
|
+
import { DEFAULT_CAPTCHA_LABELS } from '../labels';
|
|
7
8
|
import { captchaTheme } from '../theme';
|
|
8
9
|
gsap.registerPlugin(useGSAP);
|
|
9
10
|
function mergeTheme(base, override) {
|
|
@@ -62,7 +63,14 @@ const RefreshIcon = ({ className, iconRef })=>/*#__PURE__*/ _jsxs("svg", {
|
|
|
62
63
|
})
|
|
63
64
|
]
|
|
64
65
|
});
|
|
65
|
-
export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChange, disabled = false, autoGenerate = true, className, label
|
|
66
|
+
export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChange, disabled = false, autoGenerate = true, className, label, labels: labelOverrides, errorMessage, themeOverride }) {
|
|
67
|
+
// `label` came first and some installs pass it; it still wins for the
|
|
68
|
+
// heading so nothing that already works changes.
|
|
69
|
+
const labels = {
|
|
70
|
+
...DEFAULT_CAPTCHA_LABELS,
|
|
71
|
+
...labelOverrides
|
|
72
|
+
};
|
|
73
|
+
const heading = label ?? labels.heading;
|
|
66
74
|
const theme = themeOverride ? mergeTheme(captchaTheme, themeOverride) : captchaTheme;
|
|
67
75
|
const containerRef = useRef(null);
|
|
68
76
|
const challengeRef = useRef(null);
|
|
@@ -89,9 +97,8 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
89
97
|
},
|
|
90
98
|
onAfterHandle: (response)=>{
|
|
91
99
|
const { data } = response;
|
|
92
|
-
console.log('[DEBUG]:', response);
|
|
93
100
|
if (!data || data.rateLimited) {
|
|
94
|
-
setRateLimitError(response.message ??
|
|
101
|
+
setRateLimitError(response.message ?? labels.tooManyRequests);
|
|
95
102
|
setChallengeData(null);
|
|
96
103
|
return;
|
|
97
104
|
}
|
|
@@ -111,7 +118,7 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
111
118
|
},
|
|
112
119
|
onErrorHandle: (_error, code)=>{
|
|
113
120
|
if (code === 429) {
|
|
114
|
-
setRateLimitError(
|
|
121
|
+
setRateLimitError(labels.tooManyRequests);
|
|
115
122
|
}
|
|
116
123
|
setChallengeData(null);
|
|
117
124
|
}
|
|
@@ -186,17 +193,17 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
186
193
|
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
|
187
194
|
};
|
|
188
195
|
const getPlaceholder = ()=>{
|
|
189
|
-
if (!challenge) return
|
|
196
|
+
if (!challenge) return labels.enterAnswer;
|
|
190
197
|
switch(challenge.type){
|
|
191
198
|
case 'math':
|
|
192
|
-
return
|
|
199
|
+
return labels.enterResult;
|
|
193
200
|
case 'image':
|
|
194
201
|
case 'text':
|
|
195
|
-
return
|
|
202
|
+
return labels.enterTextShown;
|
|
196
203
|
case 'puzzle':
|
|
197
|
-
return
|
|
204
|
+
return labels.enterPieceOrder;
|
|
198
205
|
default:
|
|
199
|
-
return
|
|
206
|
+
return labels.enterAnswer;
|
|
200
207
|
}
|
|
201
208
|
};
|
|
202
209
|
if (config?.enabled === false) {
|
|
@@ -210,7 +217,7 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
210
217
|
children: [
|
|
211
218
|
/*#__PURE__*/ _jsx("span", {
|
|
212
219
|
className: theme.label.base,
|
|
213
|
-
children:
|
|
220
|
+
children: heading
|
|
214
221
|
}),
|
|
215
222
|
/*#__PURE__*/ _jsx("div", {
|
|
216
223
|
ref: challengeRef,
|
|
@@ -234,7 +241,7 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
234
241
|
className: theme.challenge.image.wrapper,
|
|
235
242
|
children: /*#__PURE__*/ _jsx("img", {
|
|
236
243
|
src: challenge.imageData,
|
|
237
|
-
alt:
|
|
244
|
+
alt: labels.imageAlt,
|
|
238
245
|
className: theme.challenge.image.img,
|
|
239
246
|
draggable: false
|
|
240
247
|
})
|
|
@@ -242,14 +249,9 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
242
249
|
challenge.type === 'puzzle' && challenge.puzzleData && /*#__PURE__*/ _jsxs("div", {
|
|
243
250
|
className: theme.challenge.puzzle.wrapper,
|
|
244
251
|
children: [
|
|
245
|
-
/*#__PURE__*/
|
|
252
|
+
/*#__PURE__*/ _jsx("p", {
|
|
246
253
|
className: theme.challenge.puzzle.instruction,
|
|
247
|
-
children:
|
|
248
|
-
"Click the pieces in the correct order (0 to",
|
|
249
|
-
' ',
|
|
250
|
-
challenge.puzzleData.pieces.length - 1,
|
|
251
|
-
")"
|
|
252
|
-
]
|
|
254
|
+
children: labels.puzzleInstruction.replace('{last}', String(challenge.puzzleData.pieces.length - 1))
|
|
253
255
|
}),
|
|
254
256
|
/*#__PURE__*/ _jsx("div", {
|
|
255
257
|
className: theme.challenge.puzzle.grid,
|
|
@@ -272,7 +274,7 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
272
274
|
type: "button",
|
|
273
275
|
onClick: handleClearPuzzleOrder,
|
|
274
276
|
className: theme.challenge.puzzle.clearButton,
|
|
275
|
-
children:
|
|
277
|
+
children: labels.clearOrder
|
|
276
278
|
})
|
|
277
279
|
]
|
|
278
280
|
})
|
|
@@ -283,7 +285,7 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
283
285
|
className: theme.loading.wrapper,
|
|
284
286
|
children: /*#__PURE__*/ _jsx("p", {
|
|
285
287
|
className: "text-sm text-zinc-500",
|
|
286
|
-
children:
|
|
288
|
+
children: labels.clickRefresh
|
|
287
289
|
})
|
|
288
290
|
})
|
|
289
291
|
}),
|
|
@@ -293,7 +295,7 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
293
295
|
/*#__PURE__*/ _jsx("label", {
|
|
294
296
|
htmlFor: "captcha-answer",
|
|
295
297
|
className: "sr-only",
|
|
296
|
-
children:
|
|
298
|
+
children: heading
|
|
297
299
|
}),
|
|
298
300
|
/*#__PURE__*/ _jsx("input", {
|
|
299
301
|
id: "captcha-answer",
|
|
@@ -320,13 +322,13 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
320
322
|
iconRef: iconRef
|
|
321
323
|
}),
|
|
322
324
|
/*#__PURE__*/ _jsx("span", {
|
|
323
|
-
children:
|
|
325
|
+
children: labels.newChallenge
|
|
324
326
|
})
|
|
325
327
|
]
|
|
326
328
|
}),
|
|
327
329
|
timeRemaining !== null && /*#__PURE__*/ _jsx("span", {
|
|
328
330
|
className: isExpired ? theme.actions.timerExpired : theme.actions.timer,
|
|
329
|
-
children: isExpired ?
|
|
331
|
+
children: isExpired ? labels.expired : labels.expiresIn.replace('{time}', formatTime(timeRemaining))
|
|
330
332
|
})
|
|
331
333
|
]
|
|
332
334
|
}),
|
|
@@ -334,7 +336,7 @@ export function Captcha({ generateAction, config, onChallengeLoad, onAnswerChang
|
|
|
334
336
|
className: theme.error.container,
|
|
335
337
|
children: /*#__PURE__*/ _jsx("p", {
|
|
336
338
|
className: theme.error.text,
|
|
337
|
-
children: rateLimitError ? rateLimitError : isExpired ?
|
|
339
|
+
children: rateLimitError ? rateLimitError : isExpired ? labels.expiredMessage : errorMessage
|
|
338
340
|
})
|
|
339
341
|
})
|
|
340
342
|
]
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { Captcha } from './components/Captcha';
|
|
2
|
+
export { type CaptchaLabels, DEFAULT_CAPTCHA_LABELS } from './labels';
|
|
2
3
|
export { captchaTheme } from './theme';
|
|
3
4
|
export type { CaptchaAction, CaptchaChallenge, CaptchaChallengeData, CaptchaConfig, CaptchaDifficulty, CaptchaProps, CaptchaState, CaptchaThemeOverride, CaptchaType, } from './types';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every word the security check says.
|
|
3
|
+
*
|
|
4
|
+
* This is the most-read component in the kit and the one nobody thought to
|
|
5
|
+
* translate: it sits on the sign-in form, so on an installation of 879 people
|
|
6
|
+
* it is shown several hundred times a morning. A portal could pass `label` and
|
|
7
|
+
* change the heading — and the box under the heading still said "Enter the
|
|
8
|
+
* result", "New challenge", "Expires in 1:30" and, when somebody was slow,
|
|
9
|
+
* "Captcha expired. Please refresh." Four sentences of English on the first
|
|
10
|
+
* screen of a portal that is otherwise entirely in its own language.
|
|
11
|
+
*
|
|
12
|
+
* The placeholders are per challenge type because the instruction is different
|
|
13
|
+
* for each: a sum wants its result, an image wants the letters in it, and the
|
|
14
|
+
* puzzle wants an order. `expiresIn` takes the formatted clock as `{time}` so a
|
|
15
|
+
* translation can put it where its own grammar wants it.
|
|
16
|
+
*
|
|
17
|
+
* Defaults stay English, so an installation that passes nothing is unchanged.
|
|
18
|
+
*/
|
|
19
|
+
export type CaptchaLabels = {
|
|
20
|
+
/** The heading over the box, and the input's screen-reader label. */
|
|
21
|
+
heading: string;
|
|
22
|
+
/** Before a challenge has been asked for. */
|
|
23
|
+
clickRefresh: string;
|
|
24
|
+
/** The answer box, by challenge type. */
|
|
25
|
+
enterAnswer: string;
|
|
26
|
+
enterResult: string;
|
|
27
|
+
enterTextShown: string;
|
|
28
|
+
enterPieceOrder: string;
|
|
29
|
+
/** The picture challenge's alternative text. */
|
|
30
|
+
imageAlt: string;
|
|
31
|
+
/** The puzzle: its instruction takes the highest piece number as `{last}`. */
|
|
32
|
+
puzzleInstruction: string;
|
|
33
|
+
clearOrder: string;
|
|
34
|
+
/** Asking for a different challenge. */
|
|
35
|
+
newChallenge: string;
|
|
36
|
+
/** The countdown. `expiresIn` takes the clock as `{time}`. */
|
|
37
|
+
expiresIn: string;
|
|
38
|
+
expired: string;
|
|
39
|
+
/** What the box says once the clock has run out. */
|
|
40
|
+
expiredMessage: string;
|
|
41
|
+
/** Asked for too many challenges too quickly. */
|
|
42
|
+
tooManyRequests: string;
|
|
43
|
+
};
|
|
44
|
+
export declare const DEFAULT_CAPTCHA_LABELS: CaptchaLabels;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every word the security check says.
|
|
3
|
+
*
|
|
4
|
+
* This is the most-read component in the kit and the one nobody thought to
|
|
5
|
+
* translate: it sits on the sign-in form, so on an installation of 879 people
|
|
6
|
+
* it is shown several hundred times a morning. A portal could pass `label` and
|
|
7
|
+
* change the heading — and the box under the heading still said "Enter the
|
|
8
|
+
* result", "New challenge", "Expires in 1:30" and, when somebody was slow,
|
|
9
|
+
* "Captcha expired. Please refresh." Four sentences of English on the first
|
|
10
|
+
* screen of a portal that is otherwise entirely in its own language.
|
|
11
|
+
*
|
|
12
|
+
* The placeholders are per challenge type because the instruction is different
|
|
13
|
+
* for each: a sum wants its result, an image wants the letters in it, and the
|
|
14
|
+
* puzzle wants an order. `expiresIn` takes the formatted clock as `{time}` so a
|
|
15
|
+
* translation can put it where its own grammar wants it.
|
|
16
|
+
*
|
|
17
|
+
* Defaults stay English, so an installation that passes nothing is unchanged.
|
|
18
|
+
*/ export const DEFAULT_CAPTCHA_LABELS = {
|
|
19
|
+
heading: 'Security Check',
|
|
20
|
+
clickRefresh: 'Click refresh to load captcha',
|
|
21
|
+
enterAnswer: 'Enter answer',
|
|
22
|
+
enterResult: 'Enter the result',
|
|
23
|
+
enterTextShown: 'Enter the text shown',
|
|
24
|
+
enterPieceOrder: 'Enter piece order (e.g., 0,1,2,3)',
|
|
25
|
+
imageAlt: 'Captcha',
|
|
26
|
+
puzzleInstruction: 'Click the pieces in the correct order (0 to {last})',
|
|
27
|
+
clearOrder: 'Clear',
|
|
28
|
+
newChallenge: 'New challenge',
|
|
29
|
+
expiresIn: 'Expires in {time}',
|
|
30
|
+
expired: 'Expired',
|
|
31
|
+
expiredMessage: 'Captcha expired. Please refresh.',
|
|
32
|
+
tooManyRequests: 'Too many requests. Please try again later.'
|
|
33
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CaptchaLabels } from './labels';
|
|
1
2
|
export type CaptchaType = 'math' | 'image' | 'puzzle' | 'text';
|
|
2
3
|
export type CaptchaDifficulty = 'easy' | 'medium' | 'hard';
|
|
3
4
|
export interface CaptchaChallengeData {
|
|
@@ -110,7 +111,10 @@ export interface CaptchaProps {
|
|
|
110
111
|
disabled?: boolean;
|
|
111
112
|
autoGenerate?: boolean;
|
|
112
113
|
className?: string;
|
|
114
|
+
/** The heading only. Kept because installs already pass it; `labels` covers the rest. */
|
|
113
115
|
label?: string;
|
|
116
|
+
/** Every other word the box says — see `../labels`. */
|
|
117
|
+
labels?: Partial<CaptchaLabels>;
|
|
114
118
|
errorMessage?: string;
|
|
115
119
|
themeOverride?: CaptchaThemeOverride;
|
|
116
120
|
}
|
|
@@ -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 :
|
|
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(
|
|
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(
|
|
61
|
+
setNote(t.exported);
|
|
60
62
|
}).catch((error)=>{
|
|
61
63
|
setBusy(false);
|
|
62
|
-
store.setError(error instanceof Error ? error.message :
|
|
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:
|
|
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:
|
|
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(
|
|
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,
|
|
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:
|
|
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,
|
|
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 ??
|
|
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 :
|
|
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:
|
|
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 ?
|
|
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:
|
|
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(
|
|
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(
|
|
108
|
+
setStatus(t.credentialsSaved);
|
|
108
109
|
}).catch((reason)=>{
|
|
109
110
|
setBusy(false);
|
|
110
|
-
store.setError(errorText(reason,
|
|
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(
|
|
132
|
+
setStatus(t.credentialCleared);
|
|
132
133
|
}).catch((reason)=>{
|
|
133
134
|
setBusy(false);
|
|
134
|
-
store.setError(errorText(reason,
|
|
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 ?
|
|
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(
|
|
110
|
-
}).catch(fail(
|
|
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(
|
|
120
|
-
}).catch(fail(
|
|
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 :
|
|
101
|
+
store.setError(error instanceof Error ? error.message : t.sampleFailed);
|
|
101
102
|
});
|
|
102
103
|
};
|
|
103
104
|
return /*#__PURE__*/ _jsxs("section", {
|