nucleus-core-ts 0.9.800 → 0.9.801
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/fe/components/IntegrationsPage/components/ConnectionBasicFields.js +18 -17
- package/dist/fe/components/IntegrationsPage/components/IntegrationsPage.js +29 -0
- package/dist/fe/components/IntegrationsPage/store/index.js +9 -0
- package/dist/fe/components/IntegrationsPage/store/state.d.ts +9 -0
- package/dist/fe/components/IntegrationsPage/text/index.d.ts +20 -0
- package/dist/fe/components/IntegrationsPage/text/index.js +19 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { cn } from '../../../utils/cn';
|
|
4
|
+
import { useLabels } from '../text/context';
|
|
4
5
|
import { integrationsPageTheme } from '../theme';
|
|
5
6
|
import { describedBy } from './formSupport';
|
|
6
7
|
import { Field } from './Primitives';
|
|
@@ -9,16 +10,16 @@ import { Field } from './Primitives';
|
|
|
9
10
|
* decide whether it is used and how carefully.
|
|
10
11
|
*/ const theme = integrationsPageTheme;
|
|
11
12
|
const CHECKBOX = 'h-4 w-4 shrink-0 accent-sky-600 dark:accent-sky-500';
|
|
12
|
-
const BASE_URL_HINT = 'The scheme is free. https:// and plain http:// are both accepted and neither is rewritten — calling a service inside the same cluster over http, for example http://hr-service:8080, is a legitimate setup.';
|
|
13
13
|
export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
14
|
+
const labels = useLabels();
|
|
14
15
|
return /*#__PURE__*/ _jsxs("section", {
|
|
15
|
-
"aria-label":
|
|
16
|
+
"aria-label": labels.connectionForm.sectionLabel,
|
|
16
17
|
className: "flex flex-col gap-3",
|
|
17
18
|
children: [
|
|
18
19
|
/*#__PURE__*/ _jsx(Field, {
|
|
19
20
|
error: errors.name,
|
|
20
21
|
htmlFor: "connection-name",
|
|
21
|
-
label:
|
|
22
|
+
label: labels.connectionForm.name,
|
|
22
23
|
children: /*#__PURE__*/ _jsx("input", {
|
|
23
24
|
"aria-describedby": describedBy('connection-name', false, Boolean(errors.name)),
|
|
24
25
|
className: theme.field.input,
|
|
@@ -27,16 +28,16 @@ export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
|
27
28
|
onChange: (event)=>onChange({
|
|
28
29
|
name: event.target.value
|
|
29
30
|
}),
|
|
30
|
-
placeholder:
|
|
31
|
+
placeholder: labels.connectionForm.namePlaceholder,
|
|
31
32
|
type: "text",
|
|
32
33
|
value: draft.name
|
|
33
34
|
})
|
|
34
35
|
}),
|
|
35
36
|
/*#__PURE__*/ _jsx(Field, {
|
|
36
37
|
error: errors.slug,
|
|
37
|
-
hint:
|
|
38
|
+
hint: labels.connectionForm.slugHint,
|
|
38
39
|
htmlFor: "connection-slug",
|
|
39
|
-
label:
|
|
40
|
+
label: labels.connectionForm.slug,
|
|
40
41
|
children: /*#__PURE__*/ _jsx("input", {
|
|
41
42
|
"aria-describedby": describedBy('connection-slug', true, Boolean(errors.slug)),
|
|
42
43
|
className: theme.field.input,
|
|
@@ -52,9 +53,9 @@ export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
|
52
53
|
}),
|
|
53
54
|
/*#__PURE__*/ _jsx(Field, {
|
|
54
55
|
error: errors.baseUrl,
|
|
55
|
-
hint:
|
|
56
|
+
hint: labels.connectionForm.baseUrlHint,
|
|
56
57
|
htmlFor: "connection-base-url",
|
|
57
|
-
label:
|
|
58
|
+
label: labels.connectionForm.baseUrl,
|
|
58
59
|
children: /*#__PURE__*/ _jsx("input", {
|
|
59
60
|
"aria-describedby": describedBy('connection-base-url', true, Boolean(errors.baseUrl)),
|
|
60
61
|
className: theme.field.input,
|
|
@@ -69,9 +70,9 @@ export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
|
69
70
|
})
|
|
70
71
|
}),
|
|
71
72
|
/*#__PURE__*/ _jsx(Field, {
|
|
72
|
-
hint:
|
|
73
|
+
hint: labels.connectionForm.descriptionHint,
|
|
73
74
|
htmlFor: "connection-description",
|
|
74
|
-
label:
|
|
75
|
+
label: labels.connectionForm.description,
|
|
75
76
|
children: /*#__PURE__*/ _jsx("textarea", {
|
|
76
77
|
"aria-describedby": describedBy('connection-description', true, false),
|
|
77
78
|
className: cn(theme.field.input, 'h-20 py-2 sm:h-20'),
|
|
@@ -80,7 +81,7 @@ export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
|
80
81
|
onChange: (event)=>onChange({
|
|
81
82
|
description: event.target.value
|
|
82
83
|
}),
|
|
83
|
-
placeholder:
|
|
84
|
+
placeholder: labels.connectionForm.descriptionPlaceholder,
|
|
84
85
|
value: draft.description
|
|
85
86
|
})
|
|
86
87
|
}),
|
|
@@ -102,13 +103,13 @@ export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
|
102
103
|
}),
|
|
103
104
|
type: "checkbox"
|
|
104
105
|
}),
|
|
105
|
-
|
|
106
|
+
labels.connectionForm.enabled
|
|
106
107
|
]
|
|
107
108
|
}),
|
|
108
109
|
/*#__PURE__*/ _jsx("span", {
|
|
109
110
|
className: theme.field.hint,
|
|
110
111
|
id: "connection-enabled-hint",
|
|
111
|
-
children:
|
|
112
|
+
children: labels.connectionForm.enabledHint
|
|
112
113
|
})
|
|
113
114
|
]
|
|
114
115
|
}),
|
|
@@ -130,21 +131,21 @@ export function ConnectionBasicFields({ draft, errors, disabled, onChange }) {
|
|
|
130
131
|
}),
|
|
131
132
|
type: "checkbox"
|
|
132
133
|
}),
|
|
133
|
-
|
|
134
|
+
labels.connectionForm.tlsVerify
|
|
134
135
|
]
|
|
135
136
|
}),
|
|
136
137
|
/*#__PURE__*/ _jsx("span", {
|
|
137
138
|
className: theme.field.hint,
|
|
138
139
|
id: "connection-tls-verify-hint",
|
|
139
|
-
children: draft.tlsVerify ?
|
|
140
|
+
children: draft.tlsVerify ? labels.connectionForm.tlsVerifyOnHint : labels.connectionForm.tlsVerifyOffHint
|
|
140
141
|
})
|
|
141
142
|
]
|
|
142
143
|
}),
|
|
143
144
|
/*#__PURE__*/ _jsx(Field, {
|
|
144
145
|
error: errors.timeoutMs,
|
|
145
|
-
hint:
|
|
146
|
+
hint: labels.connectionForm.timeoutHint,
|
|
146
147
|
htmlFor: "connection-timeout",
|
|
147
|
-
label:
|
|
148
|
+
label: labels.connectionForm.timeout,
|
|
148
149
|
children: /*#__PURE__*/ _jsx("input", {
|
|
149
150
|
"aria-describedby": describedBy('connection-timeout', true, Boolean(errors.timeoutMs)),
|
|
150
151
|
className: theme.field.input,
|
|
@@ -45,6 +45,35 @@ export function IntegrationsPage({ title = 'Integrations', subtitle = 'Connect a
|
|
|
45
45
|
const handleSourceSaved = ()=>{
|
|
46
46
|
setSourcesReloadToken((token)=>token + 1);
|
|
47
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* How far this connection has got, asked for directly.
|
|
50
|
+
*
|
|
51
|
+
* The step strip promises to say where you are, so it cannot depend on having
|
|
52
|
+
* VISITED the step that counts — on a fresh load every total was zero and the
|
|
53
|
+
* strip told an operator with five calls, three mappings and two finished
|
|
54
|
+
* imports to "finish the previous step first". Three counting requests, one
|
|
55
|
+
* row each, are the price of a strip that is telling the truth.
|
|
56
|
+
*/ const loadProgress = useEffectEvent((sourceId)=>{
|
|
57
|
+
const one = {
|
|
58
|
+
page: 1,
|
|
59
|
+
limit: 1
|
|
60
|
+
};
|
|
61
|
+
const total = (result)=>result.meta?.totalItems ?? 0;
|
|
62
|
+
actions.listEndpoints(sourceId, one).then((r)=>store.setEndpointsTotal(total(r))).catch(()=>{});
|
|
63
|
+
actions.listMappings(sourceId, one).then((r)=>store.setMappingsTotal(total(r))).catch(()=>{});
|
|
64
|
+
// Runs are deliberately NOT counted here. A run records the mapping it came
|
|
65
|
+
// from and nothing about the connection, so the only count available is
|
|
66
|
+
// every run of every connection — which on the second connection would be
|
|
67
|
+
// a number that looks like this one's and is not. The Runs tab sets the
|
|
68
|
+
// real figure for the mapping it is showing; until then the step says
|
|
69
|
+
// nothing rather than something wrong.
|
|
70
|
+
});
|
|
71
|
+
useEffect(()=>{
|
|
72
|
+
if (store.selectedSourceId) loadProgress(store.selectedSourceId);
|
|
73
|
+
}, [
|
|
74
|
+
store.selectedSourceId,
|
|
75
|
+
sourcesReloadToken
|
|
76
|
+
]);
|
|
48
77
|
// One measured entrance. Anything longer makes an operator wait to read counts
|
|
49
78
|
// they came here to check.
|
|
50
79
|
useGSAP(()=>{
|
|
@@ -49,6 +49,9 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
49
49
|
store.endpointsTotal = total;
|
|
50
50
|
store.endpointsLoading = false;
|
|
51
51
|
}),
|
|
52
|
+
setEndpointsTotal: (store)=>(total)=>{
|
|
53
|
+
store.endpointsTotal = total;
|
|
54
|
+
},
|
|
52
55
|
setEndpointsPage: (store)=>(page)=>{
|
|
53
56
|
store.endpointsPage = page;
|
|
54
57
|
},
|
|
@@ -70,6 +73,9 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
70
73
|
store.mappingsTotal = total;
|
|
71
74
|
store.mappingsLoading = false;
|
|
72
75
|
}),
|
|
76
|
+
setMappingsTotal: (store)=>(total)=>{
|
|
77
|
+
store.mappingsTotal = total;
|
|
78
|
+
},
|
|
73
79
|
setMappingsPage: (store)=>(page)=>{
|
|
74
80
|
store.mappingsPage = page;
|
|
75
81
|
},
|
|
@@ -97,6 +103,9 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
97
103
|
store.runsTotal = total;
|
|
98
104
|
store.runsLoading = false;
|
|
99
105
|
}),
|
|
106
|
+
setRunsTotal: (store)=>(total)=>{
|
|
107
|
+
store.runsTotal = total;
|
|
108
|
+
},
|
|
100
109
|
setRunsPage: (store)=>(page)=>{
|
|
101
110
|
store.runsPage = page;
|
|
102
111
|
},
|
|
@@ -57,16 +57,25 @@ export type Actions = {
|
|
|
57
57
|
selectSource: (id: string | null) => void;
|
|
58
58
|
setTab: (tab: ConnectionTab) => void;
|
|
59
59
|
setEndpoints: (items: IntegrationEndpoint[], total: number) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Just the count, without the rows.
|
|
62
|
+
*
|
|
63
|
+
* The step strip reports how far a connection has got, and it cannot wait for
|
|
64
|
+
* the tab that lists the rows to have been opened — so it counts directly.
|
|
65
|
+
*/
|
|
66
|
+
setEndpointsTotal: (total: number) => void;
|
|
60
67
|
setEndpointsPage: (page: number) => void;
|
|
61
68
|
setEndpointsSearch: (search: string) => void;
|
|
62
69
|
setEndpointsLoading: (loading: boolean) => void;
|
|
63
70
|
selectEndpoint: (id: string | null) => void;
|
|
64
71
|
setMappings: (items: IntegrationMapping[], total: number) => void;
|
|
72
|
+
setMappingsTotal: (total: number) => void;
|
|
65
73
|
setMappingsPage: (page: number) => void;
|
|
66
74
|
setMappingsSearch: (search: string) => void;
|
|
67
75
|
setMappingsLoading: (loading: boolean) => void;
|
|
68
76
|
selectMapping: (id: string | null) => void;
|
|
69
77
|
setRuns: (items: IntegrationRun[], total: number) => void;
|
|
78
|
+
setRunsTotal: (total: number) => void;
|
|
70
79
|
setRunsPage: (page: number) => void;
|
|
71
80
|
setRunsLoading: (loading: boolean) => void;
|
|
72
81
|
setSample: (sample: EndpointSampleValue | null) => void;
|
|
@@ -80,6 +80,26 @@ export type IntegrationsLabels = {
|
|
|
80
80
|
skipped: string;
|
|
81
81
|
dedupKey: string;
|
|
82
82
|
};
|
|
83
|
+
/** The connection form — the first screen anyone meets. */
|
|
84
|
+
connectionForm: {
|
|
85
|
+
sectionLabel: string;
|
|
86
|
+
name: string;
|
|
87
|
+
namePlaceholder: string;
|
|
88
|
+
slug: string;
|
|
89
|
+
slugHint: string;
|
|
90
|
+
baseUrl: string;
|
|
91
|
+
baseUrlHint: string;
|
|
92
|
+
description: string;
|
|
93
|
+
descriptionHint: string;
|
|
94
|
+
descriptionPlaceholder: string;
|
|
95
|
+
enabled: string;
|
|
96
|
+
enabledHint: string;
|
|
97
|
+
tlsVerify: string;
|
|
98
|
+
tlsVerifyOnHint: string;
|
|
99
|
+
tlsVerifyOffHint: string;
|
|
100
|
+
timeout: string;
|
|
101
|
+
timeoutHint: string;
|
|
102
|
+
};
|
|
83
103
|
writeMode: {
|
|
84
104
|
upsert: string;
|
|
85
105
|
append: string;
|
|
@@ -74,6 +74,25 @@
|
|
|
74
74
|
skipped: 'Skipped',
|
|
75
75
|
dedupKey: 'Dedup key'
|
|
76
76
|
},
|
|
77
|
+
connectionForm: {
|
|
78
|
+
sectionLabel: 'Connection details',
|
|
79
|
+
name: 'Name',
|
|
80
|
+
namePlaceholder: 'Directory service',
|
|
81
|
+
slug: 'Slug',
|
|
82
|
+
slugHint: 'Used to refer to this connection elsewhere. It does not change once things point at it.',
|
|
83
|
+
baseUrl: 'Base URL',
|
|
84
|
+
baseUrlHint: 'The scheme is free. https:// and plain http:// are both accepted and neither is rewritten — calling a service inside the same cluster over http, for example http://hr-service:8080, is a legitimate setup.',
|
|
85
|
+
description: 'Description',
|
|
86
|
+
descriptionHint: 'For whoever has to work out what this connection is, months from now.',
|
|
87
|
+
descriptionPlaceholder: 'Read-only employee directory used by the nightly import.',
|
|
88
|
+
enabled: 'Enabled',
|
|
89
|
+
enabledHint: 'Turning this off stops every endpoint and import that goes through this connection. The settings are kept.',
|
|
90
|
+
tlsVerify: 'Verify TLS certificate',
|
|
91
|
+
tlsVerifyOnHint: 'On. Unchecking it applies to requests made through THIS connection only — no other connection and nothing else in the app is affected.',
|
|
92
|
+
tlsVerifyOffHint: 'Off. Certificates are not checked for requests made through THIS connection only. Every other connection still verifies. Use it for an internal service with its own certificate authority.',
|
|
93
|
+
timeout: 'Timeout (ms)',
|
|
94
|
+
timeoutHint: 'How long one request may take before it is given up on. Empty means the server default.'
|
|
95
|
+
},
|
|
77
96
|
writeMode: {
|
|
78
97
|
upsert: 'update what matches, insert the rest',
|
|
79
98
|
append: 'always insert, never match',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nucleus-core-ts",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.801",
|
|
4
4
|
"description": "Production-ready, enterprise-grade TypeScript framework for building multi-tenant APIs",
|
|
5
5
|
"author": "Hidayet Can Özcan <hidayetcan@gmail.com>",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|