nucleus-core-ts 0.9.859 → 0.9.861
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/ConnectionList.js +6 -2
- package/dist/fe/components/IntegrationsPage/components/EndpointList.js +6 -2
- package/dist/fe/components/IntegrationsPage/components/MappingList.js +6 -2
- package/dist/fe/components/IntegrationsPage/components/MappingsTab.js +39 -15
- package/dist/fe/components/IntegrationsPage/components/RunHistory.js +6 -2
- package/dist/fe/components/IntegrationsPage/components/RunPanel.js +11 -3
- package/dist/fe/components/IntegrationsPage/store/index.js +11 -1
- package/dist/fe/components/IntegrationsPage/store/state.d.ts +12 -1
- package/dist/fe/components/IntegrationsPage/store/state.js +1 -0
- package/dist/index.js +1 -1
- package/dist/src/Services/Integrations/mapping.d.ts +1 -1
- package/dist/src/Services/Integrations/writer.d.ts +9 -0
- package/package.json +1 -1
|
@@ -64,11 +64,15 @@ export function ConnectionList({ actions, onNewConnection, reloadToken = 0 }) {
|
|
|
64
64
|
// which is where the editor looks for the record it is editing. Saving
|
|
65
65
|
// triggers a reset, so saving is when the record vanished.
|
|
66
66
|
useEffect(()=>{
|
|
67
|
-
|
|
67
|
+
// And not when it FAILED. `settled` means the request finished, which a
|
|
68
|
+
// refused one also did — publishing that emptied the store on every
|
|
69
|
+
// failed refetch and took the record the editor was showing with it.
|
|
70
|
+
if (list.settled && !list.error) publishItems();
|
|
68
71
|
}, [
|
|
69
72
|
list.items,
|
|
70
73
|
list.total,
|
|
71
|
-
list.settled
|
|
74
|
+
list.settled,
|
|
75
|
+
list.error
|
|
72
76
|
]);
|
|
73
77
|
useEffect(()=>{
|
|
74
78
|
publishLoading();
|
|
@@ -77,11 +77,15 @@ export function EndpointList({ sourceId, actions, onNewEndpoint, onSelect, reloa
|
|
|
77
77
|
// which is where the editor looks for the record it is editing. Saving
|
|
78
78
|
// triggers a reset, so saving is when the record vanished.
|
|
79
79
|
useEffect(()=>{
|
|
80
|
-
|
|
80
|
+
// And not when it FAILED. `settled` means the request finished, which a
|
|
81
|
+
// refused one also did — publishing that emptied the store on every
|
|
82
|
+
// failed refetch and took the record the editor was showing with it.
|
|
83
|
+
if (list.settled && !list.error) publishItems();
|
|
81
84
|
}, [
|
|
82
85
|
list.items,
|
|
83
86
|
list.total,
|
|
84
|
-
list.settled
|
|
87
|
+
list.settled,
|
|
88
|
+
list.error
|
|
85
89
|
]);
|
|
86
90
|
useEffect(()=>{
|
|
87
91
|
publishLoading();
|
|
@@ -88,11 +88,15 @@ export function MappingList({ actions, sourceId, selectedId, reloadToken, onSele
|
|
|
88
88
|
// which is where the editor looks for the record it is editing. Saving
|
|
89
89
|
// triggers a reset, so saving is when the record vanished.
|
|
90
90
|
useEffect(()=>{
|
|
91
|
-
|
|
91
|
+
// And not when it FAILED. `settled` means the request finished, which a
|
|
92
|
+
// refused one also did — publishing that emptied the store on every
|
|
93
|
+
// failed refetch and took the record the editor was showing with it.
|
|
94
|
+
if (list.settled && !list.error) publishItems();
|
|
92
95
|
}, [
|
|
93
96
|
list.items,
|
|
94
97
|
list.total,
|
|
95
|
-
list.settled
|
|
98
|
+
list.settled,
|
|
99
|
+
list.error
|
|
96
100
|
]);
|
|
97
101
|
useEffect(()=>{
|
|
98
102
|
publishLoading();
|
|
@@ -31,7 +31,8 @@ export function MappingsTab({ actions }) {
|
|
|
31
31
|
const [reloadToken, setReloadToken] = useState(0);
|
|
32
32
|
/** Set only when a new mapping is being started for a table named on arrival. */ const [pendingTarget, setPendingTarget] = useState('');
|
|
33
33
|
const sourceId = store.selectedSourceId ?? '';
|
|
34
|
-
const
|
|
34
|
+
const [pickableEndpoints, setPickableEndpoints] = useState([]);
|
|
35
|
+
const newMappingEndpointId = store.selectedEndpointId ?? pickableEndpoints[0]?.id ?? '';
|
|
35
36
|
const loadTargets = useEffectEvent(()=>{
|
|
36
37
|
setTargetsLoading(true);
|
|
37
38
|
actions.listTargets().then((result)=>{
|
|
@@ -53,21 +54,44 @@ export function MappingsTab({ actions }) {
|
|
|
53
54
|
* and a disabled New mapping — about a connection with three of them. The
|
|
54
55
|
* only way through was to visit the other tab first, which nothing said.
|
|
55
56
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
* Its OWN list, not the one the Endpoints step is showing.
|
|
58
|
+
*
|
|
59
|
+
* `store.endpoints` holds whatever that step last fetched — including what a
|
|
60
|
+
* SEARCH narrowed it to. A mapping reads one call, and the picker offering
|
|
61
|
+
* them was reading that same array: typing "employee" into the endpoints
|
|
62
|
+
* search left the mapping editor able to choose only the calls matching it,
|
|
63
|
+
* and `loadEndpointsIfMissing` then declined to fetch because the array was
|
|
64
|
+
* not empty. Nothing said the list was a filtered one.
|
|
65
|
+
*
|
|
66
|
+
* Read to exhaustion rather than one page: a picker that silently stops at
|
|
67
|
+
* fifty is the same defect one step down.
|
|
68
|
+
*/ const loadPickableEndpoints = useEffectEvent(()=>{
|
|
69
|
+
if (sourceId === '') {
|
|
70
|
+
setPickableEndpoints([]);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const PAGE = 200;
|
|
74
|
+
const MAX_PAGES = 20;
|
|
75
|
+
const read = (page, collected)=>{
|
|
76
|
+
actions.listEndpoints(sourceId, {
|
|
77
|
+
page,
|
|
78
|
+
limit: PAGE
|
|
79
|
+
}).then((result)=>{
|
|
80
|
+
const all = collected.concat(result.items);
|
|
81
|
+
const total = result.meta?.totalItems ?? all.length;
|
|
82
|
+
if (result.items.length === PAGE && all.length < total && page < MAX_PAGES) {
|
|
83
|
+
read(page + 1, all);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
setPickableEndpoints(all);
|
|
87
|
+
}).catch((error)=>{
|
|
88
|
+
store.setError(messageOf(error));
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
read(1, []);
|
|
68
92
|
});
|
|
69
93
|
useEffect(()=>{
|
|
70
|
-
|
|
94
|
+
loadPickableEndpoints();
|
|
71
95
|
}, [
|
|
72
96
|
sourceId
|
|
73
97
|
]);
|
|
@@ -245,7 +269,7 @@ export function MappingsTab({ actions }) {
|
|
|
245
269
|
className: theme.layout.main,
|
|
246
270
|
children: draft ? /*#__PURE__*/ _jsx(MappingEditor, {
|
|
247
271
|
deleting: deleting,
|
|
248
|
-
endpoints:
|
|
272
|
+
endpoints: pickableEndpoints,
|
|
249
273
|
freshSample: freshSample,
|
|
250
274
|
mapping: draft,
|
|
251
275
|
onCancel: closeEditor,
|
|
@@ -55,11 +55,15 @@ export function RunHistory({ actions, mappingId, refreshKey, onRefresh }) {
|
|
|
55
55
|
// reset empties the hook's items before the first page is asked for, and
|
|
56
56
|
// publishing that emptied the shared store.
|
|
57
57
|
useEffect(()=>{
|
|
58
|
-
|
|
58
|
+
// And not when it FAILED. `settled` means the request finished, which a
|
|
59
|
+
// refused one also did — publishing that emptied the store on every
|
|
60
|
+
// failed refetch and took the record the editor was showing with it.
|
|
61
|
+
if (list.settled && !list.error) publishRuns();
|
|
59
62
|
}, [
|
|
60
63
|
list.items,
|
|
61
64
|
list.total,
|
|
62
|
-
list.settled
|
|
65
|
+
list.settled,
|
|
66
|
+
list.error
|
|
63
67
|
]);
|
|
64
68
|
useEffect(()=>{
|
|
65
69
|
publishLoading();
|
|
@@ -44,13 +44,21 @@ export function RunPanel({ mapping, actions, onSubscribeProgress, onRunSettled }
|
|
|
44
44
|
const needsPassword = passwordIsNeeded(mapping);
|
|
45
45
|
const passwordReady = !needsPassword || sharedPassword.length >= MIN_SHARED_PASSWORD;
|
|
46
46
|
const activeRunId = store.activeRunId;
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Only a plan computed for THIS mapping.
|
|
49
|
+
*
|
|
50
|
+
* A preview reads a whole source, so it can land long after the operator has
|
|
51
|
+
* moved on — and it used to land under whatever was selected by then. The
|
|
52
|
+
* counts an operator reads before pressing Run must describe the mapping they
|
|
53
|
+
* are looking at.
|
|
54
|
+
*/ const plan = store.planMappingId === mapping.id ? store.plan : null;
|
|
48
55
|
const preview = ()=>{
|
|
56
|
+
const requestedFor = mapping.id;
|
|
49
57
|
store.setError(null);
|
|
50
58
|
store.setPlanning(true);
|
|
51
|
-
actions.previewRun(
|
|
59
|
+
actions.previewRun(requestedFor).then((result)=>{
|
|
52
60
|
if (result.error) store.setError(result.error);
|
|
53
|
-
store.setPlan(result.plan);
|
|
61
|
+
store.setPlan(result.plan, requestedFor);
|
|
54
62
|
}).catch((error)=>{
|
|
55
63
|
store.setPlanning(false);
|
|
56
64
|
store.setError(errorText(error, 'The preview could not be computed.'));
|
|
@@ -33,6 +33,10 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
33
33
|
store.sourcesLoading = loading;
|
|
34
34
|
},
|
|
35
35
|
selectSource: (store)=>(id)=>batch(()=>{
|
|
36
|
+
// Same rule as selectMapping: everything below discards what belonged to
|
|
37
|
+
// the previous connection, so re-choosing the current one would empty the
|
|
38
|
+
// step somebody is working in for no reason.
|
|
39
|
+
if (store.selectedSourceId === id) return;
|
|
36
40
|
store.selectedSourceId = id;
|
|
37
41
|
// Everything below a connection belongs to THAT connection. Leaving the
|
|
38
42
|
// previous one's endpoints on screen under a new name is worse than empty.
|
|
@@ -55,6 +59,7 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
55
59
|
store.sampleEndpointId = null;
|
|
56
60
|
store.sampling = false;
|
|
57
61
|
store.plan = null;
|
|
62
|
+
store.planMappingId = null;
|
|
58
63
|
store.planning = false;
|
|
59
64
|
store.activeRunId = null;
|
|
60
65
|
store.progress = null;
|
|
@@ -97,6 +102,9 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
97
102
|
store.endpointsLoading = loading;
|
|
98
103
|
},
|
|
99
104
|
selectEndpoint: (store)=>(id)=>batch(()=>{
|
|
105
|
+
// Re-choosing the call already open would throw away the sample just
|
|
106
|
+
// taken of it — and taking a sample is a real request to somebody's API.
|
|
107
|
+
if (store.selectedEndpointId === id) return;
|
|
100
108
|
store.selectedEndpointId = id;
|
|
101
109
|
// The sample describes ONE endpoint; carrying it over would offer the
|
|
102
110
|
// wrong field list to the next mapping.
|
|
@@ -150,6 +158,7 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
150
158
|
// A plan belongs to the mapping it was computed for. Showing it against a
|
|
151
159
|
// different one would have an operator approve counts from another import.
|
|
152
160
|
store.plan = null;
|
|
161
|
+
store.planMappingId = null;
|
|
153
162
|
// And the WAIT for a plan goes with it. Discarding the plan while leaving
|
|
154
163
|
// this set put the next mapping's panel on a counting skeleton for a
|
|
155
164
|
// preview that had been computed for a different mapping and thrown away.
|
|
@@ -177,8 +186,9 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
177
186
|
setSampling: (store)=>(sampling)=>{
|
|
178
187
|
store.sampling = sampling;
|
|
179
188
|
},
|
|
180
|
-
setPlan: (store)=>(plan)=>batch(()=>{
|
|
189
|
+
setPlan: (store)=>(plan, mappingId)=>batch(()=>{
|
|
181
190
|
store.plan = plan;
|
|
191
|
+
store.planMappingId = plan ? mappingId : null;
|
|
182
192
|
store.planning = false;
|
|
183
193
|
}),
|
|
184
194
|
setPlanning: (store)=>(planning)=>{
|
|
@@ -61,6 +61,17 @@ export type State = {
|
|
|
61
61
|
sampling: boolean;
|
|
62
62
|
/** What a run would do. Cleared whenever the mapping changes underneath it. */
|
|
63
63
|
plan: RunPlanValue | null;
|
|
64
|
+
/**
|
|
65
|
+
* The mapping the plan in hand was computed for.
|
|
66
|
+
*
|
|
67
|
+
* A preview reads a whole source and can take a while. Switching mapping
|
|
68
|
+
* while one is in flight used to land the answer under whatever was selected
|
|
69
|
+
* when it arrived — so an operator read "880 to create, 3 to skip" about a
|
|
70
|
+
* mapping that had never been previewed, and pressing Run beside it started
|
|
71
|
+
* an import against those numbers. Same shape as the endpoint sample, and the
|
|
72
|
+
* same fix: the answer is tagged, and only its own mapping reads it.
|
|
73
|
+
*/
|
|
74
|
+
planMappingId: string | null;
|
|
64
75
|
planning: boolean;
|
|
65
76
|
/** Live progress of the run this panel started. */
|
|
66
77
|
progress: RunProgressValue | null;
|
|
@@ -129,7 +140,7 @@ export type Actions = {
|
|
|
129
140
|
setRunsLoading: (loading: boolean) => void;
|
|
130
141
|
setSample: (sample: EndpointSampleValue | null, endpointId: string | null) => void;
|
|
131
142
|
setSampling: (sampling: boolean) => void;
|
|
132
|
-
setPlan: (plan: RunPlanValue | null) => void;
|
|
143
|
+
setPlan: (plan: RunPlanValue | null, mappingId: string | null) => void;
|
|
133
144
|
setPlanning: (planning: boolean) => void;
|
|
134
145
|
setProgress: (progress: RunProgressValue | null) => void;
|
|
135
146
|
setActiveRun: (runId: string | null) => void;
|