nucleus-core-ts 0.9.816 → 0.9.818
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/IntegrationsPage.d.ts +1 -1
- package/dist/fe/components/IntegrationsPage/components/IntegrationsPage.js +4 -3
- package/dist/fe/components/IntegrationsPage/components/MappingEditor.d.ts +15 -1
- package/dist/fe/components/IntegrationsPage/components/MappingEditor.js +8 -1
- package/dist/fe/components/IntegrationsPage/components/MappingsTab.js +26 -1
- package/dist/fe/components/IntegrationsPage/store/index.js +2 -1
- package/dist/fe/components/IntegrationsPage/store/state.d.ts +3 -1
- package/dist/fe/components/IntegrationsPage/store/state.js +1 -0
- package/dist/fe/components/IntegrationsPage/types/actions.d.ts +8 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { IntegrationsPageProps } from '../types';
|
|
2
|
-
export declare function IntegrationsPage({ title, subtitle, className, actions, labels: labelsOverride, focusTargetEntity, onSubscribeProgress, }: IntegrationsPageProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function IntegrationsPage({ title, subtitle, className, actions, labels: labelsOverride, focusTargetEntity, focusStep, onSubscribeProgress, }: IntegrationsPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -25,7 +25,7 @@ import { RunsTab } from './RunsTab';
|
|
|
25
25
|
* page from the server rather than being handed a list to slice.
|
|
26
26
|
*/ gsap.registerPlugin(useGSAP);
|
|
27
27
|
const theme = integrationsPageTheme;
|
|
28
|
-
export function IntegrationsPage({ title = 'Integrations', subtitle = 'Connect an external service, describe the data you want and import it on your terms.', className, actions, labels: labelsOverride, focusTargetEntity, onSubscribeProgress }) {
|
|
28
|
+
export function IntegrationsPage({ title = 'Integrations', subtitle = 'Connect an external service, describe the data you want and import it on your terms.', className, actions, labels: labelsOverride, focusTargetEntity, focusStep, onSubscribeProgress }) {
|
|
29
29
|
const store = useIntegrationsStore();
|
|
30
30
|
// Resolved here rather than read from the context, because this component is
|
|
31
31
|
// the one that PROVIDES it — and passed down so a control four levels deep
|
|
@@ -92,12 +92,13 @@ export function IntegrationsPage({ title = 'Integrations', subtitle = 'Connect a
|
|
|
92
92
|
* is chosen for them. With several, the choice is real and stays theirs.
|
|
93
93
|
*/ const takeFocus = useEffectEvent(()=>{
|
|
94
94
|
if (!focusTargetEntity) return;
|
|
95
|
-
store.setFocusTargetEntity(focusTargetEntity);
|
|
95
|
+
store.setFocusTargetEntity(focusTargetEntity, focusStep ?? 'mapping');
|
|
96
96
|
});
|
|
97
97
|
useEffect(()=>{
|
|
98
98
|
takeFocus();
|
|
99
99
|
}, [
|
|
100
|
-
focusTargetEntity
|
|
100
|
+
focusTargetEntity,
|
|
101
|
+
focusStep
|
|
101
102
|
]);
|
|
102
103
|
const followFocus = useEffectEvent(()=>{
|
|
103
104
|
if (!store.focusTargetEntity) return;
|
|
@@ -26,5 +26,19 @@ export type MappingEditorProps = {
|
|
|
26
26
|
onSave: (draft: MappingDraft) => void;
|
|
27
27
|
onDelete: (id: string) => void;
|
|
28
28
|
onCancel: () => void;
|
|
29
|
+
/**
|
|
30
|
+
* Go and import with this mapping.
|
|
31
|
+
*
|
|
32
|
+
* The import lives on its own step, and it should: it is the destructive one,
|
|
33
|
+
* and it wants the whole width for a preview. But somebody who has just
|
|
34
|
+
* finished describing a mapping wants to RUN it, and leaving them to find the
|
|
35
|
+
* step themselves is the panel forgetting what they were doing. Absent for an
|
|
36
|
+
* unsaved mapping, because there is nothing to run yet.
|
|
37
|
+
*
|
|
38
|
+
* The DRAFT is handed over, not the id: what is on screen is what the operator
|
|
39
|
+
* means to run, so edits they have not saved yet are saved on the way rather
|
|
40
|
+
* than quietly ignored by an import of the older version.
|
|
41
|
+
*/
|
|
42
|
+
onRunImport?: (draft: MappingDraft) => void;
|
|
29
43
|
};
|
|
30
|
-
export declare function MappingEditor({ mapping, targets, targetsLoading, endpoints, freshSample, saving, deleting, onSave, onDelete, onCancel, }: MappingEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
44
|
+
export declare function MappingEditor({ mapping, targets, targetsLoading, endpoints, freshSample, saving, deleting, onSave, onDelete, onCancel, onRunImport, }: MappingEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -21,7 +21,7 @@ import { CardSkeleton } from './Skeletons';
|
|
|
21
21
|
* Mount it with a `key` of the mapping id so switching rows starts a fresh
|
|
22
22
|
* draft instead of pouring one mapping's edits into another.
|
|
23
23
|
*/ const theme = integrationsPageTheme;
|
|
24
|
-
export function MappingEditor({ mapping, targets, targetsLoading, endpoints, freshSample, saving, deleting, onSave, onDelete, onCancel }) {
|
|
24
|
+
export function MappingEditor({ mapping, targets, targetsLoading, endpoints, freshSample, saving, deleting, onSave, onDelete, onCancel, onRunImport }) {
|
|
25
25
|
const labels = useLabels();
|
|
26
26
|
const uid = useId();
|
|
27
27
|
const [draft, setDraft] = useState(mapping);
|
|
@@ -236,6 +236,13 @@ export function MappingEditor({ mapping, targets, targetsLoading, endpoints, fre
|
|
|
236
236
|
type: "button",
|
|
237
237
|
children: "Cancel"
|
|
238
238
|
}),
|
|
239
|
+
draft.id && onRunImport ? /*#__PURE__*/ _jsx("button", {
|
|
240
|
+
className: theme.button.secondary,
|
|
241
|
+
disabled: busy,
|
|
242
|
+
onClick: ()=>onRunImport(draft),
|
|
243
|
+
type: "button",
|
|
244
|
+
children: "Preview and import"
|
|
245
|
+
}) : null,
|
|
239
246
|
/*#__PURE__*/ _jsx("button", {
|
|
240
247
|
className: theme.button.primary,
|
|
241
248
|
disabled: busy || issues.length > 0,
|
|
@@ -95,6 +95,7 @@ export function MappingsTab({ actions }) {
|
|
|
95
95
|
*/ const followFocus = useEffectEvent(()=>{
|
|
96
96
|
const entity = store.focusTargetEntity;
|
|
97
97
|
if (!entity || sourceId === '') return;
|
|
98
|
+
const step = store.focusStep;
|
|
98
99
|
store.setFocusTargetEntity(null);
|
|
99
100
|
actions.listMappings(sourceId, {
|
|
100
101
|
page: 1,
|
|
@@ -110,6 +111,9 @@ export function MappingsTab({ actions }) {
|
|
|
110
111
|
const found = result.items[0];
|
|
111
112
|
if (found) {
|
|
112
113
|
openMapping(found);
|
|
114
|
+
// "Fill this table now" is a different errand from "describe how it is
|
|
115
|
+
// filled", and both are offered from the table itself.
|
|
116
|
+
if (step === 'import') store.setTab('runs');
|
|
113
117
|
return;
|
|
114
118
|
}
|
|
115
119
|
setSelected(null);
|
|
@@ -132,7 +136,7 @@ export function MappingsTab({ actions }) {
|
|
|
132
136
|
setSelected(null);
|
|
133
137
|
store.selectMapping(null);
|
|
134
138
|
};
|
|
135
|
-
const save = (draft)=>{
|
|
139
|
+
const save = (draft, then)=>{
|
|
136
140
|
setSaving(true);
|
|
137
141
|
store.setError(null);
|
|
138
142
|
actions.saveMapping(draft).then((saved)=>{
|
|
@@ -142,11 +146,31 @@ export function MappingsTab({ actions }) {
|
|
|
142
146
|
setSelected(saved);
|
|
143
147
|
store.selectMapping(saved.id);
|
|
144
148
|
setReloadToken((token)=>token + 1);
|
|
149
|
+
then?.(saved);
|
|
145
150
|
}).catch((error)=>{
|
|
146
151
|
setSaving(false);
|
|
147
152
|
store.setError(messageOf(error));
|
|
148
153
|
});
|
|
149
154
|
};
|
|
155
|
+
/**
|
|
156
|
+
* Take this mapping to the import step.
|
|
157
|
+
*
|
|
158
|
+
* Saved first when it differs from what is stored: the operator is looking at
|
|
159
|
+
* the version they mean to run, and importing the older one instead — with no
|
|
160
|
+
* sign that it happened — is the worst kind of quiet.
|
|
161
|
+
*/ const runImport = (draft)=>{
|
|
162
|
+
const stored = selected ? toMappingDraft(selected) : null;
|
|
163
|
+
const dirty = !stored || JSON.stringify(stored) !== JSON.stringify(draft);
|
|
164
|
+
const go = (id)=>{
|
|
165
|
+
store.selectMapping(id);
|
|
166
|
+
store.setTab('runs');
|
|
167
|
+
};
|
|
168
|
+
if (!dirty && draft.id) {
|
|
169
|
+
go(draft.id);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
save(draft, (saved)=>go(saved.id));
|
|
173
|
+
};
|
|
150
174
|
const remove = (id)=>{
|
|
151
175
|
if (id === '') return;
|
|
152
176
|
setDeleting(true);
|
|
@@ -213,6 +237,7 @@ export function MappingsTab({ actions }) {
|
|
|
213
237
|
mapping: draft,
|
|
214
238
|
onCancel: closeEditor,
|
|
215
239
|
onDelete: remove,
|
|
240
|
+
onRunImport: runImport,
|
|
216
241
|
onSave: save,
|
|
217
242
|
saving: saving,
|
|
218
243
|
targets: targets,
|
|
@@ -41,8 +41,9 @@ export const { useStore: useIntegrationsStore } = createStore(initial, {
|
|
|
41
41
|
store.plan = null;
|
|
42
42
|
store.error = null;
|
|
43
43
|
}),
|
|
44
|
-
setFocusTargetEntity: (store)=>(entity)=>{
|
|
44
|
+
setFocusTargetEntity: (store)=>(entity, step)=>{
|
|
45
45
|
store.focusTargetEntity = entity;
|
|
46
|
+
if (step) store.focusStep = step;
|
|
46
47
|
},
|
|
47
48
|
setTab: (store)=>(tab)=>{
|
|
48
49
|
store.tab = tab;
|
|
@@ -29,6 +29,8 @@ export type State = {
|
|
|
29
29
|
* later click on another mapping is not dragged back.
|
|
30
30
|
*/
|
|
31
31
|
focusTargetEntity: string | null;
|
|
32
|
+
/** Whether that caller wanted to DESCRIBE the import or RUN it. */
|
|
33
|
+
focusStep: 'mapping' | 'import';
|
|
32
34
|
endpoints: IntegrationEndpoint[];
|
|
33
35
|
endpointsTotal: number;
|
|
34
36
|
endpointsPage: number;
|
|
@@ -65,7 +67,7 @@ export type Actions = {
|
|
|
65
67
|
setSourcesLoading: (loading: boolean) => void;
|
|
66
68
|
selectSource: (id: string | null) => void;
|
|
67
69
|
setTab: (tab: ConnectionTab) => void;
|
|
68
|
-
setFocusTargetEntity: (entity: string | null) => void;
|
|
70
|
+
setFocusTargetEntity: (entity: string | null, step?: 'mapping' | 'import') => void;
|
|
69
71
|
setEndpoints: (items: IntegrationEndpoint[], total: number) => void;
|
|
70
72
|
/**
|
|
71
73
|
* Just the count, without the rows.
|
|
@@ -106,6 +106,14 @@ export type IntegrationsPageProps = {
|
|
|
106
106
|
* it — instead of on a chooser the caller has already answered.
|
|
107
107
|
*/
|
|
108
108
|
focusTargetEntity?: string;
|
|
109
|
+
/**
|
|
110
|
+
* What they came to do with it.
|
|
111
|
+
*
|
|
112
|
+
* "Describe how this table is filled" and "fill it now" are two different
|
|
113
|
+
* errands, and a management screen offers both. Landing on the wrong one
|
|
114
|
+
* means finding the right step by hand — which is what the button was for.
|
|
115
|
+
*/
|
|
116
|
+
focusStep?: 'mapping' | 'import';
|
|
109
117
|
/**
|
|
110
118
|
* The panel's own words, in the app's language.
|
|
111
119
|
*
|