@nice2dev/ui-bi 1.1.9 → 1.2.0
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/CHANGELOG.md +139 -0
- package/dist/NiceETLBuilder.d.ts +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +756 -2
- package/dist/types.d.ts +3 -5
- package/dist/ui-bi.css +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,144 @@
|
|
|
1
1
|
# @nice2dev/ui-bi
|
|
2
2
|
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3a4939d: 1.2.0 — the API cleanup announced for this version, dictionaries per language by default, and
|
|
8
|
+
three new controls. **Breaking:** every removal has a replacement, listed name by name in
|
|
9
|
+
`documentation/omniverk/OMNIVERK_UPGRADE_1.2.0.md`.
|
|
10
|
+
|
|
11
|
+
**Removed (breaking).** All 118 `@deprecated` names: the aliases without the `Nice` prefix in
|
|
12
|
+
`ui-audio`, `ui-graphics` and `ui-3d`; `NiceBarcodeGenerator` (→ `NiceBarcode`), `NiceFloorPlanCanvas`
|
|
13
|
+
(→ `NiceSpatialEditor` in `@nice2dev/ui-buildings`), the v2 props and types of `NiceTopNav`,
|
|
14
|
+
`NiceProgress.showLabel`, `NiceCountryPicker.showDialCode` / `showFlag`, `type` on
|
|
15
|
+
`NiceDateTimePicker` / `NiceDateRangeBox` (→ `dateFormatPreset`); `ZoneOccupancy` in
|
|
16
|
+
`ui-buildings` and `events`, the `SmartHome*` types; the icon variant `flat` (→ `cutout`) and
|
|
17
|
+
`NiceIconEditor` (→ `NiceVectorEditor`); `NiceSizeLegacy`; the `snapGrid` module of `ui-diagrams` (→
|
|
18
|
+
`@nice2dev/spatial-core`); the opt-in stylesheet `@nice2dev/ui/css/legacy-bg-text-aliases.css`, which
|
|
19
|
+
formed an alias cycle with `style.css`. Props that were accepted and never read — 19 on
|
|
20
|
+
`NiceModuleGrid`, and more on `NiceAutocomplete`, `NiceTaskInbox`, `NiceConsentBanner`, the
|
|
21
|
+
building and communication controls, four `ui-audio` panels and `NiceStreamDashboard` — are gone
|
|
22
|
+
from the types. `NiceResourceAllocation` in `ui-erp` is `NiceCapacityPlanner` (the one in `ui`
|
|
23
|
+
keeps its name); `NiceGenericPlayerStageVisualizer` (→ `NiceStageVisualizer`) and
|
|
24
|
+
`NiceCubeBrowserProps` are removed. The `@nice2dev/ui/overlays` entry calls its modal, drawer,
|
|
25
|
+
bottom sheet and context menu `NiceOverlayModal`, `NiceOverlayDrawer`, `NiceOverlayBottomSheet` and
|
|
26
|
+
`NiceOverlayContextMenu`: the old names belonged to different components of `@nice2dev/ui`.
|
|
27
|
+
|
|
28
|
+
**Dictionaries per language.** `NiceI18nProvider` loads only the language in use, with `import()`
|
|
29
|
+
(it was `NiceI18nLazyProvider` in 1.1.10, which stays as the same component); the controls show their
|
|
30
|
+
built-in English until it arrives — `await loadNiceDictionary(lang)` before the first render to start
|
|
31
|
+
in the language. Nothing on the main entry of `@nice2dev/i18n` imports a dictionary any more:
|
|
32
|
+
`NICE_I18N_DICTIONARIES`, `createTranslator`, `NICE_I18N_VARIANTS` / `resolvePlVariant` and the
|
|
33
|
+
translation tooling moved to the new entry `@nice2dev/i18n/all`, and `@nice2dev/ui-core` no longer
|
|
34
|
+
re-exports the dictionary map. `@nice2dev/ui` with what it bundles: 1283 kB → 952 kB gzip loaded up
|
|
35
|
+
front. The `ui-audio` controls read the app's `NiceI18nProvider` now; their own provider overrides it.
|
|
36
|
+
|
|
37
|
+
**New controls.** `NiceRecurrenceEditor`, `NiceStopwatch`, `NiceCountdownTimer` (`@nice2dev/ui`) and
|
|
38
|
+
`NicePasswordGenerator` (`@nice2dev/auth`), plus `recurrenceDates()` and `generatePassword()`.
|
|
39
|
+
`NiceScheduler` honours a weekly rule's `byDay`, which it ignored.
|
|
40
|
+
|
|
41
|
+
**Visible changes.** The palette meets WCAG AA for text on every fill: darker fills in the light
|
|
42
|
+
theme, dark text on the fills of the dark theme (new `--nice-text-on-success` / `-error` / `-info` /
|
|
43
|
+
`-accent` / `-warning`; `NiceThemeText` takes `onSuccess`, `onError`, `onInfo`, `onWarning`). Mobile
|
|
44
|
+
and platform panels follow the app theme instead of `prefers-color-scheme`. Swipes in
|
|
45
|
+
`NiceSwipeActions`, `NiceTouchTable` and `NiceMobileCalendar` work with a mouse and a pen. The
|
|
46
|
+
`ui-forms` editors have the intended spacing (it was four times too large). `NiceMAM`,
|
|
47
|
+
`NiceTranscoder`, `NiceVideoAnnotator` and `NiceStreamDashboard` use `nice-`-prefixed BEM classes.
|
|
48
|
+
|
|
49
|
+
**Fixes.** Controls that invented results ask the host instead: `NiceIntegrationHub`,
|
|
50
|
+
`NiceMLStudio` (`onExperimentRun` may return metrics), `NiceRemoteManagement`
|
|
51
|
+
(`onCaptureScreenshot`), `NicePoseDetector` (`detector`), `NiceBatchScannerProvider`,
|
|
52
|
+
`NiceCacheStrategies`; `NiceLowCodeStudio` accepts dropped components. Controls that did nothing
|
|
53
|
+
work or say why they are off: `NiceStreamDashboard` adds sources, sends chat and runs the chosen
|
|
54
|
+
transition (new `onAddPlatform`, `onSendChatMessage`, `onTransition`, `onScreenshot`,
|
|
55
|
+
`onOpenAudioMixer`, `onOpenSettings`; `receiveChatMessage` feeds incoming chat), `NiceMLStudio`
|
|
56
|
+
downloads through `onModelDownload`, `NiceETLBuilder` saves through `onSave` (its Save button had
|
|
57
|
+
no handler), `NiceTranscoder` makes jobs of picked and dropped files, `NiceAutomationEditor` offers
|
|
58
|
+
the trigger types its model has. Texts of about fifty components go
|
|
59
|
+
through `t()` in six languages, among them the AI data grid, chart and form builders, the ML
|
|
60
|
+
studio, the report designer, the song picker, `NiceProtocolConfig`, `NiceETLBuilder` and
|
|
61
|
+
`NiceInlineHelp` — every key the controls pass to `t()` now has a dictionary entry, so none of
|
|
62
|
+
them stays English under another language; `NiceDataGridAI` sorts on a query in any language, not
|
|
63
|
+
only in English. `NiceWindow`, `NiceConsole`, `NiceFileManager` and `NiceGitManager` no longer
|
|
64
|
+
crash when `accessMode` switches to or from `'hidden'`. Ids come from `createId()` (`@nice2dev/ui-core`), so nothing throws
|
|
65
|
+
outside a secure context as `crypto.randomUUID()` did on plain http. `ui-3d` runs on three r183
|
|
66
|
+
without its deprecation warnings. `NiceRemoteManagement` calls the handlers of the latest render.
|
|
67
|
+
The AI hint popover and the `ui-platform` panels follow the app theme, not the system's or a
|
|
68
|
+
`.dark` class on the host. `NiceCommandPalette` has styles and its search filters;
|
|
69
|
+
`NiceTimeoutFeedback` starts its clock; `NiceOfflineBanner` takes `online`; Monaco's workers in
|
|
70
|
+
`NiceCodeEditor` load; the `ui-audio` panels that used Bootstrap classes use Nice controls; colours
|
|
71
|
+
that reached a canvas as `var(…)` (karaoke lanes and notes) are resolved first.
|
|
72
|
+
|
|
73
|
+
## 1.1.10
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- The package description on npm shows a dash instead of the mis-encoded "—".
|
|
78
|
+
- 1.1.10 — the additive part of OmniVerk's 1.2.0 list: ui-audio builds without optional packages, one
|
|
79
|
+
i18n context, dictionaries per language, data props optional. No breaking changes.
|
|
80
|
+
|
|
81
|
+
**`@nice2dev/ui-audio` no longer breaks the consumer's build.** It imported `react-bootstrap`,
|
|
82
|
+
`recharts`, `react-window`, `react-youtube` and `pitchy` statically while declaring none of them
|
|
83
|
+
(only optional entries in `peerDependenciesMeta`), so a Vite app without them failed with "failed to
|
|
84
|
+
resolve import". Loading them with `import()` is no way out: Vite 8 (Rolldown) resolves dynamic
|
|
85
|
+
imports at build time and fails the same way, which made `hls.js` and `phaser` mandatory too.
|
|
86
|
+
`react-bootstrap`, `recharts`, `react-window` and `phaser` are now gone from the code
|
|
87
|
+
(`NiceBarFillEditor` uses Nice controls, `NiceVocalPerformanceReport` uses `NiceChart` /
|
|
88
|
+
`NicePieChart`, the karaoke editor list uses `NiceVirtualScroller`, `NiceKaraokePhaserRenderer`
|
|
89
|
+
renders with the DOM and keeps its name); `pitchy`, `react-youtube` and `hls.js` are regular
|
|
90
|
+
`dependencies`. Found on the way: in live mode the vocal performance report subtracted UltraStar note
|
|
91
|
+
numbers from MIDI pitch, so every singer got thousands of cents of deviation and 0 % accuracy — it now
|
|
92
|
+
compares pitch within the octave, as the scoring does; `NiceBarFillEditor` put a colour into a
|
|
93
|
+
percentage slider.
|
|
94
|
+
|
|
95
|
+
**Every package declares what its bundle imports.** A new CI gate checks every `import`, `import()`
|
|
96
|
+
and `require()` in the published `dist` against `dependencies` and non-optional `peerDependencies`.
|
|
97
|
+
To reach zero: `@nice2dev/licensing` no longer has `require('webpack')` in its main bundle (the webpack
|
|
98
|
+
plugin uses `compiler.webpack`; webpack 4 gets a warning instead of feature flags) and `react` is a
|
|
99
|
+
required peer; `@nice2dev/erp-adapter` lists `@microsoft/signalr` in `dependencies` (still loaded on
|
|
100
|
+
first use); `@nice2dev/icons-cursor` declares its `react-dom` peer; `@nice2dev/ui-printing` treats
|
|
101
|
+
`@nice2dev/ui` as a required peer.
|
|
102
|
+
|
|
103
|
+
**One copy of each package, one i18n context.** `@nice2dev/ui` carried its own copy of
|
|
104
|
+
`@nice2dev/ui-core` and `@nice2dev/i18n`, and `ui-forms`, `ui-api`, `ui-bi`, `ui-designers`, `ui-math`
|
|
105
|
+
and `ui-video` each carried a copy of all of `@nice2dev/ui` (about 4.4 MB each). Every copy had its own
|
|
106
|
+
React contexts: a `NiceI18nProvider` imported from `@nice2dev/i18n` did not reach the controls of
|
|
107
|
+
`@nice2dev/ui`, which kept their English defaults and `lang` `'en'`, and the dictionaries ended up in
|
|
108
|
+
an app several times. These packages now import `@nice2dev/*` instead (`ui-forms` 4.4 MB → 82 kB).
|
|
109
|
+
Keep every `@nice2dev/*` package on the same version.
|
|
110
|
+
|
|
111
|
+
**Dictionaries per language.** `NiceI18nLazyProvider` takes the same props as `NiceI18nProvider`
|
|
112
|
+
(`t`, `lang`, `overrides`, plus `fallback` and `onError`) but loads only the active language's
|
|
113
|
+
dictionary, with `import()`; until it arrives the controls show their built-in English (or
|
|
114
|
+
`fallback`), and with `t` nothing is loaded at all. Also `loadNiceDictionary(lang)`, to start in a
|
|
115
|
+
language without a flash of English, and `getLoadedNiceDictionary(lang)`. Exported from
|
|
116
|
+
`@nice2dev/i18n`, `@nice2dev/ui-core` and `@nice2dev/ui`; in the `i18n` build every language is its own
|
|
117
|
+
file. `NiceI18nProvider` and `NICE_I18N_DICTIONARIES` are unchanged and still bring all 30 dictionaries.
|
|
118
|
+
`NiceTestWrapper` (ui-core) and `NiceShowcase` (ui) use the lazy provider now, so they no longer pull
|
|
119
|
+
every dictionary into the apps that bundle them.
|
|
120
|
+
|
|
121
|
+
**Data props are optional.** These controls threw a `TypeError` without data and now render empty:
|
|
122
|
+
`NiceTreeView.nodes`, `NiceAccordion.items`, `NiceCascadeSelect.options`, `NiceAutocomplete.options`,
|
|
123
|
+
`NiceAuditLog.entries`, `NiceDocumentVersionList.versions`, `NicePermissionMatrix.roles` / `actions`,
|
|
124
|
+
`WizardStep.content`, `NiceDiagramViewer.document`, `NiceOrgChartVisualizer.data`,
|
|
125
|
+
`NiceSpatialViewer.document`, and in `@nice2dev/events` the lists of `NiceGiftRegistry`,
|
|
126
|
+
`NiceParticipantList`, `NiceExpenseSplit`, `NiceSeatingChart`, `NiceMediaCollage` and `NiceEventMedia`.
|
|
127
|
+
`NiceMap` without `center` centres on its markers (the whole world without markers), `NiceCountdown`
|
|
128
|
+
without `targetDate` shows zero and never calls `onComplete`, `NiceChat` without `onSend` is read-only
|
|
129
|
+
(no input), and `NiceInvitationDesigner` gains `defaultTemplate`. A CI ratchet counts the required
|
|
130
|
+
array props that remain.
|
|
131
|
+
|
|
132
|
+
**Smaller fixes.** `NicePieChart` draws a 100 % slice as a full circle instead of nothing. In
|
|
133
|
+
development `NiceThemeProvider` warns when `--nice-primary` / `--nice-color-primary` (or another linked
|
|
134
|
+
pair) resolves to nothing on `:root` — usually an alias cycle in the app's CSS; the theming guides say
|
|
135
|
+
which side to set. `@nice2dev/game-engine` exports `createAnimationClip`, `AnimatorController` and
|
|
136
|
+
`createAnimatorController` (two modules exported each name, so `export *` dropped all three); the other
|
|
137
|
+
implementations are `StateMachineAnimatorController`, `createStateMachineAnimatorController`,
|
|
138
|
+
`createTimelineAnimationClip` and `createRetargetingAnimationClip`.
|
|
139
|
+
|
|
140
|
+
Nothing was renamed or removed.
|
|
141
|
+
|
|
3
142
|
## 1.1.9
|
|
4
143
|
|
|
5
144
|
### Patch Changes
|
package/dist/NiceETLBuilder.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ import { NiceETLBuilderProps } from './types';
|
|
|
3
3
|
/**
|
|
4
4
|
* NiceETLBuilder - Visual ETL Pipeline Builder
|
|
5
5
|
*/
|
|
6
|
-
export declare function NiceETLBuilder({ pipeline: initialPipeline, dataSources, onChange, onRun, onSchedule, className, tutorial, }: NiceETLBuilderProps): React.ReactElement;
|
|
6
|
+
export declare function NiceETLBuilder({ pipeline: initialPipeline, dataSources, onChange, onRun, onSchedule, onSave, className, tutorial, }: NiceETLBuilderProps): React.ReactElement;
|
|
7
7
|
export default NiceETLBuilder;
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),g=require("@nice2dev/ui"),f=require("@nice2dev/ui-core"),m=require("react"),q=[{target:".nice-etl-builder",titleKey:"tutorial.etlBuilder.intro.title",title:"ETL builder",contentKey:"tutorial.etlBuilder.intro.content",content:"Wire sources → transformations → destinations into a pipeline, switch the views, then run it and save the configuration.",placement:"auto"}],K={id:"",name:"New Pipeline",sources:[],transformations:[],destinations:[],version:1},E=o=>/^[a-z][a-z0-9-]*$/.test(o)?e.jsx(g.NiceIcon,{name:o,size:16}):o,w=[{type:"filter",key:"etlBuilder.transform.filter",label:"Filter",icon:"filter"},{type:"map",key:"etlBuilder.transform.map",label:"Map",icon:"shuffle"},{type:"aggregate",key:"etlBuilder.transform.aggregate",label:"Aggregate",icon:"∑"},{type:"join",key:"etlBuilder.transform.join",label:"Join",icon:"link"},{type:"union",key:"etlBuilder.transform.union",label:"Union",icon:"∪"},{type:"sort",key:"etlBuilder.transform.sort",label:"Sort",icon:"sort"},{type:"deduplicate",key:"etlBuilder.transform.deduplicate",label:"Deduplicate",icon:"copy"},{type:"pivot",key:"etlBuilder.transform.pivot",label:"Pivot",icon:"expand"},{type:"unpivot",key:"etlBuilder.transform.unpivot",label:"Unpivot",icon:"collapse"},{type:"split",key:"etlBuilder.transform.split",label:"Split",icon:"scissors"},{type:"merge",key:"etlBuilder.transform.merge",label:"Merge",icon:"git-branch"},{type:"lookup",key:"etlBuilder.transform.lookup",label:"Lookup",icon:"book"},{type:"derive",key:"etlBuilder.transform.derive",label:"Derive Column",icon:"plus"},{type:"validate",key:"etlBuilder.transform.validate",label:"Validate",icon:"check"},{type:"cleanse",key:"etlBuilder.transform.cleanse",label:"Cleanse",icon:"wand"},{type:"custom",key:"etlBuilder.transform.custom",label:"Custom",icon:"ƒ"}];function V({pipeline:o,dataSources:l=[],onChange:d,onRun:t,onSchedule:h,onSave:n,className:j="",tutorial:a}){const{t:c}=f.useNiceTranslation(),[p,I]=m.useState(()=>o||{...K,id:f.createId(),name:c("etlBuilder.newPipeline","New Pipeline")}),[u,_]=m.useState(null),[v,L]=m.useState("design"),[B,T]=m.useState(!1),[P,A]=m.useState([]),[y,N]=m.useState(null),F=m.useRef(null),b=m.useCallback(i=>{I(s=>{const r=i(s);return d==null||d(r),r})},[d]),S=m.useCallback(i=>{var r;const s={id:f.createId(),type:i.type,name:i.name,config:i.config,schema:(r=i.schema)==null?void 0:r.tables[0]};b(x=>({...x,sources:[...x.sources,s]}))},[b]),D=m.useCallback((i,s)=>{const r={id:f.createId(),type:i,name:(()=>{const x=w.find(H=>H.type===i);return x?c(x.key,x.label):i})(),input:[],output:f.createId(),config:Y(i)};b(x=>({...x,transformations:[...x.transformations,r]})),_({type:"transformation",id:r.id})},[b,c]),z=m.useCallback(()=>{const i={id:f.createId(),type:"database",name:c("etlBuilder.newDestination","New Destination"),config:{},writeMode:"append"};b(s=>({...s,destinations:[...s.destinations,i]})),_({type:"destination",id:i.id})},[b,c]),k=m.useCallback((i,s)=>{b(r=>{switch(i){case"source":return{...r,sources:r.sources.filter(x=>x.id!==s)};case"transformation":return{...r,transformations:r.transformations.filter(x=>x.id!==s)};case"destination":return{...r,destinations:r.destinations.filter(x=>x.id!==s)};default:return r}}),_(null)},[b]),R=m.useCallback(async()=>{if(t){T(!0);try{const i=await t(p);A(s=>[i,...s].slice(0,50))}finally{T(!1)}}},[p,t]),U=m.useCallback(i=>{b(s=>({...s,schedule:i})),h==null||h(p,i)},[p,b,h]),M=m.useCallback(i=>{if(i.preventDefault(),!!y){if(y.startsWith("transform:")){const s=y.replace("transform:","");D(s)}N(null)}},[y,D]),$=()=>{if(!u)return null;switch(u.type){case"source":return p.sources.find(i=>i.id===u.id);case"transformation":return p.transformations.find(i=>i.id===u.id);case"destination":return p.destinations.find(i=>i.id===u.id);default:return null}},O=v==="design"?e.jsxs("div",{className:"nice-etl-builder__palette",children:[e.jsx("h4",{children:c("etlBuilder.sources","Sources")}),l.map(i=>e.jsxs("div",{className:"nice-etl-builder__palette-item",onClick:()=>S(i),children:[e.jsx("span",{className:"nice-etl-builder__palette-icon",children:e.jsx(g.NiceIcon,{name:"database",size:14})}),e.jsx("span",{children:i.name})]},i.id)),e.jsxs("button",{onClick:()=>S({id:"",name:c("etlBuilder.newSource","New Source"),type:"database",config:{}}),children:[e.jsx(g.NiceIcon,{name:"plus",size:14})," ",c("etlBuilder.addSource","Add Source")]}),e.jsx("h4",{children:c("etlBuilder.transformations","Transformations")}),w.map(i=>e.jsxs("div",{className:"nice-etl-builder__palette-item",draggable:!0,onDragStart:()=>N(`transform:${i.type}`),onDragEnd:()=>N(null),children:[e.jsx("span",{className:"nice-etl-builder__palette-icon",children:E(i.icon)}),e.jsx("span",{children:c(i.key,i.label)})]},i.type)),e.jsx("h4",{children:c("etlBuilder.destinations","Destinations")}),e.jsxs("button",{onClick:z,children:[e.jsx(g.NiceIcon,{name:"plus",size:14})," ",c("etlBuilder.addDestination","Add Destination")]})]}):void 0,W=u&&v==="design"?e.jsx(J,{nodeType:u.type,node:$()??null,dataSources:l,onChange:i=>{b(s=>{switch(u.type){case"source":return{...s,sources:s.sources.map(r=>r.id===u.id?{...r,...i}:r)};case"transformation":return{...s,transformations:s.transformations.map(r=>r.id===u.id?{...r,...i}:r)};case"destination":return{...s,destinations:s.destinations.map(r=>r.id===u.id?{...r,...i}:r)};default:return s}})},onClose:()=>_(null)}):void 0;return e.jsxs(g.NiceAppShell,{flush:!0,className:`nice-etl-builder ${j}`,height:"100%",style:{minHeight:600},sidebar:O,rightSidebar:W,toolbar:e.jsxs("div",{className:"nice-etl-builder__toolbar",children:[e.jsx("input",{type:"text",value:p.name,onChange:i=>b(s=>({...s,name:i.target.value})),className:"nice-etl-builder__name-input"}),e.jsx("div",{className:"nice-etl-builder__tabs",children:["design","code","schedule","history"].map(i=>e.jsx("button",{className:`nice-etl-builder__tab ${v===i?"nice-etl-builder__tab--active":""}`,onClick:()=>L(i),children:c(`etlBuilder.tab.${i}`,i.charAt(0).toUpperCase()+i.slice(1))},i))}),e.jsxs("div",{className:"nice-etl-builder__actions",children:[e.jsxs("button",{onClick:R,disabled:B||!t,title:t?void 0:c("etlBuilder.runNotSetUp","Running pipelines is not set up"),className:"nice-etl-builder__run-btn",children:[e.jsx(g.NiceIcon,{name:B?"clock":"play",size:14})," ",B?c("etlBuilder.running","Running..."):c("etlBuilder.run","Run")]}),e.jsxs("button",{onClick:()=>n==null?void 0:n(p),disabled:!n,title:n?void 0:c("etlBuilder.saveNotSetUp","Saving pipelines is not set up"),className:"nice-etl-builder__save-btn",children:[e.jsx(g.NiceIcon,{name:"save",size:14})," ",c("save","Save")]}),e.jsx(f.NiceTutorialButton,{steps:f.resolveTutorial(a,q)})]})]}),children:[v==="design"&&e.jsx("div",{ref:F,className:"nice-etl-builder__canvas",onDragOver:i=>i.preventDefault(),onDrop:M,onClick:()=>_(null),children:e.jsxs("div",{className:"nice-etl-builder__flow",children:[e.jsxs("div",{className:"nice-etl-builder__column",children:[e.jsx("h5",{children:c("etlBuilder.sources","Sources")}),p.sources.map(i=>e.jsx(C,{node:i,nodeType:"source",icon:"database",isSelected:(u==null?void 0:u.id)===i.id,onSelect:()=>_({type:"source",id:i.id}),onDelete:()=>k("source",i.id)},i.id))]}),e.jsx("div",{className:"nice-etl-builder__arrow","aria-hidden":"true",children:e.jsx(g.NiceIcon,{name:"arrow-right",size:16})}),e.jsxs("div",{className:"nice-etl-builder__column nice-etl-builder__column--transforms",children:[e.jsx("h5",{children:c("etlBuilder.transformations","Transformations")}),p.transformations.map(i=>{const s=w.find(r=>r.type===i.type);return e.jsx(C,{node:i,nodeType:"transformation",icon:(s==null?void 0:s.icon)||"shuffle",isSelected:(u==null?void 0:u.id)===i.id,onSelect:()=>_({type:"transformation",id:i.id}),onDelete:()=>k("transformation",i.id)},i.id)}),p.transformations.length===0&&e.jsx("div",{className:"nice-etl-builder__empty-column",children:c("etlBuilder.dragTransformationsHere","Drag transformations here")})]}),e.jsx("div",{className:"nice-etl-builder__arrow","aria-hidden":"true",children:e.jsx(g.NiceIcon,{name:"arrow-right",size:16})}),e.jsxs("div",{className:"nice-etl-builder__column",children:[e.jsx("h5",{children:c("etlBuilder.destinations","Destinations")}),p.destinations.map(i=>e.jsx(C,{node:i,nodeType:"destination",icon:"download",isSelected:(u==null?void 0:u.id)===i.id,onSelect:()=>_({type:"destination",id:i.id}),onDelete:()=>k("destination",i.id)},i.id))]})]})}),v==="code"&&e.jsx("div",{className:"nice-etl-builder__code-view",children:e.jsx("pre",{children:JSON.stringify(p,null,2)})}),v==="schedule"&&e.jsx(G,{schedule:p.schedule,monitoring:p.monitoring,onChange:U}),v==="history"&&e.jsx(Q,{runs:P})]})}function Y(o){switch(o){case"filter":return{condition:""};case"map":return{mappings:[]};case"aggregate":return{groupBy:[],aggregations:[]};case"join":return{joinType:"inner",leftKey:"",rightKey:""};case"union":return{inputs:[]};case"sort":return{columns:[],directions:[]};case"deduplicate":return{columns:[],keepFirst:!0};case"pivot":return{pivotColumn:"",valueColumn:"",aggregation:"sum"};case"unpivot":return{columns:[],nameColumn:"name",valueColumn:"value"};case"derive":return{name:"",expression:""};case"validate":return{rules:[]};case"cleanse":return{operations:[]};case"custom":return{code:`// Custom transformation
|
|
2
|
+
return data;`};default:return{}}}function C({node:o,nodeType:l,icon:d,isSelected:t,onSelect:h,onDelete:n}){return e.jsxs("div",{className:`nice-etl-builder__node nice-etl-builder__node--${l} ${t?"nice-etl-builder__node--selected":""}`,onClick:j=>{j.stopPropagation(),h()},children:[e.jsx("span",{className:"nice-etl-builder__node-icon",children:E(d)}),e.jsx("span",{className:"nice-etl-builder__node-name",children:o.name}),e.jsx("button",{className:"nice-etl-builder__node-delete",onClick:j=>{j.stopPropagation(),n()},children:"×"})]})}function J({nodeType:o,node:l,dataSources:d,onChange:t,onClose:h}){var j;const{t:n}=f.useNiceTranslation();return l?e.jsxs("div",{className:"nice-etl-builder__properties",children:[e.jsxs("div",{className:"nice-etl-builder__properties-header",children:[e.jsxs("h4",{children:[o.charAt(0).toUpperCase()+o.slice(1)," Properties"]}),e.jsx("button",{onClick:h,children:"×"})]}),e.jsxs("div",{className:"nice-etl-builder__properties-content",children:[e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.name","Name")}),e.jsx("input",{type:"text",value:l.name,onChange:a=>t({name:a.target.value})})]}),o==="source"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.type","Type")}),e.jsxs("select",{value:l.type,onChange:a=>t({type:a.target.value}),children:[e.jsx("option",{value:"database",children:n("etlBuilder.database","Database")}),e.jsx("option",{value:"api",children:"API"}),e.jsx("option",{value:"file",children:n("etlBuilder.file","File")}),e.jsx("option",{value:"stream",children:n("etlBuilder.stream","Stream")})]})]}),e.jsx("div",{className:"nice-etl-builder__field",children:e.jsxs("label",{children:[e.jsx("input",{type:"checkbox",checked:((j=l.incremental)==null?void 0:j.enabled)||!1,onChange:a=>{var c;return t({incremental:{...l.incremental,enabled:a.target.checked,column:((c=l.incremental)==null?void 0:c.column)||""}})}}),n("etlBuilder.incrementalLoad","Incremental Load")]})})]}),o==="transformation"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.type","Type")}),e.jsx("span",{children:l.type})]}),l.type==="filter"&&e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.condition","Condition")}),e.jsx("textarea",{value:String(l.config.condition||""),onChange:a=>t({config:{...l.config,condition:a.target.value}}),placeholder:n("etlBuilder.conditionPlaceholder","e.g., age > 18 AND status = 'active'"),rows:3})]}),l.type==="derive"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.columnName","Column Name")}),e.jsx("input",{type:"text",value:String(l.config.name||""),onChange:a=>t({config:{...l.config,name:a.target.value}})})]}),e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.expression","Expression")}),e.jsx("input",{type:"text",value:String(l.config.expression||""),onChange:a=>t({config:{...l.config,expression:a.target.value}}),placeholder:n("etlBuilder.expressionPlaceholder","e.g., price * quantity")})]})]}),l.type==="custom"&&e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.code","Code")}),e.jsx("textarea",{value:String(l.config.code||""),onChange:a=>t({config:{...l.config,code:a.target.value}}),rows:10,className:"nice-etl-builder__code-input"})]})]}),o==="destination"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.type","Type")}),e.jsxs("select",{value:l.type,onChange:a=>t({type:a.target.value}),children:[e.jsx("option",{value:"database",children:n("etlBuilder.database","Database")}),e.jsx("option",{value:"file",children:n("etlBuilder.file","File")}),e.jsx("option",{value:"api",children:"API"}),e.jsx("option",{value:"warehouse",children:n("etlBuilder.dataWarehouse","Data Warehouse")})]})]}),e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:n("etlBuilder.writeMode","Write Mode")}),e.jsxs("select",{value:l.writeMode,onChange:a=>t({writeMode:a.target.value}),children:[e.jsx("option",{value:"append",children:n("etlBuilder.append","Append")}),e.jsx("option",{value:"overwrite",children:n("etlBuilder.overwrite","Overwrite")}),e.jsx("option",{value:"upsert",children:n("etlBuilder.upsert","Upsert")}),e.jsx("option",{value:"merge",children:n("etlBuilder.merge","Merge")})]})]})]})]})]}):e.jsx(e.Fragment,{})}function G({schedule:o,monitoring:l,onChange:d}){const{t}=f.useNiceTranslation(),[h,n]=m.useState(o||{enabled:!1});return e.jsxs("div",{className:"nice-etl-builder__schedule-editor",children:[e.jsx("h4",{children:t("etlBuilder.scheduleConfiguration","Schedule Configuration")}),e.jsx("div",{className:"nice-etl-builder__field",children:e.jsxs("label",{children:[e.jsx("input",{type:"checkbox",checked:h.enabled,onChange:j=>{const a={...h,enabled:j.target.checked};n(a),d(a)}}),t("etlBuilder.enableScheduledExecution","Enable scheduled execution")]})}),h.enabled&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:t("etlBuilder.cronExpression","Cron Expression")}),e.jsx("input",{type:"text",value:h.cron||"",onChange:j=>{const a={...h,cron:j.target.value};n(a)},placeholder:t("etlBuilder.cronPlaceholder","0 * * * * (every hour)")}),e.jsx("small",{children:t("etlBuilder.cronFormat","Format: minute hour day month weekday")})]}),e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:t("etlBuilder.timezone","Timezone")}),e.jsxs("select",{value:h.timezone||"UTC",onChange:j=>{const a={...h,timezone:j.target.value};n(a)},children:[e.jsx("option",{value:"UTC",children:"UTC"}),e.jsx("option",{value:"America/New_York",children:t("etlBuilder.easternTime","Eastern Time")}),e.jsx("option",{value:"America/Chicago",children:t("etlBuilder.centralTime","Central Time")}),e.jsx("option",{value:"America/Los_Angeles",children:t("etlBuilder.pacificTime","Pacific Time")}),e.jsx("option",{value:"Europe/London",children:t("etlBuilder.london","London")}),e.jsx("option",{value:"Europe/Warsaw",children:t("etlBuilder.warsaw","Warsaw")})]})]}),e.jsx("button",{onClick:()=>d(h),children:t("etlBuilder.saveSchedule","Save Schedule")})]}),e.jsx("h4",{children:t("etlBuilder.monitoring","Monitoring")}),e.jsx("div",{className:"nice-etl-builder__field",children:e.jsxs("label",{children:[e.jsx("input",{type:"checkbox",checked:(l==null?void 0:l.alertOnFailure)||!1,disabled:!0}),t("etlBuilder.alertOnFailure","Alert on failure")]})}),e.jsxs("div",{className:"nice-etl-builder__field",children:[e.jsx("label",{children:t("etlBuilder.logLevel","Log Level")}),e.jsxs("select",{value:(l==null?void 0:l.logLevel)||"info",disabled:!0,children:[e.jsx("option",{value:"error",children:t("etlBuilder.error","Error")}),e.jsx("option",{value:"warn",children:t("etlBuilder.warning","Warning")}),e.jsx("option",{value:"info",children:t("etlBuilder.info","Info")}),e.jsx("option",{value:"debug",children:t("etlBuilder.debug","Debug")})]})]})]})}function Q({runs:o}){const{t:l}=f.useNiceTranslation();return e.jsxs("div",{className:"nice-etl-builder__history-view",children:[e.jsx("h4",{children:l("etlBuilder.runHistory","Run History")}),o.length===0?e.jsx("div",{className:"nice-etl-builder__no-history",children:l("etlBuilder.noRunsYet","No runs yet")}):e.jsxs("table",{className:"nice-etl-builder__history-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:l("etlBuilder.status","Status")}),e.jsx("th",{children:l("etlBuilder.startTime","Start Time")}),e.jsx("th",{children:l("etlBuilder.duration","Duration")}),e.jsx("th",{children:l("etlBuilder.rows","Rows")}),e.jsx("th",{children:l("etlBuilder.errors","Errors")})]})}),e.jsx("tbody",{children:o.map(d=>e.jsxs("tr",{className:`nice-etl-builder__run nice-etl-builder__run--${d.status}`,children:[e.jsx("td",{children:e.jsxs("span",{className:`nice-etl-builder__status nice-etl-builder__status--${d.status}`,children:[e.jsx(g.NiceIcon,{name:d.status==="success"?"check":d.status==="failed"?"close":"clock",size:12}),d.status]})}),e.jsx("td",{children:d.startTime.toLocaleString()}),e.jsx("td",{children:d.endTime?`${Math.round((d.endTime.getTime()-d.startTime.getTime())/1e3)}s`:"-"}),e.jsxs("td",{children:[d.rowsProcessed.toLocaleString()," / ",d.rowsWritten.toLocaleString()]}),e.jsx("td",{children:d.errors.length})]},d.id))})]})]})}exports.NiceETLBuilder=V;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
* Nice2Dev Business Intelligence
|
|
4
4
|
*/
|
|
5
5
|
export { NiceETLBuilder } from './NiceETLBuilder';
|
|
6
|
-
export type { DataSource, DataSourceConfig, DataSchema, TableSchema, ColumnSchema, Relationship, Report, ReportQuery, QueryJoin, QueryColumn, QueryCondition, ReportLayout, ReportElement, ReportElementType, DataBinding, ElementStyle, ReportParameter, ReportFilter, ReportSorting, ReportGrouping, CalculatedField, ReportFormatting, ConditionalFormat, DrillDownConfig, DrillDownLevel, Dashboard, DashboardLayout, DashboardWidget, WidgetType, GridPosition, WidgetConfig, ChartType, ChartSeries, ChartAxis, LegendConfig, TableColumn, MapConfig, WidgetInteraction, DashboardFilter, DashboardTheme, SharingConfig, SharedUser, ETLPipeline, ETLSource, ETLTransformation, ETLTransformationType, ETLDestination, ETLSchedule, ETLMonitoring, ETLRun, ETLError, Cube, CubeDimension, CubeMeasure, CubeHierarchy, NiceETLBuilderProps,
|
|
6
|
+
export type { DataSource, DataSourceConfig, DataSchema, TableSchema, ColumnSchema, Relationship, Report, ReportQuery, QueryJoin, QueryColumn, QueryCondition, ReportLayout, ReportElement, ReportElementType, DataBinding, ElementStyle, ReportParameter, ReportFilter, ReportSorting, ReportGrouping, CalculatedField, ReportFormatting, ConditionalFormat, DrillDownConfig, DrillDownLevel, Dashboard, DashboardLayout, DashboardWidget, WidgetType, GridPosition, WidgetConfig, ChartType, ChartSeries, ChartAxis, LegendConfig, TableColumn, MapConfig, WidgetInteraction, DashboardFilter, DashboardTheme, SharingConfig, SharedUser, ETLPipeline, ETLSource, ETLTransformation, ETLTransformationType, ETLDestination, ETLSchedule, ETLMonitoring, ETLRun, ETLError, Cube, CubeDimension, CubeMeasure, CubeHierarchy, NiceETLBuilderProps, } from './types';
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,758 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsxs as l, jsx as e, Fragment as k } from "react/jsx-runtime";
|
|
2
|
+
import { NiceIcon as g, NiceAppShell as q } from "@nice2dev/ui";
|
|
3
|
+
import { useNiceTranslation as C, createId as w, NiceTutorialButton as G, resolveTutorial as Q } from "@nice2dev/ui-core";
|
|
4
|
+
import { useState as N, useRef as X, useCallback as y } from "react";
|
|
5
|
+
const Z = [
|
|
6
|
+
{
|
|
7
|
+
target: ".nice-etl-builder",
|
|
8
|
+
titleKey: "tutorial.etlBuilder.intro.title",
|
|
9
|
+
title: "ETL builder",
|
|
10
|
+
contentKey: "tutorial.etlBuilder.intro.content",
|
|
11
|
+
content: "Wire sources → transformations → destinations into a pipeline, switch the views, then run it and save the configuration.",
|
|
12
|
+
placement: "auto"
|
|
13
|
+
}
|
|
14
|
+
], ee = {
|
|
15
|
+
id: "",
|
|
16
|
+
name: "New Pipeline",
|
|
17
|
+
sources: [],
|
|
18
|
+
transformations: [],
|
|
19
|
+
destinations: [],
|
|
20
|
+
version: 1
|
|
21
|
+
}, R = (u) => /^[a-z][a-z0-9-]*$/.test(u) ? /* @__PURE__ */ e(g, { name: u, size: 16 }) : u, E = [
|
|
22
|
+
{ type: "filter", key: "etlBuilder.transform.filter", label: "Filter", icon: "filter" },
|
|
23
|
+
{ type: "map", key: "etlBuilder.transform.map", label: "Map", icon: "shuffle" },
|
|
24
|
+
{ type: "aggregate", key: "etlBuilder.transform.aggregate", label: "Aggregate", icon: "∑" },
|
|
25
|
+
{ type: "join", key: "etlBuilder.transform.join", label: "Join", icon: "link" },
|
|
26
|
+
{ type: "union", key: "etlBuilder.transform.union", label: "Union", icon: "∪" },
|
|
27
|
+
{ type: "sort", key: "etlBuilder.transform.sort", label: "Sort", icon: "sort" },
|
|
28
|
+
{
|
|
29
|
+
type: "deduplicate",
|
|
30
|
+
key: "etlBuilder.transform.deduplicate",
|
|
31
|
+
label: "Deduplicate",
|
|
32
|
+
icon: "copy"
|
|
33
|
+
},
|
|
34
|
+
{ type: "pivot", key: "etlBuilder.transform.pivot", label: "Pivot", icon: "expand" },
|
|
35
|
+
{ type: "unpivot", key: "etlBuilder.transform.unpivot", label: "Unpivot", icon: "collapse" },
|
|
36
|
+
{ type: "split", key: "etlBuilder.transform.split", label: "Split", icon: "scissors" },
|
|
37
|
+
{ type: "merge", key: "etlBuilder.transform.merge", label: "Merge", icon: "git-branch" },
|
|
38
|
+
{ type: "lookup", key: "etlBuilder.transform.lookup", label: "Lookup", icon: "book" },
|
|
39
|
+
{ type: "derive", key: "etlBuilder.transform.derive", label: "Derive Column", icon: "plus" },
|
|
40
|
+
{ type: "validate", key: "etlBuilder.transform.validate", label: "Validate", icon: "check" },
|
|
41
|
+
{ type: "cleanse", key: "etlBuilder.transform.cleanse", label: "Cleanse", icon: "wand" },
|
|
42
|
+
{ type: "custom", key: "etlBuilder.transform.custom", label: "Custom", icon: "ƒ" }
|
|
43
|
+
];
|
|
44
|
+
function se({
|
|
45
|
+
pipeline: u,
|
|
46
|
+
dataSources: t = [],
|
|
47
|
+
onChange: o,
|
|
48
|
+
onRun: n,
|
|
49
|
+
onSchedule: h,
|
|
50
|
+
onSave: r,
|
|
51
|
+
className: f = "",
|
|
52
|
+
tutorial: c
|
|
53
|
+
}) {
|
|
54
|
+
const { t: s } = C(), [m, U] = N(
|
|
55
|
+
() => u || {
|
|
56
|
+
...ee,
|
|
57
|
+
id: w(),
|
|
58
|
+
name: s("etlBuilder.newPipeline", "New Pipeline")
|
|
59
|
+
}
|
|
60
|
+
), [p, v] = N(null), [B, F] = N("design"), [S, P] = N(!1), [M, I] = N([]), [T, D] = N(null), $ = X(null), _ = y(
|
|
61
|
+
(i) => {
|
|
62
|
+
U((a) => {
|
|
63
|
+
const d = i(a);
|
|
64
|
+
return o == null || o(d), d;
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
[o]
|
|
68
|
+
), A = y(
|
|
69
|
+
(i) => {
|
|
70
|
+
var d;
|
|
71
|
+
const a = {
|
|
72
|
+
id: w(),
|
|
73
|
+
type: i.type,
|
|
74
|
+
name: i.name,
|
|
75
|
+
config: i.config,
|
|
76
|
+
schema: (d = i.schema) == null ? void 0 : d.tables[0]
|
|
77
|
+
};
|
|
78
|
+
_((b) => ({
|
|
79
|
+
...b,
|
|
80
|
+
sources: [...b.sources, a]
|
|
81
|
+
}));
|
|
82
|
+
},
|
|
83
|
+
[_]
|
|
84
|
+
), z = y(
|
|
85
|
+
(i, a) => {
|
|
86
|
+
const d = {
|
|
87
|
+
id: w(),
|
|
88
|
+
type: i,
|
|
89
|
+
name: (() => {
|
|
90
|
+
const b = E.find((J) => J.type === i);
|
|
91
|
+
return b ? s(b.key, b.label) : i;
|
|
92
|
+
})(),
|
|
93
|
+
input: [],
|
|
94
|
+
output: w(),
|
|
95
|
+
config: ie(i)
|
|
96
|
+
};
|
|
97
|
+
_((b) => ({
|
|
98
|
+
...b,
|
|
99
|
+
transformations: [...b.transformations, d]
|
|
100
|
+
})), v({ type: "transformation", id: d.id });
|
|
101
|
+
},
|
|
102
|
+
[_, s]
|
|
103
|
+
), W = y(() => {
|
|
104
|
+
const i = {
|
|
105
|
+
id: w(),
|
|
106
|
+
type: "database",
|
|
107
|
+
name: s("etlBuilder.newDestination", "New Destination"),
|
|
108
|
+
config: {},
|
|
109
|
+
writeMode: "append"
|
|
110
|
+
};
|
|
111
|
+
_((a) => ({
|
|
112
|
+
...a,
|
|
113
|
+
destinations: [...a.destinations, i]
|
|
114
|
+
})), v({ type: "destination", id: i.id });
|
|
115
|
+
}, [_, s]), x = y(
|
|
116
|
+
(i, a) => {
|
|
117
|
+
_((d) => {
|
|
118
|
+
switch (i) {
|
|
119
|
+
case "source":
|
|
120
|
+
return { ...d, sources: d.sources.filter((b) => b.id !== a) };
|
|
121
|
+
case "transformation":
|
|
122
|
+
return {
|
|
123
|
+
...d,
|
|
124
|
+
transformations: d.transformations.filter((b) => b.id !== a)
|
|
125
|
+
};
|
|
126
|
+
case "destination":
|
|
127
|
+
return { ...d, destinations: d.destinations.filter((b) => b.id !== a) };
|
|
128
|
+
default:
|
|
129
|
+
return d;
|
|
130
|
+
}
|
|
131
|
+
}), v(null);
|
|
132
|
+
},
|
|
133
|
+
[_]
|
|
134
|
+
), O = y(async () => {
|
|
135
|
+
if (n) {
|
|
136
|
+
P(!0);
|
|
137
|
+
try {
|
|
138
|
+
const i = await n(m);
|
|
139
|
+
I((a) => [i, ...a].slice(0, 50));
|
|
140
|
+
} finally {
|
|
141
|
+
P(!1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}, [m, n]), H = y(
|
|
145
|
+
(i) => {
|
|
146
|
+
_((a) => ({ ...a, schedule: i })), h == null || h(m, i);
|
|
147
|
+
},
|
|
148
|
+
[m, _, h]
|
|
149
|
+
), j = y(
|
|
150
|
+
(i) => {
|
|
151
|
+
if (i.preventDefault(), !!T) {
|
|
152
|
+
if (T.startsWith("transform:")) {
|
|
153
|
+
const a = T.replace("transform:", "");
|
|
154
|
+
z(a);
|
|
155
|
+
}
|
|
156
|
+
D(null);
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
[T, z]
|
|
160
|
+
), K = () => {
|
|
161
|
+
if (!p)
|
|
162
|
+
return null;
|
|
163
|
+
switch (p.type) {
|
|
164
|
+
case "source":
|
|
165
|
+
return m.sources.find((i) => i.id === p.id);
|
|
166
|
+
case "transformation":
|
|
167
|
+
return m.transformations.find((i) => i.id === p.id);
|
|
168
|
+
case "destination":
|
|
169
|
+
return m.destinations.find((i) => i.id === p.id);
|
|
170
|
+
default:
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
}, V = B === "design" ? /* @__PURE__ */ l("div", { className: "nice-etl-builder__palette", children: [
|
|
174
|
+
/* @__PURE__ */ e("h4", { children: s("etlBuilder.sources", "Sources") }),
|
|
175
|
+
t.map((i) => /* @__PURE__ */ l("div", { className: "nice-etl-builder__palette-item", onClick: () => A(i), children: [
|
|
176
|
+
/* @__PURE__ */ e("span", { className: "nice-etl-builder__palette-icon", children: /* @__PURE__ */ e(g, { name: "database", size: 14 }) }),
|
|
177
|
+
/* @__PURE__ */ e("span", { children: i.name })
|
|
178
|
+
] }, i.id)),
|
|
179
|
+
/* @__PURE__ */ l(
|
|
180
|
+
"button",
|
|
181
|
+
{
|
|
182
|
+
onClick: () => A({
|
|
183
|
+
id: "",
|
|
184
|
+
name: s("etlBuilder.newSource", "New Source"),
|
|
185
|
+
type: "database",
|
|
186
|
+
config: {}
|
|
187
|
+
}),
|
|
188
|
+
children: [
|
|
189
|
+
/* @__PURE__ */ e(g, { name: "plus", size: 14 }),
|
|
190
|
+
" ",
|
|
191
|
+
s("etlBuilder.addSource", "Add Source")
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
/* @__PURE__ */ e("h4", { children: s("etlBuilder.transformations", "Transformations") }),
|
|
196
|
+
E.map((i) => /* @__PURE__ */ l(
|
|
197
|
+
"div",
|
|
198
|
+
{
|
|
199
|
+
className: "nice-etl-builder__palette-item",
|
|
200
|
+
draggable: !0,
|
|
201
|
+
onDragStart: () => D(`transform:${i.type}`),
|
|
202
|
+
onDragEnd: () => D(null),
|
|
203
|
+
children: [
|
|
204
|
+
/* @__PURE__ */ e("span", { className: "nice-etl-builder__palette-icon", children: R(i.icon) }),
|
|
205
|
+
/* @__PURE__ */ e("span", { children: s(i.key, i.label) })
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
i.type
|
|
209
|
+
)),
|
|
210
|
+
/* @__PURE__ */ e("h4", { children: s("etlBuilder.destinations", "Destinations") }),
|
|
211
|
+
/* @__PURE__ */ l("button", { onClick: W, children: [
|
|
212
|
+
/* @__PURE__ */ e(g, { name: "plus", size: 14 }),
|
|
213
|
+
" ",
|
|
214
|
+
s("etlBuilder.addDestination", "Add Destination")
|
|
215
|
+
] })
|
|
216
|
+
] }) : void 0, Y = p && B === "design" ? /* @__PURE__ */ e(
|
|
217
|
+
le,
|
|
218
|
+
{
|
|
219
|
+
nodeType: p.type,
|
|
220
|
+
node: K() ?? null,
|
|
221
|
+
dataSources: t,
|
|
222
|
+
onChange: (i) => {
|
|
223
|
+
_((a) => {
|
|
224
|
+
switch (p.type) {
|
|
225
|
+
case "source":
|
|
226
|
+
return {
|
|
227
|
+
...a,
|
|
228
|
+
sources: a.sources.map(
|
|
229
|
+
(d) => d.id === p.id ? { ...d, ...i } : d
|
|
230
|
+
)
|
|
231
|
+
};
|
|
232
|
+
case "transformation":
|
|
233
|
+
return {
|
|
234
|
+
...a,
|
|
235
|
+
transformations: a.transformations.map(
|
|
236
|
+
(d) => d.id === p.id ? { ...d, ...i } : d
|
|
237
|
+
)
|
|
238
|
+
};
|
|
239
|
+
case "destination":
|
|
240
|
+
return {
|
|
241
|
+
...a,
|
|
242
|
+
destinations: a.destinations.map(
|
|
243
|
+
(d) => d.id === p.id ? { ...d, ...i } : d
|
|
244
|
+
)
|
|
245
|
+
};
|
|
246
|
+
default:
|
|
247
|
+
return a;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
},
|
|
251
|
+
onClose: () => v(null)
|
|
252
|
+
}
|
|
253
|
+
) : void 0;
|
|
254
|
+
return /* @__PURE__ */ l(
|
|
255
|
+
q,
|
|
256
|
+
{
|
|
257
|
+
flush: !0,
|
|
258
|
+
className: `nice-etl-builder ${f}`,
|
|
259
|
+
height: "100%",
|
|
260
|
+
style: { minHeight: 600 },
|
|
261
|
+
sidebar: V,
|
|
262
|
+
rightSidebar: Y,
|
|
263
|
+
toolbar: /* @__PURE__ */ l("div", { className: "nice-etl-builder__toolbar", children: [
|
|
264
|
+
/* @__PURE__ */ e(
|
|
265
|
+
"input",
|
|
266
|
+
{
|
|
267
|
+
type: "text",
|
|
268
|
+
value: m.name,
|
|
269
|
+
onChange: (i) => _((a) => ({ ...a, name: i.target.value })),
|
|
270
|
+
className: "nice-etl-builder__name-input"
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
/* @__PURE__ */ e("div", { className: "nice-etl-builder__tabs", children: ["design", "code", "schedule", "history"].map((i) => /* @__PURE__ */ e(
|
|
274
|
+
"button",
|
|
275
|
+
{
|
|
276
|
+
className: `nice-etl-builder__tab ${B === i ? "nice-etl-builder__tab--active" : ""}`,
|
|
277
|
+
onClick: () => F(i),
|
|
278
|
+
children: s(`etlBuilder.tab.${i}`, i.charAt(0).toUpperCase() + i.slice(1))
|
|
279
|
+
},
|
|
280
|
+
i
|
|
281
|
+
)) }),
|
|
282
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__actions", children: [
|
|
283
|
+
/* @__PURE__ */ l(
|
|
284
|
+
"button",
|
|
285
|
+
{
|
|
286
|
+
onClick: O,
|
|
287
|
+
disabled: S || !n,
|
|
288
|
+
title: n ? void 0 : s("etlBuilder.runNotSetUp", "Running pipelines is not set up"),
|
|
289
|
+
className: "nice-etl-builder__run-btn",
|
|
290
|
+
children: [
|
|
291
|
+
/* @__PURE__ */ e(g, { name: S ? "clock" : "play", size: 14 }),
|
|
292
|
+
" ",
|
|
293
|
+
S ? s("etlBuilder.running", "Running...") : s("etlBuilder.run", "Run")
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
),
|
|
297
|
+
/* @__PURE__ */ l(
|
|
298
|
+
"button",
|
|
299
|
+
{
|
|
300
|
+
onClick: () => r == null ? void 0 : r(m),
|
|
301
|
+
disabled: !r,
|
|
302
|
+
title: r ? void 0 : s("etlBuilder.saveNotSetUp", "Saving pipelines is not set up"),
|
|
303
|
+
className: "nice-etl-builder__save-btn",
|
|
304
|
+
children: [
|
|
305
|
+
/* @__PURE__ */ e(g, { name: "save", size: 14 }),
|
|
306
|
+
" ",
|
|
307
|
+
s("save", "Save")
|
|
308
|
+
]
|
|
309
|
+
}
|
|
310
|
+
),
|
|
311
|
+
/* @__PURE__ */ e(G, { steps: Q(c, Z) })
|
|
312
|
+
] })
|
|
313
|
+
] }),
|
|
314
|
+
children: [
|
|
315
|
+
B === "design" && /* @__PURE__ */ e(
|
|
316
|
+
"div",
|
|
317
|
+
{
|
|
318
|
+
ref: $,
|
|
319
|
+
className: "nice-etl-builder__canvas",
|
|
320
|
+
onDragOver: (i) => i.preventDefault(),
|
|
321
|
+
onDrop: j,
|
|
322
|
+
onClick: () => v(null),
|
|
323
|
+
children: /* @__PURE__ */ l("div", { className: "nice-etl-builder__flow", children: [
|
|
324
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__column", children: [
|
|
325
|
+
/* @__PURE__ */ e("h5", { children: s("etlBuilder.sources", "Sources") }),
|
|
326
|
+
m.sources.map((i) => /* @__PURE__ */ e(
|
|
327
|
+
L,
|
|
328
|
+
{
|
|
329
|
+
node: i,
|
|
330
|
+
nodeType: "source",
|
|
331
|
+
icon: "database",
|
|
332
|
+
isSelected: (p == null ? void 0 : p.id) === i.id,
|
|
333
|
+
onSelect: () => v({ type: "source", id: i.id }),
|
|
334
|
+
onDelete: () => x("source", i.id)
|
|
335
|
+
},
|
|
336
|
+
i.id
|
|
337
|
+
))
|
|
338
|
+
] }),
|
|
339
|
+
/* @__PURE__ */ e("div", { className: "nice-etl-builder__arrow", "aria-hidden": "true", children: /* @__PURE__ */ e(g, { name: "arrow-right", size: 16 }) }),
|
|
340
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__column nice-etl-builder__column--transforms", children: [
|
|
341
|
+
/* @__PURE__ */ e("h5", { children: s("etlBuilder.transformations", "Transformations") }),
|
|
342
|
+
m.transformations.map((i) => {
|
|
343
|
+
const a = E.find((d) => d.type === i.type);
|
|
344
|
+
return /* @__PURE__ */ e(
|
|
345
|
+
L,
|
|
346
|
+
{
|
|
347
|
+
node: i,
|
|
348
|
+
nodeType: "transformation",
|
|
349
|
+
icon: (a == null ? void 0 : a.icon) || "shuffle",
|
|
350
|
+
isSelected: (p == null ? void 0 : p.id) === i.id,
|
|
351
|
+
onSelect: () => v({ type: "transformation", id: i.id }),
|
|
352
|
+
onDelete: () => x("transformation", i.id)
|
|
353
|
+
},
|
|
354
|
+
i.id
|
|
355
|
+
);
|
|
356
|
+
}),
|
|
357
|
+
m.transformations.length === 0 && /* @__PURE__ */ e("div", { className: "nice-etl-builder__empty-column", children: s("etlBuilder.dragTransformationsHere", "Drag transformations here") })
|
|
358
|
+
] }),
|
|
359
|
+
/* @__PURE__ */ e("div", { className: "nice-etl-builder__arrow", "aria-hidden": "true", children: /* @__PURE__ */ e(g, { name: "arrow-right", size: 16 }) }),
|
|
360
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__column", children: [
|
|
361
|
+
/* @__PURE__ */ e("h5", { children: s("etlBuilder.destinations", "Destinations") }),
|
|
362
|
+
m.destinations.map((i) => /* @__PURE__ */ e(
|
|
363
|
+
L,
|
|
364
|
+
{
|
|
365
|
+
node: i,
|
|
366
|
+
nodeType: "destination",
|
|
367
|
+
icon: "download",
|
|
368
|
+
isSelected: (p == null ? void 0 : p.id) === i.id,
|
|
369
|
+
onSelect: () => v({ type: "destination", id: i.id }),
|
|
370
|
+
onDelete: () => x("destination", i.id)
|
|
371
|
+
},
|
|
372
|
+
i.id
|
|
373
|
+
))
|
|
374
|
+
] })
|
|
375
|
+
] })
|
|
376
|
+
}
|
|
377
|
+
),
|
|
378
|
+
B === "code" && /* @__PURE__ */ e("div", { className: "nice-etl-builder__code-view", children: /* @__PURE__ */ e("pre", { children: JSON.stringify(m, null, 2) }) }),
|
|
379
|
+
B === "schedule" && /* @__PURE__ */ e(
|
|
380
|
+
te,
|
|
381
|
+
{
|
|
382
|
+
schedule: m.schedule,
|
|
383
|
+
monitoring: m.monitoring,
|
|
384
|
+
onChange: H
|
|
385
|
+
}
|
|
386
|
+
),
|
|
387
|
+
B === "history" && /* @__PURE__ */ e(ne, { runs: M })
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
function ie(u) {
|
|
393
|
+
switch (u) {
|
|
394
|
+
case "filter":
|
|
395
|
+
return { condition: "" };
|
|
396
|
+
case "map":
|
|
397
|
+
return { mappings: [] };
|
|
398
|
+
case "aggregate":
|
|
399
|
+
return { groupBy: [], aggregations: [] };
|
|
400
|
+
case "join":
|
|
401
|
+
return { joinType: "inner", leftKey: "", rightKey: "" };
|
|
402
|
+
case "union":
|
|
403
|
+
return { inputs: [] };
|
|
404
|
+
case "sort":
|
|
405
|
+
return { columns: [], directions: [] };
|
|
406
|
+
case "deduplicate":
|
|
407
|
+
return { columns: [], keepFirst: !0 };
|
|
408
|
+
case "pivot":
|
|
409
|
+
return { pivotColumn: "", valueColumn: "", aggregation: "sum" };
|
|
410
|
+
case "unpivot":
|
|
411
|
+
return { columns: [], nameColumn: "name", valueColumn: "value" };
|
|
412
|
+
case "derive":
|
|
413
|
+
return { name: "", expression: "" };
|
|
414
|
+
case "validate":
|
|
415
|
+
return { rules: [] };
|
|
416
|
+
case "cleanse":
|
|
417
|
+
return { operations: [] };
|
|
418
|
+
case "custom":
|
|
419
|
+
return { code: `// Custom transformation
|
|
420
|
+
return data;` };
|
|
421
|
+
default:
|
|
422
|
+
return {};
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function L({
|
|
426
|
+
node: u,
|
|
427
|
+
nodeType: t,
|
|
428
|
+
icon: o,
|
|
429
|
+
isSelected: n,
|
|
430
|
+
onSelect: h,
|
|
431
|
+
onDelete: r
|
|
432
|
+
}) {
|
|
433
|
+
return /* @__PURE__ */ l(
|
|
434
|
+
"div",
|
|
435
|
+
{
|
|
436
|
+
className: `nice-etl-builder__node nice-etl-builder__node--${t} ${n ? "nice-etl-builder__node--selected" : ""}`,
|
|
437
|
+
onClick: (f) => {
|
|
438
|
+
f.stopPropagation(), h();
|
|
439
|
+
},
|
|
440
|
+
children: [
|
|
441
|
+
/* @__PURE__ */ e("span", { className: "nice-etl-builder__node-icon", children: R(o) }),
|
|
442
|
+
/* @__PURE__ */ e("span", { className: "nice-etl-builder__node-name", children: u.name }),
|
|
443
|
+
/* @__PURE__ */ e(
|
|
444
|
+
"button",
|
|
445
|
+
{
|
|
446
|
+
className: "nice-etl-builder__node-delete",
|
|
447
|
+
onClick: (f) => {
|
|
448
|
+
f.stopPropagation(), r();
|
|
449
|
+
},
|
|
450
|
+
children: "×"
|
|
451
|
+
}
|
|
452
|
+
)
|
|
453
|
+
]
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
function le({
|
|
458
|
+
nodeType: u,
|
|
459
|
+
node: t,
|
|
460
|
+
dataSources: o,
|
|
461
|
+
onChange: n,
|
|
462
|
+
onClose: h
|
|
463
|
+
}) {
|
|
464
|
+
var f;
|
|
465
|
+
const { t: r } = C();
|
|
466
|
+
return t ? /* @__PURE__ */ l("div", { className: "nice-etl-builder__properties", children: [
|
|
467
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__properties-header", children: [
|
|
468
|
+
/* @__PURE__ */ l("h4", { children: [
|
|
469
|
+
u.charAt(0).toUpperCase() + u.slice(1),
|
|
470
|
+
" Properties"
|
|
471
|
+
] }),
|
|
472
|
+
/* @__PURE__ */ e("button", { onClick: h, children: "×" })
|
|
473
|
+
] }),
|
|
474
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__properties-content", children: [
|
|
475
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
476
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.name", "Name") }),
|
|
477
|
+
/* @__PURE__ */ e(
|
|
478
|
+
"input",
|
|
479
|
+
{
|
|
480
|
+
type: "text",
|
|
481
|
+
value: t.name,
|
|
482
|
+
onChange: (c) => n({ name: c.target.value })
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
] }),
|
|
486
|
+
u === "source" && /* @__PURE__ */ l(k, { children: [
|
|
487
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
488
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.type", "Type") }),
|
|
489
|
+
/* @__PURE__ */ l(
|
|
490
|
+
"select",
|
|
491
|
+
{
|
|
492
|
+
value: t.type,
|
|
493
|
+
onChange: (c) => n({ type: c.target.value }),
|
|
494
|
+
children: [
|
|
495
|
+
/* @__PURE__ */ e("option", { value: "database", children: r("etlBuilder.database", "Database") }),
|
|
496
|
+
/* @__PURE__ */ e("option", { value: "api", children: "API" }),
|
|
497
|
+
/* @__PURE__ */ e("option", { value: "file", children: r("etlBuilder.file", "File") }),
|
|
498
|
+
/* @__PURE__ */ e("option", { value: "stream", children: r("etlBuilder.stream", "Stream") })
|
|
499
|
+
]
|
|
500
|
+
}
|
|
501
|
+
)
|
|
502
|
+
] }),
|
|
503
|
+
/* @__PURE__ */ e("div", { className: "nice-etl-builder__field", children: /* @__PURE__ */ l("label", { children: [
|
|
504
|
+
/* @__PURE__ */ e(
|
|
505
|
+
"input",
|
|
506
|
+
{
|
|
507
|
+
type: "checkbox",
|
|
508
|
+
checked: ((f = t.incremental) == null ? void 0 : f.enabled) || !1,
|
|
509
|
+
onChange: (c) => {
|
|
510
|
+
var s;
|
|
511
|
+
return n({
|
|
512
|
+
incremental: {
|
|
513
|
+
...t.incremental,
|
|
514
|
+
enabled: c.target.checked,
|
|
515
|
+
column: ((s = t.incremental) == null ? void 0 : s.column) || ""
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
),
|
|
521
|
+
r("etlBuilder.incrementalLoad", "Incremental Load")
|
|
522
|
+
] }) })
|
|
523
|
+
] }),
|
|
524
|
+
u === "transformation" && /* @__PURE__ */ l(k, { children: [
|
|
525
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
526
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.type", "Type") }),
|
|
527
|
+
/* @__PURE__ */ e("span", { children: t.type })
|
|
528
|
+
] }),
|
|
529
|
+
t.type === "filter" && /* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
530
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.condition", "Condition") }),
|
|
531
|
+
/* @__PURE__ */ e(
|
|
532
|
+
"textarea",
|
|
533
|
+
{
|
|
534
|
+
value: String(t.config.condition || ""),
|
|
535
|
+
onChange: (c) => n({
|
|
536
|
+
config: { ...t.config, condition: c.target.value }
|
|
537
|
+
}),
|
|
538
|
+
placeholder: r(
|
|
539
|
+
"etlBuilder.conditionPlaceholder",
|
|
540
|
+
"e.g., age > 18 AND status = 'active'"
|
|
541
|
+
),
|
|
542
|
+
rows: 3
|
|
543
|
+
}
|
|
544
|
+
)
|
|
545
|
+
] }),
|
|
546
|
+
t.type === "derive" && /* @__PURE__ */ l(k, { children: [
|
|
547
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
548
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.columnName", "Column Name") }),
|
|
549
|
+
/* @__PURE__ */ e(
|
|
550
|
+
"input",
|
|
551
|
+
{
|
|
552
|
+
type: "text",
|
|
553
|
+
value: String(t.config.name || ""),
|
|
554
|
+
onChange: (c) => n({
|
|
555
|
+
config: { ...t.config, name: c.target.value }
|
|
556
|
+
})
|
|
557
|
+
}
|
|
558
|
+
)
|
|
559
|
+
] }),
|
|
560
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
561
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.expression", "Expression") }),
|
|
562
|
+
/* @__PURE__ */ e(
|
|
563
|
+
"input",
|
|
564
|
+
{
|
|
565
|
+
type: "text",
|
|
566
|
+
value: String(t.config.expression || ""),
|
|
567
|
+
onChange: (c) => n({
|
|
568
|
+
config: {
|
|
569
|
+
...t.config,
|
|
570
|
+
expression: c.target.value
|
|
571
|
+
}
|
|
572
|
+
}),
|
|
573
|
+
placeholder: r("etlBuilder.expressionPlaceholder", "e.g., price * quantity")
|
|
574
|
+
}
|
|
575
|
+
)
|
|
576
|
+
] })
|
|
577
|
+
] }),
|
|
578
|
+
t.type === "custom" && /* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
579
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.code", "Code") }),
|
|
580
|
+
/* @__PURE__ */ e(
|
|
581
|
+
"textarea",
|
|
582
|
+
{
|
|
583
|
+
value: String(t.config.code || ""),
|
|
584
|
+
onChange: (c) => n({
|
|
585
|
+
config: { ...t.config, code: c.target.value }
|
|
586
|
+
}),
|
|
587
|
+
rows: 10,
|
|
588
|
+
className: "nice-etl-builder__code-input"
|
|
589
|
+
}
|
|
590
|
+
)
|
|
591
|
+
] })
|
|
592
|
+
] }),
|
|
593
|
+
u === "destination" && /* @__PURE__ */ l(k, { children: [
|
|
594
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
595
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.type", "Type") }),
|
|
596
|
+
/* @__PURE__ */ l(
|
|
597
|
+
"select",
|
|
598
|
+
{
|
|
599
|
+
value: t.type,
|
|
600
|
+
onChange: (c) => n({ type: c.target.value }),
|
|
601
|
+
children: [
|
|
602
|
+
/* @__PURE__ */ e("option", { value: "database", children: r("etlBuilder.database", "Database") }),
|
|
603
|
+
/* @__PURE__ */ e("option", { value: "file", children: r("etlBuilder.file", "File") }),
|
|
604
|
+
/* @__PURE__ */ e("option", { value: "api", children: "API" }),
|
|
605
|
+
/* @__PURE__ */ e("option", { value: "warehouse", children: r("etlBuilder.dataWarehouse", "Data Warehouse") })
|
|
606
|
+
]
|
|
607
|
+
}
|
|
608
|
+
)
|
|
609
|
+
] }),
|
|
610
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
611
|
+
/* @__PURE__ */ e("label", { children: r("etlBuilder.writeMode", "Write Mode") }),
|
|
612
|
+
/* @__PURE__ */ l(
|
|
613
|
+
"select",
|
|
614
|
+
{
|
|
615
|
+
value: t.writeMode,
|
|
616
|
+
onChange: (c) => n({ writeMode: c.target.value }),
|
|
617
|
+
children: [
|
|
618
|
+
/* @__PURE__ */ e("option", { value: "append", children: r("etlBuilder.append", "Append") }),
|
|
619
|
+
/* @__PURE__ */ e("option", { value: "overwrite", children: r("etlBuilder.overwrite", "Overwrite") }),
|
|
620
|
+
/* @__PURE__ */ e("option", { value: "upsert", children: r("etlBuilder.upsert", "Upsert") }),
|
|
621
|
+
/* @__PURE__ */ e("option", { value: "merge", children: r("etlBuilder.merge", "Merge") })
|
|
622
|
+
]
|
|
623
|
+
}
|
|
624
|
+
)
|
|
625
|
+
] })
|
|
626
|
+
] })
|
|
627
|
+
] })
|
|
628
|
+
] }) : /* @__PURE__ */ e(k, {});
|
|
629
|
+
}
|
|
630
|
+
function te({
|
|
631
|
+
schedule: u,
|
|
632
|
+
monitoring: t,
|
|
633
|
+
onChange: o
|
|
634
|
+
}) {
|
|
635
|
+
const { t: n } = C(), [h, r] = N(u || { enabled: !1 });
|
|
636
|
+
return /* @__PURE__ */ l("div", { className: "nice-etl-builder__schedule-editor", children: [
|
|
637
|
+
/* @__PURE__ */ e("h4", { children: n("etlBuilder.scheduleConfiguration", "Schedule Configuration") }),
|
|
638
|
+
/* @__PURE__ */ e("div", { className: "nice-etl-builder__field", children: /* @__PURE__ */ l("label", { children: [
|
|
639
|
+
/* @__PURE__ */ e(
|
|
640
|
+
"input",
|
|
641
|
+
{
|
|
642
|
+
type: "checkbox",
|
|
643
|
+
checked: h.enabled,
|
|
644
|
+
onChange: (f) => {
|
|
645
|
+
const c = { ...h, enabled: f.target.checked };
|
|
646
|
+
r(c), o(c);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
),
|
|
650
|
+
n("etlBuilder.enableScheduledExecution", "Enable scheduled execution")
|
|
651
|
+
] }) }),
|
|
652
|
+
h.enabled && /* @__PURE__ */ l(k, { children: [
|
|
653
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
654
|
+
/* @__PURE__ */ e("label", { children: n("etlBuilder.cronExpression", "Cron Expression") }),
|
|
655
|
+
/* @__PURE__ */ e(
|
|
656
|
+
"input",
|
|
657
|
+
{
|
|
658
|
+
type: "text",
|
|
659
|
+
value: h.cron || "",
|
|
660
|
+
onChange: (f) => {
|
|
661
|
+
const c = { ...h, cron: f.target.value };
|
|
662
|
+
r(c);
|
|
663
|
+
},
|
|
664
|
+
placeholder: n("etlBuilder.cronPlaceholder", "0 * * * * (every hour)")
|
|
665
|
+
}
|
|
666
|
+
),
|
|
667
|
+
/* @__PURE__ */ e("small", { children: n("etlBuilder.cronFormat", "Format: minute hour day month weekday") })
|
|
668
|
+
] }),
|
|
669
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
670
|
+
/* @__PURE__ */ e("label", { children: n("etlBuilder.timezone", "Timezone") }),
|
|
671
|
+
/* @__PURE__ */ l(
|
|
672
|
+
"select",
|
|
673
|
+
{
|
|
674
|
+
value: h.timezone || "UTC",
|
|
675
|
+
onChange: (f) => {
|
|
676
|
+
const c = { ...h, timezone: f.target.value };
|
|
677
|
+
r(c);
|
|
678
|
+
},
|
|
679
|
+
children: [
|
|
680
|
+
/* @__PURE__ */ e("option", { value: "UTC", children: "UTC" }),
|
|
681
|
+
/* @__PURE__ */ e("option", { value: "America/New_York", children: n("etlBuilder.easternTime", "Eastern Time") }),
|
|
682
|
+
/* @__PURE__ */ e("option", { value: "America/Chicago", children: n("etlBuilder.centralTime", "Central Time") }),
|
|
683
|
+
/* @__PURE__ */ e("option", { value: "America/Los_Angeles", children: n("etlBuilder.pacificTime", "Pacific Time") }),
|
|
684
|
+
/* @__PURE__ */ e("option", { value: "Europe/London", children: n("etlBuilder.london", "London") }),
|
|
685
|
+
/* @__PURE__ */ e("option", { value: "Europe/Warsaw", children: n("etlBuilder.warsaw", "Warsaw") })
|
|
686
|
+
]
|
|
687
|
+
}
|
|
688
|
+
)
|
|
689
|
+
] }),
|
|
690
|
+
/* @__PURE__ */ e("button", { onClick: () => o(h), children: n("etlBuilder.saveSchedule", "Save Schedule") })
|
|
691
|
+
] }),
|
|
692
|
+
/* @__PURE__ */ e("h4", { children: n("etlBuilder.monitoring", "Monitoring") }),
|
|
693
|
+
/* @__PURE__ */ e("div", { className: "nice-etl-builder__field", children: /* @__PURE__ */ l("label", { children: [
|
|
694
|
+
/* @__PURE__ */ e("input", { type: "checkbox", checked: (t == null ? void 0 : t.alertOnFailure) || !1, disabled: !0 }),
|
|
695
|
+
n("etlBuilder.alertOnFailure", "Alert on failure")
|
|
696
|
+
] }) }),
|
|
697
|
+
/* @__PURE__ */ l("div", { className: "nice-etl-builder__field", children: [
|
|
698
|
+
/* @__PURE__ */ e("label", { children: n("etlBuilder.logLevel", "Log Level") }),
|
|
699
|
+
/* @__PURE__ */ l("select", { value: (t == null ? void 0 : t.logLevel) || "info", disabled: !0, children: [
|
|
700
|
+
/* @__PURE__ */ e("option", { value: "error", children: n("etlBuilder.error", "Error") }),
|
|
701
|
+
/* @__PURE__ */ e("option", { value: "warn", children: n("etlBuilder.warning", "Warning") }),
|
|
702
|
+
/* @__PURE__ */ e("option", { value: "info", children: n("etlBuilder.info", "Info") }),
|
|
703
|
+
/* @__PURE__ */ e("option", { value: "debug", children: n("etlBuilder.debug", "Debug") })
|
|
704
|
+
] })
|
|
705
|
+
] })
|
|
706
|
+
] });
|
|
707
|
+
}
|
|
708
|
+
function ne({ runs: u }) {
|
|
709
|
+
const { t } = C();
|
|
710
|
+
return /* @__PURE__ */ l("div", { className: "nice-etl-builder__history-view", children: [
|
|
711
|
+
/* @__PURE__ */ e("h4", { children: t("etlBuilder.runHistory", "Run History") }),
|
|
712
|
+
u.length === 0 ? /* @__PURE__ */ e("div", { className: "nice-etl-builder__no-history", children: t("etlBuilder.noRunsYet", "No runs yet") }) : /* @__PURE__ */ l("table", { className: "nice-etl-builder__history-table", children: [
|
|
713
|
+
/* @__PURE__ */ e("thead", { children: /* @__PURE__ */ l("tr", { children: [
|
|
714
|
+
/* @__PURE__ */ e("th", { children: t("etlBuilder.status", "Status") }),
|
|
715
|
+
/* @__PURE__ */ e("th", { children: t("etlBuilder.startTime", "Start Time") }),
|
|
716
|
+
/* @__PURE__ */ e("th", { children: t("etlBuilder.duration", "Duration") }),
|
|
717
|
+
/* @__PURE__ */ e("th", { children: t("etlBuilder.rows", "Rows") }),
|
|
718
|
+
/* @__PURE__ */ e("th", { children: t("etlBuilder.errors", "Errors") })
|
|
719
|
+
] }) }),
|
|
720
|
+
/* @__PURE__ */ e("tbody", { children: u.map((o) => /* @__PURE__ */ l(
|
|
721
|
+
"tr",
|
|
722
|
+
{
|
|
723
|
+
className: `nice-etl-builder__run nice-etl-builder__run--${o.status}`,
|
|
724
|
+
children: [
|
|
725
|
+
/* @__PURE__ */ e("td", { children: /* @__PURE__ */ l(
|
|
726
|
+
"span",
|
|
727
|
+
{
|
|
728
|
+
className: `nice-etl-builder__status nice-etl-builder__status--${o.status}`,
|
|
729
|
+
children: [
|
|
730
|
+
/* @__PURE__ */ e(
|
|
731
|
+
g,
|
|
732
|
+
{
|
|
733
|
+
name: o.status === "success" ? "check" : o.status === "failed" ? "close" : "clock",
|
|
734
|
+
size: 12
|
|
735
|
+
}
|
|
736
|
+
),
|
|
737
|
+
o.status
|
|
738
|
+
]
|
|
739
|
+
}
|
|
740
|
+
) }),
|
|
741
|
+
/* @__PURE__ */ e("td", { children: o.startTime.toLocaleString() }),
|
|
742
|
+
/* @__PURE__ */ e("td", { children: o.endTime ? `${Math.round((o.endTime.getTime() - o.startTime.getTime()) / 1e3)}s` : "-" }),
|
|
743
|
+
/* @__PURE__ */ l("td", { children: [
|
|
744
|
+
o.rowsProcessed.toLocaleString(),
|
|
745
|
+
" / ",
|
|
746
|
+
o.rowsWritten.toLocaleString()
|
|
747
|
+
] }),
|
|
748
|
+
/* @__PURE__ */ e("td", { children: o.errors.length })
|
|
749
|
+
]
|
|
750
|
+
},
|
|
751
|
+
o.id
|
|
752
|
+
)) })
|
|
753
|
+
] })
|
|
754
|
+
] });
|
|
755
|
+
}
|
|
2
756
|
export {
|
|
3
|
-
|
|
757
|
+
se as NiceETLBuilder
|
|
4
758
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -417,14 +417,12 @@ export interface NiceETLBuilderProps {
|
|
|
417
417
|
pipeline?: ETLPipeline;
|
|
418
418
|
dataSources?: DataSource[];
|
|
419
419
|
onChange?: (pipeline: ETLPipeline) => void;
|
|
420
|
+
/** Runs the pipeline. Without it the Run button is disabled and says why. */
|
|
420
421
|
onRun?: (pipeline: ETLPipeline) => Promise<ETLRun>;
|
|
421
422
|
onSchedule?: (pipeline: ETLPipeline, schedule: ETLSchedule) => void;
|
|
423
|
+
/** Saves the pipeline (the Save button). Without it the button is disabled and says why. */
|
|
424
|
+
onSave?: (pipeline: ETLPipeline) => void;
|
|
422
425
|
className?: string;
|
|
423
426
|
/** Optional "?" guided tour. Off by default; `true` uses the built-in tour. */
|
|
424
427
|
tutorial?: NiceComponentTutorial;
|
|
425
428
|
}
|
|
426
|
-
export interface NiceCubeBrowserProps {
|
|
427
|
-
cube?: Cube;
|
|
428
|
-
onQuery?: (dimensions: string[], measures: string[], filters: ReportFilter[]) => Promise<unknown[]>;
|
|
429
|
-
className?: string;
|
|
430
|
-
}
|
package/dist/ui-bi.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.nice-etl-builder{font-family:system-ui,-apple-system,sans-serif;background:var(--nice-bg, #fff)}.nice-etl-builder__toolbar{display:flex;align-items:center;gap:1rem;padding:.5rem 1rem;border-bottom:1px solid var(--nice-border, #ddd);background:var(--nice-bg-secondary, #f8f9fa)}.nice-etl-builder__name-input{padding:.375rem .75rem;border:1px solid var(--nice-border, #ddd);border-radius:var(--nice-radius-sm, 4px);font-size:.9375rem;font-weight:500}.nice-etl-builder__tabs{display:flex;gap:.25rem;flex:1}.nice-etl-builder__tab{padding:.375rem .75rem;border:none;background:transparent;cursor:pointer;font-size:.875rem;border-radius:var(--nice-radius-sm, 4px)}.nice-etl-builder__tab:hover{background:var(--nice-hover-bg, #e9ecef)}.nice-etl-builder__tab--active{background:var(--nice-primary, #0066cc);color
|
|
1
|
+
.nice-etl-builder{font-family:system-ui,-apple-system,sans-serif;background:var(--nice-bg, #fff)}.nice-etl-builder__toolbar{display:flex;align-items:center;gap:1rem;padding:.5rem 1rem;border-bottom:1px solid var(--nice-border, #ddd);background:var(--nice-bg-secondary, #f8f9fa)}.nice-etl-builder__name-input{padding:.375rem .75rem;border:1px solid var(--nice-border, #ddd);border-radius:var(--nice-radius-sm, 4px);font-size:.9375rem;font-weight:500}.nice-etl-builder__tabs{display:flex;gap:.25rem;flex:1}.nice-etl-builder__tab{padding:.375rem .75rem;border:none;background:transparent;cursor:pointer;font-size:.875rem;border-radius:var(--nice-radius-sm, 4px)}.nice-etl-builder__tab:hover{background:var(--nice-hover-bg, #e9ecef)}.nice-etl-builder__tab--active{background:var(--nice-primary, #0066cc);color:var(--nice-text-on-primary)}.nice-etl-builder__actions{display:flex;gap:.5rem}.nice-etl-builder__run-btn{padding:.5rem 1rem;background:var(--nice-success, #28a745);color:var(--nice-text-on-success);border:none;border-radius:var(--nice-radius-sm, 4px);cursor:pointer;font-weight:500}.nice-etl-builder__run-btn:disabled{background:var(--nice-bg-tertiary, #6c757d);cursor:not-allowed}.nice-etl-builder__save-btn{padding:.5rem 1rem;background:var(--nice-primary, #0066cc);color:var(--nice-text-on-primary);border:none;border-radius:var(--nice-radius-sm, 4px);cursor:pointer}.nice-etl-builder__palette{width:200px;border-right:1px solid var(--nice-border, #ddd);padding:.5rem;overflow-y:auto;background:var(--nice-bg-secondary, #f8f9fa)}.nice-etl-builder__palette h4{margin:.5rem 0;font-size:.75rem;color:var(--nice-text-muted, #6c757d);text-transform:uppercase}.nice-etl-builder__palette-item{display:flex;align-items:center;gap:.5rem;padding:.5rem;border-radius:var(--nice-radius-sm, 4px);cursor:grab;font-size:.875rem}.nice-etl-builder__palette-item:hover{background:var(--nice-hover-bg, #e9ecef)}.nice-etl-builder__palette-icon{font-size:1rem}.nice-etl-builder__palette button{width:100%;padding:.5rem;border:1px dashed var(--nice-border, #ddd);background:transparent;border-radius:var(--nice-radius-sm, 4px);cursor:pointer;font-size:.875rem;margin-top:.5rem}.nice-etl-builder__canvas{flex:1;height:100%;overflow:auto;padding:1rem}.nice-etl-builder__flow{display:flex;gap:1rem;align-items:flex-start;min-height:100%}.nice-etl-builder__column{min-width:200px;max-width:300px}.nice-etl-builder__column h5{margin:0 0 .5rem;font-size:.75rem;color:var(--nice-text-muted, #6c757d);text-transform:uppercase}.nice-etl-builder__column--transforms{flex:1;min-width:300px}.nice-etl-builder__arrow{display:flex;align-items:center;font-size:1.5rem;color:var(--nice-text-muted, #6c757d);padding-top:2rem}.nice-etl-builder__empty-column{padding:2rem 1rem;border:2px dashed var(--nice-border, #ddd);border-radius:var(--nice-radius-lg, 8px);text-align:center;color:var(--nice-text-muted, #6c757d)}.nice-etl-builder__node{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;background:#fff;border:1px solid var(--nice-border, #ddd);border-radius:var(--nice-radius-lg, 8px);margin-bottom:.5rem;cursor:pointer;box-shadow:0 1px 3px var(--nice-overlay-5, rgba(0, 0, 0, .05))}.nice-etl-builder__node:hover{border-color:var(--nice-primary, #0066cc)}.nice-etl-builder__node--selected{border-color:var(--nice-primary, #0066cc);box-shadow:0 0 0 2px var(--nice-primary-tint-20, rgba(0, 102, 204, .2))}.nice-etl-builder__node-icon{font-size:1.125rem}.nice-etl-builder__node-name{flex:1;font-size:.875rem;font-weight:500}.nice-etl-builder__node-delete{padding:0;width:20px;height:20px;border:none;background:transparent;cursor:pointer;opacity:0;transition:opacity .2s}.nice-etl-builder__node:hover .nice-etl-builder__node-delete{opacity:.5}.nice-etl-builder__node-delete:hover{opacity:1;color:var(--nice-danger, #dc3545)}.nice-etl-builder__properties{width:300px;border-left:1px solid var(--nice-border, #ddd);display:flex;flex-direction:column;background:#fff}.nice-etl-builder__properties-header{display:flex;justify-content:space-between;align-items:center;padding:.75rem 1rem;border-bottom:1px solid var(--nice-border, #ddd);background:var(--nice-bg-secondary, #f8f9fa)}.nice-etl-builder__properties-header h4{margin:0;font-size:.875rem}.nice-etl-builder__properties-content{flex:1;overflow-y:auto;padding:1rem}.nice-etl-builder__field{margin-bottom:1rem}.nice-etl-builder__field label{display:block;margin-bottom:.25rem;font-size:.8125rem;font-weight:500}.nice-etl-builder__field input,.nice-etl-builder__field select,.nice-etl-builder__field textarea{width:100%;padding:.375rem .5rem;border:1px solid var(--nice-border, #ddd);border-radius:var(--nice-radius-sm, 4px);font-size:.875rem}.nice-etl-builder__code-input{font-family:Fira Code,monospace;font-size:.8125rem}.nice-etl-builder__code-view,.nice-etl-builder__schedule-editor,.nice-etl-builder__history-view{flex:1;padding:1rem;overflow:auto}.nice-etl-builder__code-view pre{margin:0;font-family:Fira Code,monospace;font-size:.8125rem}.nice-etl-builder__schedule-editor h4{margin:0 0 1rem}.nice-etl-builder__schedule-editor small{display:block;color:var(--nice-text-muted, #6c757d);font-size:.75rem;margin-top:.25rem}.nice-etl-builder__history-table{width:100%;border-collapse:collapse}.nice-etl-builder__history-table th,.nice-etl-builder__history-table td{padding:.75rem;text-align:left;border-bottom:1px solid var(--nice-border, #ddd)}.nice-etl-builder__history-table th{background:var(--nice-bg-secondary, #f8f9fa);font-weight:500;font-size:.8125rem}.nice-etl-builder__status{display:inline-flex;align-items:center;gap:.25rem;padding:.25rem .5rem;border-radius:var(--nice-radius-sm, 4px);font-size:.8125rem}.nice-etl-builder__status--success{background:var(--nice-success-bg, #d4edda);color:var(--nice-success-dark, #155724)}.nice-etl-builder__status--failed{background:var(--nice-danger-bg, #f8d7da);color:var(--nice-danger-dark, #721c24)}.nice-etl-builder__status--running{background:var(--nice-warning-bg, #fff3cd);color:var(--nice-warning-dark, #856404)}.nice-etl-builder__no-history{text-align:center;color:var(--nice-text-muted, #6c757d);padding:2rem}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nice2dev/ui-bi",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Nice2Dev Business Intelligence
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Nice2Dev Business Intelligence — Report builder, dashboard studio, ETL pipeline builder",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"react-dom": ">=17.0.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@nice2dev/ui": "^1.
|
|
43
|
-
"@nice2dev/ui-core": "^1.
|
|
42
|
+
"@nice2dev/ui": "^1.2.0",
|
|
43
|
+
"@nice2dev/ui-core": "^1.2.0",
|
|
44
44
|
"@testing-library/jest-dom": "^7.0.1",
|
|
45
45
|
"@testing-library/react": "^16.3.3",
|
|
46
46
|
"@types/react": "^19.2.18",
|