retold-data-service 2.1.2 → 2.1.6
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/.github/workflows/publish-image.yml +2 -2
- package/BUILDING-AND-PUBLISHING.md +6 -6
- package/CONTRIBUTING.md +1 -1
- package/Dockerfile +1 -1
- package/README.md +12 -27
- package/build-all.js +66 -0
- package/diagrams/architecture.excalidraw +2966 -0
- package/diagrams/architecture.mmd +17 -0
- package/diagrams/architecture.svg +2 -0
- package/docs/README.md +12 -12
- package/docs/_brand.json +18 -0
- package/docs/_cover.md +1 -1
- package/docs/_topbar.md +1 -1
- package/docs/_version.json +3 -3
- package/docs/api/reference.md +8 -8
- package/docs/architecture.md +6 -84
- package/docs/diagrams/component-diagram.excalidraw +2807 -0
- package/docs/diagrams/component-diagram.mmd +14 -0
- package/docs/diagrams/component-diagram.svg +2 -0
- package/docs/diagrams/component-stack.excalidraw +1169 -0
- package/docs/diagrams/component-stack.mmd +6 -0
- package/docs/diagrams/component-stack.svg +2 -0
- package/docs/diagrams/hook-execution-order.excalidraw +3230 -0
- package/docs/diagrams/hook-execution-order.mmd +19 -0
- package/docs/diagrams/hook-execution-order.svg +2 -0
- package/docs/diagrams/initialization-flow.excalidraw +1800 -0
- package/docs/diagrams/initialization-flow.mmd +22 -0
- package/docs/diagrams/initialization-flow.svg +2 -0
- package/docs/index.html +6 -7
- package/docs/lifecycle-hooks.md +2 -21
- package/docs/retold-catalog.json +141 -141
- package/docs/retold-keyword-index.json +6818 -1608
- package/package.json +130 -96
- package/source/services/RetoldDataService-Brand.js +13 -0
- package/source/services/comprehension-loader/pict-app/Pict-Application-ComprehensionLoader.js +65 -15
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Layout.js +28 -74
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Load.js +17 -17
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-SettingsPanel.js +62 -0
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Shell.js +142 -0
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-StatusBar.js +125 -0
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-StatusDetail.js +89 -0
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-TopBar-Nav.js +42 -0
- package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-TopBar-User.js +48 -0
- package/source/services/comprehension-loader/web/comprehension-loader.js +5517 -6183
- package/source/services/comprehension-loader/web/comprehension-loader.js.map +1 -1
- package/source/services/comprehension-loader/web/comprehension-loader.min.js +75 -1
- package/source/services/comprehension-loader/web/comprehension-loader.min.js.map +1 -1
- package/source/services/comprehension-loader/web/favicons/favicon-dark.svg +13 -0
- package/source/services/comprehension-loader/web/favicons/favicon-light.svg +13 -0
- package/source/services/comprehension-loader/web/favicons/favicon.svg +13 -0
- package/source/services/comprehension-loader/web/index.html +3 -0
- package/source/services/comprehension-loader/web/pict.min.js +12 -0
- package/source/services/data-cloner/DataCloner-Command-Headless.js +102 -4
- package/source/services/data-cloner/DataCloner-Command-Schema.js +105 -8
- package/source/services/data-cloner/DataCloner-Command-Sync.js +111 -75
- package/source/services/data-cloner/pict-app/Pict-Application-DataCloner.js +70 -47
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Export.js +3 -3
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Layout.js +40 -86
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-SettingsPanel.js +61 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Shell.js +136 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-StatusBar.js +117 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-StatusDetail.js +81 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Sync.js +18 -18
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-TopBar-Nav.js +42 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-TopBar-User.js +48 -0
- package/source/services/data-cloner/pict-app/views/PictView-DataCloner-ViewData.js +2 -2
- package/source/services/data-cloner/web/data-cloner.js +5874 -7986
- package/source/services/data-cloner/web/data-cloner.js.map +1 -1
- package/source/services/data-cloner/web/data-cloner.min.js +75 -1
- package/source/services/data-cloner/web/data-cloner.min.js.map +1 -1
- package/source/services/data-cloner/web/favicons/favicon-dark.svg +13 -0
- package/source/services/data-cloner/web/favicons/favicon-light.svg +13 -0
- package/source/services/data-cloner/web/favicons/favicon.svg +13 -0
- package/source/services/data-cloner/web/favicons/favicons/favicon-dark.svg +13 -0
- package/source/services/data-cloner/web/favicons/favicons/favicon-light.svg +13 -0
- package/source/services/data-cloner/web/favicons/favicons/favicon.svg +13 -0
- package/source/services/data-cloner/web/index.html +3 -0
- package/source/services/data-cloner/web/pict.min.js +12 -0
- package/test/Bundles_smoke_tests.js +43 -0
- package/test/ComprehensionLoader_smoke_tests.js +95 -0
- package/test/DataCloner-RuntimeOverrides_tests.js +344 -0
- package/test/DataCloner_smoke_tests.js +87 -0
- package/tools/smoke-converge-endpoint.js +190 -0
- package/docs/css/docuserve.css +0 -327
|
@@ -2,35 +2,48 @@ const libPictApplication = require('pict-application');
|
|
|
2
2
|
|
|
3
3
|
const libProvider = require('./providers/Pict-Provider-DataCloner.js');
|
|
4
4
|
|
|
5
|
-
const libViewLayout
|
|
5
|
+
const libViewLayout = require('./views/PictView-DataCloner-Layout.js');
|
|
6
6
|
const libViewConnection = require('./views/PictView-DataCloner-Connection.js');
|
|
7
|
-
const libViewSession
|
|
8
|
-
const libViewSchema
|
|
9
|
-
const libViewDeploy
|
|
10
|
-
const libViewSync
|
|
11
|
-
const libViewExport
|
|
12
|
-
const libViewViewData
|
|
13
|
-
const libViewHistogram
|
|
7
|
+
const libViewSession = require('./views/PictView-DataCloner-Session.js');
|
|
8
|
+
const libViewSchema = require('./views/PictView-DataCloner-Schema.js');
|
|
9
|
+
const libViewDeploy = require('./views/PictView-DataCloner-Deploy.js');
|
|
10
|
+
const libViewSync = require('./views/PictView-DataCloner-Sync.js');
|
|
11
|
+
const libViewExport = require('./views/PictView-DataCloner-Export.js');
|
|
12
|
+
const libViewViewData = require('./views/PictView-DataCloner-ViewData.js');
|
|
13
|
+
const libViewHistogram = require('pict-section-histogram');
|
|
14
14
|
const libViewConnectionForm = require('pict-section-connection-form');
|
|
15
15
|
|
|
16
|
+
const libPictSectionModal = require('pict-section-modal');
|
|
17
|
+
const libPictSectionTheme = require('pict-section-theme');
|
|
18
|
+
const libBrand = require('../../RetoldDataService-Brand.js');
|
|
19
|
+
|
|
20
|
+
const libViewShell = require('./views/PictView-DataCloner-Shell.js');
|
|
21
|
+
const libViewTopBarNav = require('./views/PictView-DataCloner-TopBar-Nav.js');
|
|
22
|
+
const libViewTopBarUser = require('./views/PictView-DataCloner-TopBar-User.js');
|
|
23
|
+
const libViewStatusBar = require('./views/PictView-DataCloner-StatusBar.js');
|
|
24
|
+
const libViewStatusDetail = require('./views/PictView-DataCloner-StatusDetail.js');
|
|
25
|
+
const libViewSettings = require('./views/PictView-DataCloner-SettingsPanel.js');
|
|
26
|
+
|
|
16
27
|
class DataClonerApplication extends libPictApplication
|
|
17
28
|
{
|
|
18
29
|
constructor(pFable, pOptions, pServiceHash)
|
|
19
30
|
{
|
|
20
31
|
super(pFable, pOptions, pServiceHash);
|
|
21
32
|
|
|
22
|
-
//
|
|
23
|
-
this.pict.
|
|
33
|
+
// 1. Modal section (provides shell + panels + modal API).
|
|
34
|
+
this.pict.addView('Pict-Section-Modal',
|
|
35
|
+
libPictSectionModal.default_configuration, libPictSectionModal);
|
|
24
36
|
|
|
25
|
-
//
|
|
26
|
-
this.pict.
|
|
37
|
+
// 2. Provider + existing section views.
|
|
38
|
+
this.pict.addProvider('DataCloner', libProvider.default_configuration, libProvider);
|
|
39
|
+
this.pict.addView('DataCloner-Layout', libViewLayout.default_configuration, libViewLayout);
|
|
27
40
|
this.pict.addView('DataCloner-Connection', libViewConnection.default_configuration, libViewConnection);
|
|
28
|
-
this.pict.addView('DataCloner-Session',
|
|
29
|
-
this.pict.addView('DataCloner-Schema',
|
|
30
|
-
this.pict.addView('DataCloner-Deploy',
|
|
31
|
-
this.pict.addView('DataCloner-Sync',
|
|
32
|
-
this.pict.addView('DataCloner-Export',
|
|
33
|
-
this.pict.addView('DataCloner-ViewData',
|
|
41
|
+
this.pict.addView('DataCloner-Session', libViewSession.default_configuration, libViewSession);
|
|
42
|
+
this.pict.addView('DataCloner-Schema', libViewSchema.default_configuration, libViewSchema);
|
|
43
|
+
this.pict.addView('DataCloner-Deploy', libViewDeploy.default_configuration, libViewDeploy);
|
|
44
|
+
this.pict.addView('DataCloner-Sync', libViewSync.default_configuration, libViewSync);
|
|
45
|
+
this.pict.addView('DataCloner-Export', libViewExport.default_configuration, libViewExport);
|
|
46
|
+
this.pict.addView('DataCloner-ViewData', libViewViewData.default_configuration, libViewViewData);
|
|
34
47
|
this.pict.addView('DataCloner-StatusHistogram',
|
|
35
48
|
{
|
|
36
49
|
ViewIdentifier: 'DataCloner-StatusHistogram',
|
|
@@ -43,14 +56,12 @@ class DataClonerApplication extends libPictApplication
|
|
|
43
56
|
ShowValues: false,
|
|
44
57
|
ShowLabels: true,
|
|
45
58
|
MaxBarSize: 80,
|
|
46
|
-
BarColor: '#4a90d9',
|
|
59
|
+
BarColor: 'var(--theme-color-brand-primary, #4a90d9)',
|
|
47
60
|
Bins: []
|
|
48
61
|
}, libViewHistogram);
|
|
49
62
|
|
|
50
|
-
// Shared schema-driven connection form
|
|
51
|
-
//
|
|
52
|
-
// provider's bootstrapConnectionSchemas() pumps the schemas in
|
|
53
|
-
// once the host's /clone/connection/schemas endpoint responds.
|
|
63
|
+
// Shared schema-driven connection form (renders into the
|
|
64
|
+
// DataCloner-Connection accordion shell's slot).
|
|
54
65
|
this.pict.addView('PictSection-ConnectionForm',
|
|
55
66
|
Object.assign({}, libViewConnectionForm.default_configuration,
|
|
56
67
|
{
|
|
@@ -60,21 +71,39 @@ class DataClonerApplication extends libPictApplication
|
|
|
60
71
|
ActiveAddress: 'AppData.DataCloner.Connection.ActiveProvider',
|
|
61
72
|
FieldIDPrefix: 'datacloner-conn'
|
|
62
73
|
}), libViewConnectionForm);
|
|
74
|
+
|
|
75
|
+
// 3. Shell host + slot views + status bar / detail + settings panel.
|
|
76
|
+
this.pict.addView('DataCloner-Shell',
|
|
77
|
+
libViewShell.default_configuration, libViewShell);
|
|
78
|
+
this.pict.addView('DataCloner-TopBar-Nav',
|
|
79
|
+
libViewTopBarNav.default_configuration, libViewTopBarNav);
|
|
80
|
+
this.pict.addView('DataCloner-TopBar-User',
|
|
81
|
+
libViewTopBarUser.default_configuration, libViewTopBarUser);
|
|
82
|
+
this.pict.addView('DataCloner-StatusBar',
|
|
83
|
+
libViewStatusBar.default_configuration, libViewStatusBar);
|
|
84
|
+
this.pict.addView('DataCloner-StatusDetail',
|
|
85
|
+
libViewStatusDetail.default_configuration, libViewStatusDetail);
|
|
86
|
+
this.pict.addView('DataCloner-SettingsPanel',
|
|
87
|
+
libViewSettings.default_configuration, libViewSettings);
|
|
88
|
+
|
|
89
|
+
// 4. Theme-Section provider — registered LAST so it can find the slot views.
|
|
90
|
+
this.pict.addProvider('Theme-Section',
|
|
91
|
+
{
|
|
92
|
+
ApplyDefault: 'pict-default',
|
|
93
|
+
DefaultMode: 'system',
|
|
94
|
+
DefaultScale: 1.0,
|
|
95
|
+
Brand: libBrand,
|
|
96
|
+
Views: ['Picker', 'ModeToggle', 'ScaleSelect', 'BrandMark', 'TopBar', 'BottomBar'],
|
|
97
|
+
ViewOptions:
|
|
98
|
+
{
|
|
99
|
+
TopBar: { NavView: 'DataCloner-TopBar-Nav', UserView: 'DataCloner-TopBar-User', Height: 56 },
|
|
100
|
+
BottomBar: { StatusView: 'DataCloner-StatusBar', Height: 36 }
|
|
101
|
+
}
|
|
102
|
+
}, libPictSectionTheme);
|
|
63
103
|
}
|
|
64
104
|
|
|
65
105
|
onAfterInitializeAsync(fCallback)
|
|
66
106
|
{
|
|
67
|
-
// Centralized state (replaces global variables).
|
|
68
|
-
//
|
|
69
|
-
// PersistFields covers the static, non-connection inputs only.
|
|
70
|
-
// Connection-section fields (provider picker + per-provider
|
|
71
|
-
// inputs) are schema-driven now: their DOM ids and
|
|
72
|
-
// localStorage keys are derived at runtime from the host's
|
|
73
|
-
// /clone/connection/schemas response and persistence is hooked
|
|
74
|
-
// up by Pict-Provider-DataCloner#bootstrapConnectionSchemas
|
|
75
|
-
// after the schema-driven Connection view re-renders. See
|
|
76
|
-
// PictView-DataCloner-Connection.js for the field-id
|
|
77
|
-
// convention.
|
|
78
107
|
this.pict.AppData.DataCloner =
|
|
79
108
|
{
|
|
80
109
|
FetchedTables: [],
|
|
@@ -94,9 +123,6 @@ class DataClonerApplication extends libPictApplication
|
|
|
94
123
|
'userName', 'password', 'schemaURL', 'pageSize', 'dateTimePrecisionMS',
|
|
95
124
|
'syncMaxRecords'
|
|
96
125
|
],
|
|
97
|
-
// Connection state — populated by bootstrapConnectionSchemas().
|
|
98
|
-
// Initialized empty here so the Connection view's first
|
|
99
|
-
// onBeforeRender finds a valid (if empty) shape.
|
|
100
126
|
Connection:
|
|
101
127
|
{
|
|
102
128
|
Schemas: [],
|
|
@@ -108,15 +134,17 @@ class DataClonerApplication extends libPictApplication
|
|
|
108
134
|
}
|
|
109
135
|
};
|
|
110
136
|
|
|
111
|
-
// Make pict available for inline onclick handlers
|
|
112
137
|
window.pict = this.pict;
|
|
113
138
|
|
|
114
|
-
// Render
|
|
115
|
-
|
|
116
|
-
|
|
139
|
+
// Render the shell first — creates panel destination divs.
|
|
140
|
+
this.pict.views['DataCloner-Shell'].render();
|
|
141
|
+
|
|
142
|
+
// Render the layout (chains child renders) into #DataCloner-Workspace.
|
|
117
143
|
this.pict.views['DataCloner-Layout'].render();
|
|
118
144
|
|
|
119
|
-
//
|
|
145
|
+
// Render the StatusBar into the BottomBar slot.
|
|
146
|
+
this.pict.views['DataCloner-StatusBar'].render();
|
|
147
|
+
|
|
120
148
|
this.pict.providers.DataCloner.initPersistence();
|
|
121
149
|
this.pict.providers.DataCloner.restoreDeployedTables();
|
|
122
150
|
this.pict.providers.DataCloner.startLiveStatusPolling();
|
|
@@ -125,11 +153,6 @@ class DataClonerApplication extends libPictApplication
|
|
|
125
153
|
this.pict.views['DataCloner-Layout'].collapseAllSections();
|
|
126
154
|
this.pict.providers.DataCloner.initAutoProcess();
|
|
127
155
|
|
|
128
|
-
// Async: fetch the host's connection-form schemas and re-render
|
|
129
|
-
// the Connection section. bootstrapConnectionSchemas restores
|
|
130
|
-
// localStorage values + hooks save listeners once the new DOM
|
|
131
|
-
// is in place, then invokes onProviderChange() to surface the
|
|
132
|
-
// active provider's form.
|
|
133
156
|
this.pict.providers.DataCloner.bootstrapConnectionSchemas(function () { /* fire-and-forget */ });
|
|
134
157
|
|
|
135
158
|
return fCallback();
|
|
@@ -459,11 +459,11 @@ module.exports.default_configuration =
|
|
|
459
459
|
<div id="configExportStatus"></div>
|
|
460
460
|
<div id="cliCommand" style="display:none; margin-bottom:10px">
|
|
461
461
|
<label style="margin-bottom:4px">CLI Command <span style="color:var(--theme-color-text-muted, #888); font-weight:normal">(with config file)</span></label>
|
|
462
|
-
<div style="background:var(--theme-color-text-primary, #1a1a1a); color
|
|
462
|
+
<div style="background:var(--theme-color-text-primary, #1a1a1a); color:var(--theme-color-status-info, #4fc3f7); padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer" onclick="pict.views['DataCloner-Export'].copyCLI()" title="Click to copy"></div>
|
|
463
463
|
</div>
|
|
464
464
|
<div id="cliOneShot" style="display:none; margin-bottom:10px">
|
|
465
465
|
<label style="margin-bottom:4px">One-liner <span style="color:var(--theme-color-text-muted, #888); font-weight:normal">(no config file needed)</span></label>
|
|
466
|
-
<div style="background:var(--theme-color-text-primary, #1a1a1a); color
|
|
466
|
+
<div style="background:var(--theme-color-text-primary, #1a1a1a); color:var(--theme-color-status-info, #4fc3f7); padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer; white-space:pre-wrap" onclick="pict.views['DataCloner-Export'].copyOneShot()" title="Click to copy"></div>
|
|
467
467
|
</div>
|
|
468
468
|
<textarea id="configOutput" style="display:none; width:100%; min-height:300px; font-family:monospace; font-size:0.85em; padding:10px; border:1px solid var(--theme-color-border-default, #ccc); border-radius:4px; background:var(--theme-color-background-secondary, #fafafa); tab-size:4; resize:vertical" readonly></textarea>
|
|
469
469
|
|
|
@@ -476,7 +476,7 @@ module.exports.default_configuration =
|
|
|
476
476
|
</div>
|
|
477
477
|
<div id="mdwintCLICommand" style="margin-bottom:10px">
|
|
478
478
|
<label style="margin-bottom:4px">CLI Command</label>
|
|
479
|
-
<div style="background:var(--theme-color-text-primary, #1a1a1a); color
|
|
479
|
+
<div style="background:var(--theme-color-text-primary, #1a1a1a); color:var(--theme-color-status-info, #4fc3f7); padding:10px 14px; border-radius:4px; font-family:monospace; font-size:0.9em; word-break:break-all; cursor:pointer" onclick="pict.views['DataCloner-Export'].copyMdwintCLI()" title="Click to copy"></div>
|
|
480
480
|
</div>
|
|
481
481
|
<div id="mdwintConfigStatus"></div>
|
|
482
482
|
<textarea id="mdwintConfigOutput" style="width:100%; min-height:250px; font-family:monospace; font-size:0.85em; padding:10px; border:1px solid var(--theme-color-border-default, #ccc); border-radius:4px; background:var(--theme-color-background-secondary, #fafafa); tab-size:4; resize:vertical" readonly></textarea>
|
|
@@ -45,37 +45,6 @@ class DataClonerLayoutView extends libPictView
|
|
|
45
45
|
tmpCards[i].classList.remove('open');
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
toggleStatusDetail()
|
|
50
|
-
{
|
|
51
|
-
let tmpDetail = document.getElementById('liveStatusDetail');
|
|
52
|
-
let tmpMeta = document.getElementById('liveStatusMeta');
|
|
53
|
-
let tmpMessage = document.getElementById('liveStatusMessage');
|
|
54
|
-
let tmpToggle = document.getElementById('liveStatusToggle');
|
|
55
|
-
let tmpBar = document.getElementById('liveStatusBar');
|
|
56
|
-
if (!tmpDetail) return;
|
|
57
|
-
|
|
58
|
-
let tmpIsExpanded = tmpDetail.style.display !== 'none';
|
|
59
|
-
|
|
60
|
-
if (tmpIsExpanded)
|
|
61
|
-
{
|
|
62
|
-
tmpDetail.style.display = 'none';
|
|
63
|
-
tmpMeta.style.display = '';
|
|
64
|
-
tmpMessage.style.display = '';
|
|
65
|
-
tmpToggle.innerHTML = '▼';
|
|
66
|
-
tmpBar.classList.remove('expanded');
|
|
67
|
-
this.pict.providers.DataCloner.onStatusDetailCollapsed();
|
|
68
|
-
}
|
|
69
|
-
else
|
|
70
|
-
{
|
|
71
|
-
tmpDetail.style.display = '';
|
|
72
|
-
tmpMeta.style.display = 'none';
|
|
73
|
-
tmpMessage.style.display = 'none';
|
|
74
|
-
tmpToggle.innerHTML = '▲';
|
|
75
|
-
tmpBar.classList.add('expanded');
|
|
76
|
-
this.pict.providers.DataCloner.onStatusDetailExpanded();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
48
|
}
|
|
80
49
|
|
|
81
50
|
module.exports = DataClonerLayoutView;
|
|
@@ -84,7 +53,7 @@ module.exports.default_configuration =
|
|
|
84
53
|
{
|
|
85
54
|
ViewIdentifier: 'DataCloner-Layout',
|
|
86
55
|
DefaultRenderable: 'DataCloner-Layout',
|
|
87
|
-
DefaultDestinationAddress: '#DataCloner-
|
|
56
|
+
DefaultDestinationAddress: '#DataCloner-Workspace',
|
|
88
57
|
CSS: /*css*/`
|
|
89
58
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
90
59
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: var(--theme-color-background-secondary, #f5f5f5); color: var(--theme-color-text-primary, #333); padding: 20px; }
|
|
@@ -97,7 +66,7 @@ h2 { margin-bottom: 12px; color: var(--theme-color-text-secondary, #444); font-s
|
|
|
97
66
|
.accordion-row { display: flex; gap: 0; margin-bottom: 16px; align-items: stretch; }
|
|
98
67
|
.accordion-number {
|
|
99
68
|
flex: 0 0 48px; display: flex; align-items: flex-start; justify-content: center;
|
|
100
|
-
padding-top: 16px; font-size: 1.6em; font-weight: 700; color: #4a90d9;
|
|
69
|
+
padding-top: 16px; font-size: 1.6em; font-weight: 700; color: var(--theme-color-brand-primary, #4a90d9);
|
|
101
70
|
user-select: none;
|
|
102
71
|
}
|
|
103
72
|
.accordion-card {
|
|
@@ -126,11 +95,11 @@ h2 { margin-bottom: 12px; color: var(--theme-color-text-secondary, #444); font-s
|
|
|
126
95
|
.accordion-actions { display: flex; align-items: baseline; gap: 8px; flex-shrink: 0; }
|
|
127
96
|
.accordion-card.open .accordion-actions { display: none; }
|
|
128
97
|
.accordion-go {
|
|
129
|
-
font-size: 0.82em; color: #4a90d9; cursor: pointer; text-decoration: none;
|
|
98
|
+
font-size: 0.82em; color: var(--theme-color-brand-primary, #4a90d9); cursor: pointer; text-decoration: none;
|
|
130
99
|
font-weight: 500; white-space: nowrap; padding: 2px 6px; border-radius: 3px;
|
|
131
100
|
transition: background 0.15s;
|
|
132
101
|
}
|
|
133
|
-
.accordion-go:hover { background: #e8f0fe; text-decoration: underline; }
|
|
102
|
+
.accordion-go:hover { background: var(--theme-color-background-hover, #e8f0fe); text-decoration: underline; }
|
|
134
103
|
.accordion-auto {
|
|
135
104
|
font-size: 0.82em; color: var(--theme-color-text-muted, #999); white-space: nowrap; cursor: pointer;
|
|
136
105
|
}
|
|
@@ -147,7 +116,7 @@ h2 { margin-bottom: 12px; color: var(--theme-color-text-secondary, #444); font-s
|
|
|
147
116
|
}
|
|
148
117
|
.accordion-phase.visible { display: flex; }
|
|
149
118
|
.accordion-phase-ok { color: var(--theme-color-status-success, #28a745); }
|
|
150
|
-
.accordion-phase-error { color: #dc3545; }
|
|
119
|
+
.accordion-phase-error { color: var(--theme-color-status-error, #dc3545); }
|
|
151
120
|
.accordion-phase-busy { color: var(--theme-color-status-success, #28a745); }
|
|
152
121
|
.accordion-phase-busy .phase-spinner {
|
|
153
122
|
display: inline-block; width: 14px; height: 14px;
|
|
@@ -173,18 +142,18 @@ input[type="text"], input[type="password"], input[type="number"] {
|
|
|
173
142
|
font-size: 0.95em; margin-bottom: 10px;
|
|
174
143
|
}
|
|
175
144
|
input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus {
|
|
176
|
-
outline: none; border-color: #4a90d9;
|
|
145
|
+
outline: none; border-color: var(--theme-color-brand-primary, #4a90d9);
|
|
177
146
|
}
|
|
178
147
|
|
|
179
148
|
button {
|
|
180
149
|
padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer;
|
|
181
150
|
font-size: 0.9em; font-weight: 600; margin-right: 8px; margin-bottom: 8px;
|
|
182
151
|
}
|
|
183
|
-
button.primary { background: #4a90d9; color: var(--theme-color-background-panel, #fff); }
|
|
184
|
-
button.primary:hover { background: #357abd; }
|
|
185
|
-
button.secondary { background: #6c757d; color: var(--theme-color-background-panel, #fff); }
|
|
152
|
+
button.primary { background: var(--theme-color-brand-primary, #4a90d9); color: var(--theme-color-background-panel, #fff); }
|
|
153
|
+
button.primary:hover { background: var(--theme-color-brand-primary-hover, #357abd); }
|
|
154
|
+
button.secondary { background: var(--theme-color-text-secondary, #6c757d); color: var(--theme-color-background-panel, #fff); }
|
|
186
155
|
button.secondary:hover { background: #5a6268; }
|
|
187
|
-
button.danger { background: #dc3545; color: var(--theme-color-background-panel, #fff); }
|
|
156
|
+
button.danger { background: var(--theme-color-status-error, #dc3545); color: var(--theme-color-background-panel, #fff); }
|
|
188
157
|
button.danger:hover { background: #c82333; }
|
|
189
158
|
button.success { background: var(--theme-color-status-success, #28a745); color: var(--theme-color-background-panel, #fff); }
|
|
190
159
|
button.success:hover { background: #218838; }
|
|
@@ -199,7 +168,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
|
199
168
|
.inline-group { display: flex; gap: 8px; align-items: flex-end; margin-bottom: 10px; }
|
|
200
169
|
.inline-group > div { flex: 1; }
|
|
201
170
|
|
|
202
|
-
a { color: #4a90d9; }
|
|
171
|
+
a { color: var(--theme-color-brand-primary, #4a90d9); }
|
|
203
172
|
|
|
204
173
|
select { background: var(--theme-color-background-panel, #fff); width: 100%; padding: 8px 12px; border: 1px solid var(--theme-color-border-default, #ccc); border-radius: 4px; font-size: 0.95em; margin-bottom: 10px; }
|
|
205
174
|
|
|
@@ -211,28 +180,28 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
211
180
|
.live-status-bar {
|
|
212
181
|
background: var(--theme-color-background-panel, #fff); border-radius: 8px; margin-bottom: 16px;
|
|
213
182
|
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
214
|
-
position: sticky; top: 0; z-index: 100; border-left: 4px solid #6c757d;
|
|
183
|
+
position: sticky; top: 0; z-index: 100; border-left: 4px solid var(--theme-color-text-secondary, #6c757d);
|
|
215
184
|
}
|
|
216
|
-
.live-status-bar.phase-idle { border-left-color: #6c757d; }
|
|
217
|
-
.live-status-bar.phase-disconnected { border-left-color: #dc3545; }
|
|
218
|
-
.live-status-bar.phase-ready { border-left-color: #4a90d9; }
|
|
185
|
+
.live-status-bar.phase-idle { border-left-color: var(--theme-color-text-secondary, #6c757d); }
|
|
186
|
+
.live-status-bar.phase-disconnected { border-left-color: var(--theme-color-status-error, #dc3545); }
|
|
187
|
+
.live-status-bar.phase-ready { border-left-color: var(--theme-color-brand-primary, #4a90d9); }
|
|
219
188
|
.live-status-bar.phase-syncing { border-left-color: var(--theme-color-status-success, #28a745); }
|
|
220
|
-
.live-status-bar.phase-stopping { border-left-color: #ffc107; }
|
|
189
|
+
.live-status-bar.phase-stopping { border-left-color: var(--theme-color-status-warning, #ffc107); }
|
|
221
190
|
.live-status-bar.phase-complete { border-left-color: var(--theme-color-status-success, #28a745); }
|
|
222
191
|
|
|
223
192
|
.live-status-dot {
|
|
224
193
|
width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0;
|
|
225
|
-
background: #6c757d;
|
|
194
|
+
background: var(--theme-color-text-secondary, #6c757d);
|
|
226
195
|
}
|
|
227
|
-
.live-status-bar.phase-idle .live-status-dot { background: #6c757d; }
|
|
228
|
-
.live-status-bar.phase-disconnected .live-status-dot { background: #dc3545; }
|
|
229
|
-
.live-status-bar.phase-ready .live-status-dot { background: #4a90d9; }
|
|
196
|
+
.live-status-bar.phase-idle .live-status-dot { background: var(--theme-color-text-secondary, #6c757d); }
|
|
197
|
+
.live-status-bar.phase-disconnected .live-status-dot { background: var(--theme-color-status-error, #dc3545); }
|
|
198
|
+
.live-status-bar.phase-ready .live-status-dot { background: var(--theme-color-brand-primary, #4a90d9); }
|
|
230
199
|
.live-status-bar.phase-syncing .live-status-dot {
|
|
231
200
|
background: var(--theme-color-status-success, #28a745);
|
|
232
201
|
animation: live-pulse 1.5s ease-in-out infinite;
|
|
233
202
|
}
|
|
234
203
|
.live-status-bar.phase-stopping .live-status-dot {
|
|
235
|
-
background: #ffc107;
|
|
204
|
+
background: var(--theme-color-status-warning, #ffc107);
|
|
236
205
|
animation: live-pulse 0.8s ease-in-out infinite;
|
|
237
206
|
}
|
|
238
207
|
.live-status-bar.phase-complete .live-status-dot { background: var(--theme-color-status-success, #28a745); }
|
|
@@ -251,7 +220,7 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
251
220
|
.live-status-meta-item strong { color: var(--theme-color-text-primary, #333); }
|
|
252
221
|
|
|
253
222
|
.live-status-progress-bar {
|
|
254
|
-
height: 3px; background: #e9ecef; border-radius: 2px; overflow: hidden;
|
|
223
|
+
height: 3px; background: var(--theme-color-background-tertiary, #e9ecef); border-radius: 2px; overflow: hidden;
|
|
255
224
|
position: absolute; bottom: 0; left: 0; right: 0;
|
|
256
225
|
}
|
|
257
226
|
.live-status-progress-fill {
|
|
@@ -263,7 +232,7 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
263
232
|
padding: 14px 20px; user-select: none;
|
|
264
233
|
}
|
|
265
234
|
.live-status-bar.expanded .live-status-header {
|
|
266
|
-
border-bottom: 1px solid #e9ecef; padding-bottom: 10px;
|
|
235
|
+
border-bottom: 1px solid var(--theme-color-background-tertiary, #e9ecef); padding-bottom: 10px;
|
|
267
236
|
}
|
|
268
237
|
.live-status-expand-toggle {
|
|
269
238
|
flex: 0 0 20px; display: flex; align-items: center; justify-content: center;
|
|
@@ -278,7 +247,7 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
278
247
|
/* Status Detail Summary Banner */
|
|
279
248
|
.status-detail-summary {
|
|
280
249
|
display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
|
|
281
|
-
padding: 8px 0 12px; margin-bottom: 12px; border-bottom: 1px solid #e9ecef;
|
|
250
|
+
padding: 8px 0 12px; margin-bottom: 12px; border-bottom: 1px solid var(--theme-color-background-tertiary, #e9ecef);
|
|
282
251
|
}
|
|
283
252
|
.status-detail-summary-message {
|
|
284
253
|
font-size: 0.92em; color: var(--theme-color-text-primary, #333); font-weight: 600;
|
|
@@ -303,10 +272,10 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
303
272
|
}
|
|
304
273
|
.running-op-name { font-weight: 600; min-width: 180px; }
|
|
305
274
|
.running-op-bar {
|
|
306
|
-
flex: 1; height: 8px; background: #e9ecef; border-radius: 4px; overflow: hidden;
|
|
275
|
+
flex: 1; height: 8px; background: var(--theme-color-background-tertiary, #e9ecef); border-radius: 4px; overflow: hidden;
|
|
307
276
|
min-width: 120px;
|
|
308
277
|
}
|
|
309
|
-
.running-op-bar-fill { height: 100%; background: #4a90d9; transition: width 0.5s ease; }
|
|
278
|
+
.running-op-bar-fill { height: 100%; background: var(--theme-color-brand-primary, #4a90d9); transition: width 0.5s ease; }
|
|
310
279
|
.running-op-count { font-size: 0.85em; color: var(--theme-color-text-secondary, #666); white-space: nowrap; }
|
|
311
280
|
.running-op-pending { color: var(--theme-color-text-muted, #888); font-size: 0.85em; font-style: italic; padding: 4px 0; }
|
|
312
281
|
|
|
@@ -323,29 +292,29 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
323
292
|
/* Ratio Bar */
|
|
324
293
|
.ratio-bar-container {
|
|
325
294
|
display: flex; height: 10px; border-radius: 5px; overflow: hidden;
|
|
326
|
-
background: #e9ecef; margin: 4px 0;
|
|
295
|
+
background: var(--theme-color-background-tertiary, #e9ecef); margin: 4px 0;
|
|
327
296
|
}
|
|
328
297
|
.ratio-bar-segment { height: 100%; transition: width 0.5s ease; }
|
|
329
|
-
.ratio-bar-segment.unchanged { background: #6c757d; }
|
|
298
|
+
.ratio-bar-segment.unchanged { background: var(--theme-color-text-secondary, #6c757d); }
|
|
330
299
|
.ratio-bar-segment.new-records { background: var(--theme-color-status-success, #28a745); }
|
|
331
|
-
.ratio-bar-segment.updated { background: #4a90d9; }
|
|
332
|
-
.ratio-bar-segment.deleted { background: #dc3545; }
|
|
300
|
+
.ratio-bar-segment.updated { background: var(--theme-color-brand-primary, #4a90d9); }
|
|
301
|
+
.ratio-bar-segment.deleted { background: var(--theme-color-status-error, #dc3545); }
|
|
333
302
|
.ratio-bar-legend {
|
|
334
303
|
display: flex; gap: 12px; font-size: 0.75em; color: var(--theme-color-text-secondary, #666); margin-top: 2px; flex-wrap: wrap;
|
|
335
304
|
}
|
|
336
305
|
.ratio-bar-legend-item { display: flex; align-items: center; gap: 4px; }
|
|
337
306
|
.ratio-bar-legend-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
|
|
338
|
-
.ratio-bar-legend-dot.unchanged-dot { background: #6c757d; }
|
|
307
|
+
.ratio-bar-legend-dot.unchanged-dot { background: var(--theme-color-text-secondary, #6c757d); }
|
|
339
308
|
.ratio-bar-legend-dot.new-dot { background: var(--theme-color-status-success, #28a745); }
|
|
340
|
-
.ratio-bar-legend-dot.updated-dot { background: #4a90d9; }
|
|
341
|
-
.ratio-bar-legend-dot.deleted-dot { background: #dc3545; }
|
|
309
|
+
.ratio-bar-legend-dot.updated-dot { background: var(--theme-color-brand-primary, #4a90d9); }
|
|
310
|
+
.ratio-bar-legend-dot.deleted-dot { background: var(--theme-color-status-error, #dc3545); }
|
|
342
311
|
|
|
343
312
|
/* Error Operations */
|
|
344
313
|
.error-op-row { padding: 6px 0; border-bottom: 1px solid var(--theme-color-background-tertiary, #f0f0f0); font-size: 0.9em; }
|
|
345
314
|
.error-op-row:last-child { border-bottom: none; }
|
|
346
315
|
.error-op-header { display: flex; align-items: center; gap: 8px; }
|
|
347
|
-
.error-op-name { font-weight: 600; color: #dc3545; }
|
|
348
|
-
.error-op-status { font-size: 0.82em; color: #dc3545; }
|
|
316
|
+
.error-op-name { font-weight: 600; color: var(--theme-color-status-error, #dc3545); }
|
|
317
|
+
.error-op-status { font-size: 0.82em; color: var(--theme-color-status-error, #dc3545); }
|
|
349
318
|
.error-op-message { font-size: 0.82em; color: var(--theme-color-text-muted, #888); margin-top: 2px; padding-left: 18px; }
|
|
350
319
|
.error-op-log-entries {
|
|
351
320
|
font-size: 0.78em; color: var(--theme-color-text-muted, #888); margin-top: 4px; padding-left: 18px;
|
|
@@ -359,23 +328,23 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
359
328
|
.precount-table thead th {
|
|
360
329
|
text-align: left; font-weight: 600; color: var(--theme-color-text-secondary, #555); font-size: 0.85em;
|
|
361
330
|
text-transform: uppercase; letter-spacing: 0.3px;
|
|
362
|
-
padding: 4px 8px 6px; border-bottom: 2px solid #e9ecef;
|
|
331
|
+
padding: 4px 8px 6px; border-bottom: 2px solid var(--theme-color-background-tertiary, #e9ecef);
|
|
363
332
|
}
|
|
364
333
|
.precount-table tbody td {
|
|
365
334
|
padding: 4px 8px; border-bottom: 1px solid var(--theme-color-background-tertiary, #f0f0f0);
|
|
366
335
|
}
|
|
367
|
-
.precount-table tbody tr:last-child td { border-bottom: 1px solid #e9ecef; }
|
|
336
|
+
.precount-table tbody tr:last-child td { border-bottom: 1px solid var(--theme-color-background-tertiary, #e9ecef); }
|
|
368
337
|
.precount-table tfoot td {
|
|
369
338
|
padding: 6px 8px 2px; font-size: 0.95em;
|
|
370
339
|
}
|
|
371
|
-
.precount-error td { color: #dc3545; }
|
|
340
|
+
.precount-error td { color: var(--theme-color-status-error, #dc3545); }
|
|
372
341
|
.precount-pending {
|
|
373
342
|
color: var(--theme-color-text-muted, #888); font-size: 0.85em; font-style: italic; padding: 8px 0 2px;
|
|
374
343
|
display: flex; align-items: center; gap: 6px;
|
|
375
344
|
}
|
|
376
345
|
.precount-spinner {
|
|
377
346
|
display: inline-block; width: 12px; height: 12px;
|
|
378
|
-
border: 2px solid var(--theme-color-border-default, #ddd); border-top-color: #4a90d9;
|
|
347
|
+
border: 2px solid var(--theme-color-border-default, #ddd); border-top-color: var(--theme-color-brand-primary, #4a90d9);
|
|
379
348
|
border-radius: 50%; animation: precount-spin 0.8s linear infinite;
|
|
380
349
|
}
|
|
381
350
|
@keyframes precount-spin { to { transform: rotate(360deg); } }
|
|
@@ -387,21 +356,6 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
387
356
|
Template: /*html*/`
|
|
388
357
|
<h1>Retold Data Cloner</h1>
|
|
389
358
|
|
|
390
|
-
<!-- Live Status Bar (Expandable) -->
|
|
391
|
-
<div id="liveStatusBar" class="live-status-bar phase-idle" style="position:relative">
|
|
392
|
-
<div class="live-status-header" onclick="pict.views['DataCloner-Layout'].toggleStatusDetail()">
|
|
393
|
-
<div class="live-status-dot"></div>
|
|
394
|
-
<div class="live-status-message" id="liveStatusMessage">Idle</div>
|
|
395
|
-
<div class="live-status-meta" id="liveStatusMeta"></div>
|
|
396
|
-
<div class="live-status-expand-toggle" id="liveStatusToggle">▼</div>
|
|
397
|
-
</div>
|
|
398
|
-
<div class="live-status-detail" id="liveStatusDetail" style="display:none">
|
|
399
|
-
<div id="DataCloner-Throughput-Histogram"></div>
|
|
400
|
-
<div id="DataCloner-StatusDetail-Container"></div>
|
|
401
|
-
</div>
|
|
402
|
-
<div class="live-status-progress-bar"><div class="live-status-progress-fill" id="liveStatusProgressFill" style="width:0%"></div></div>
|
|
403
|
-
</div>
|
|
404
|
-
|
|
405
359
|
<!-- Expand / Collapse All -->
|
|
406
360
|
<div class="accordion-controls">
|
|
407
361
|
<button onclick="pict.views['DataCloner-Layout'].expandAllSections()">Expand All</button>
|
|
@@ -424,7 +378,7 @@ select { background: var(--theme-color-background-panel, #fff); width: 100%; pad
|
|
|
424
378
|
{
|
|
425
379
|
RenderableHash: 'DataCloner-Layout',
|
|
426
380
|
TemplateHash: 'DataCloner-Layout',
|
|
427
|
-
DestinationAddress: '#DataCloner-
|
|
381
|
+
DestinationAddress: '#DataCloner-Workspace'
|
|
428
382
|
}
|
|
429
383
|
]
|
|
430
384
|
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const libPictView = require('pict-view');
|
|
4
|
+
|
|
5
|
+
class DataClonerSettingsPanelView extends libPictView
|
|
6
|
+
{
|
|
7
|
+
onAfterRender(pRenderable, pAddress, pRecord, pContent)
|
|
8
|
+
{
|
|
9
|
+
if (this.pict.CSSMap) { this.pict.CSSMap.injectCSS(); }
|
|
10
|
+
|
|
11
|
+
let tmpTheme = this.pict.providers && this.pict.providers['Theme-Section'];
|
|
12
|
+
if (tmpTheme && typeof tmpTheme.mount === 'function')
|
|
13
|
+
{
|
|
14
|
+
tmpTheme.mount({
|
|
15
|
+
Container: '#DataCloner-Settings-Theme',
|
|
16
|
+
Views: ['Picker', 'ModeToggle', 'ScaleSelect']
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = DataClonerSettingsPanelView;
|
|
24
|
+
|
|
25
|
+
module.exports.default_configuration =
|
|
26
|
+
{
|
|
27
|
+
ViewIdentifier: 'DataCloner-SettingsPanel',
|
|
28
|
+
DefaultRenderable: 'DataCloner-SettingsPanel',
|
|
29
|
+
DefaultDestinationAddress: '#DataCloner-Settings-Panel',
|
|
30
|
+
AutoRender: false,
|
|
31
|
+
CSS: /*css*/`
|
|
32
|
+
.rds-settings-body {
|
|
33
|
+
padding: 12px;
|
|
34
|
+
display: flex; flex-direction: column; gap: 16px;
|
|
35
|
+
color: var(--theme-color-text-primary, #333333);
|
|
36
|
+
}
|
|
37
|
+
.rds-settings-section { display: flex; flex-direction: column; gap: 6px; }
|
|
38
|
+
.rds-settings-label {
|
|
39
|
+
font-size: 0.85em;
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
text-transform: uppercase;
|
|
42
|
+
letter-spacing: 0.04em;
|
|
43
|
+
color: var(--theme-color-text-secondary, #555555);
|
|
44
|
+
}
|
|
45
|
+
`,
|
|
46
|
+
Templates: [{
|
|
47
|
+
Hash: 'DataCloner-SettingsPanel',
|
|
48
|
+
Template: /*html*/`
|
|
49
|
+
<div class="rds-settings-body">
|
|
50
|
+
<div class="rds-settings-section">
|
|
51
|
+
<div class="rds-settings-label">Appearance</div>
|
|
52
|
+
<div id="DataCloner-Settings-Theme"></div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>`
|
|
55
|
+
}],
|
|
56
|
+
Renderables: [{
|
|
57
|
+
RenderableHash: 'DataCloner-SettingsPanel',
|
|
58
|
+
TemplateHash: 'DataCloner-SettingsPanel',
|
|
59
|
+
DestinationAddress: '#DataCloner-Settings-Panel'
|
|
60
|
+
}]
|
|
61
|
+
};
|