retold-data-service 2.1.2 → 2.1.5
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/BUILDING-AND-PUBLISHING.md +2 -2
- 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 +5415 -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 +2 -1
- package/source/services/data-cloner/DataCloner-Command-Sync.js +110 -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 +5772 -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/docs/css/docuserve.css +0 -327
|
@@ -253,7 +253,8 @@ module.exports = (pDataClonerService, pConfig, pCLIOptions, fCallback) =>
|
|
|
253
253
|
MaxRecordsPerEntity: tmpMaxRecords || tmpSync.MaxRecordsPerEntity || 0,
|
|
254
254
|
DateTimePrecisionMS: tmpSync.DateTimePrecisionMS,
|
|
255
255
|
BackSyncTimeLimit: tmpSync.BackSyncTimeLimit,
|
|
256
|
-
TrueUpPageSize: tmpSync.TrueUpPageSize
|
|
256
|
+
TrueUpPageSize: tmpSync.TrueUpPageSize,
|
|
257
|
+
SyncEntityOptions: tmpSync.SyncEntityOptions
|
|
257
258
|
});
|
|
258
259
|
|
|
259
260
|
tmpFable.log.info(`Headless: Starting ${tmpSyncBody.SyncMode} sync...`);
|
|
@@ -10,6 +10,109 @@
|
|
|
10
10
|
const libFableLog = require('fable-log');
|
|
11
11
|
const libPath = require('path');
|
|
12
12
|
|
|
13
|
+
// Runtime-overridable sync properties for the /clone/sync/start route.
|
|
14
|
+
// Each entry is a coerce function returning the value to apply, or null
|
|
15
|
+
// if the input is invalid. Drives both the top-level body overrides and
|
|
16
|
+
// the per-entity `SyncEntityOptions` overrides — adding a new knob is a
|
|
17
|
+
// one-line change here.
|
|
18
|
+
const _RuntimeSyncProperties = {
|
|
19
|
+
BackSyncTimeLimit: (pVal) => { let tmpN = parseInt(pVal, 10); return (!isNaN(tmpN) && tmpN > 0) ? tmpN : null; },
|
|
20
|
+
MaxRecordsPerEntity: (pVal) => { let tmpN = parseInt(pVal, 10); return (!isNaN(tmpN) && tmpN > 0) ? tmpN : null; },
|
|
21
|
+
DateTimePrecisionMS: (pVal) => { let tmpN = parseInt(pVal, 10); return !isNaN(tmpN) ? tmpN : null; },
|
|
22
|
+
TrueUpPageSize: (pVal) => { let tmpN = parseInt(pVal, 10); return (!isNaN(tmpN) && tmpN > 0) ? tmpN : null; },
|
|
23
|
+
UseAdvancedIDPagination: (pVal) => !!pVal,
|
|
24
|
+
SyncDeletedRecords: (pVal) => !!pVal
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Apply runtime sync overrides from a request body to a live MeadowSync.
|
|
29
|
+
*
|
|
30
|
+
* Mutates `pMeadowSync.MeadowSyncEntities[*]` properties, plus mirrors the
|
|
31
|
+
* "base" globals onto the MeadowSync orchestrator and `cloneState.SyncDeletedRecords`.
|
|
32
|
+
* Top-level body keys form the base config; per-entity overrides under
|
|
33
|
+
* `pBody.SyncEntityOptions[<TableName>]` are layered on top (per-entity wins).
|
|
34
|
+
*
|
|
35
|
+
* Only properties listed in `_RuntimeSyncProperties` are honored; unknown keys
|
|
36
|
+
* and invalid values are silently ignored. Unknown entity names produce a warn.
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} pBody - Request body (or any plain object with the same shape).
|
|
39
|
+
* @param {Object} pMeadowSync - MeadowSync orchestrator instance with `MeadowSyncEntities`.
|
|
40
|
+
* @param {Object} pCloneState - Clone-state object whose `SyncDeletedRecords` mirrors the base.
|
|
41
|
+
* @param {Object} pLog - Logger with `info(msg)` and `warn(msg)`.
|
|
42
|
+
*/
|
|
43
|
+
const applyRuntimeSyncOverrides = (pBody, pMeadowSync, pCloneState, pLog) =>
|
|
44
|
+
{
|
|
45
|
+
// Compute the base runtime config from top-level body keys.
|
|
46
|
+
let tmpBase = {};
|
|
47
|
+
let tmpBaseSchemaKeys = Object.keys(_RuntimeSyncProperties);
|
|
48
|
+
for (let i = 0; i < tmpBaseSchemaKeys.length; i++)
|
|
49
|
+
{
|
|
50
|
+
let tmpKey = tmpBaseSchemaKeys[i];
|
|
51
|
+
if (!pBody.hasOwnProperty(tmpKey)) continue;
|
|
52
|
+
let tmpCoerced = _RuntimeSyncProperties[tmpKey](pBody[tmpKey]);
|
|
53
|
+
if (tmpCoerced === null) continue;
|
|
54
|
+
tmpBase[tmpKey] = tmpCoerced;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let tmpPerEntity = (pBody.SyncEntityOptions && typeof(pBody.SyncEntityOptions) === 'object') ? pBody.SyncEntityOptions : {};
|
|
58
|
+
|
|
59
|
+
// Mirror base values onto the MeadowSync orchestrator + cloneState.
|
|
60
|
+
let tmpBaseKeys = Object.keys(tmpBase);
|
|
61
|
+
for (let i = 0; i < tmpBaseKeys.length; i++)
|
|
62
|
+
{
|
|
63
|
+
if (pMeadowSync.hasOwnProperty(tmpBaseKeys[i]))
|
|
64
|
+
{
|
|
65
|
+
pMeadowSync[tmpBaseKeys[i]] = tmpBase[tmpBaseKeys[i]];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (tmpBase.hasOwnProperty('SyncDeletedRecords'))
|
|
69
|
+
{
|
|
70
|
+
pCloneState.SyncDeletedRecords = tmpBase.SyncDeletedRecords;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Apply base to every entity.
|
|
74
|
+
let tmpAllEntityNames = Object.keys(pMeadowSync.MeadowSyncEntities || {});
|
|
75
|
+
for (let i = 0; i < tmpAllEntityNames.length; i++)
|
|
76
|
+
{
|
|
77
|
+
let tmpEntity = pMeadowSync.MeadowSyncEntities[tmpAllEntityNames[i]];
|
|
78
|
+
for (let j = 0; j < tmpBaseKeys.length; j++)
|
|
79
|
+
{
|
|
80
|
+
tmpEntity[tmpBaseKeys[j]] = tmpBase[tmpBaseKeys[j]];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Layer per-entity overrides on top. Log per entity that actually had
|
|
85
|
+
// overrides applied; warn on unknown entity names.
|
|
86
|
+
let tmpPerEntityNames = Object.keys(tmpPerEntity);
|
|
87
|
+
for (let i = 0; i < tmpPerEntityNames.length; i++)
|
|
88
|
+
{
|
|
89
|
+
let tmpEntityName = tmpPerEntityNames[i];
|
|
90
|
+
let tmpEntity = pMeadowSync.MeadowSyncEntities && pMeadowSync.MeadowSyncEntities[tmpEntityName];
|
|
91
|
+
if (!tmpEntity)
|
|
92
|
+
{
|
|
93
|
+
pLog.warn(`SyncEntityOptions: no sync entity ${tmpEntityName} loaded; ignoring overrides for it.`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
let tmpOverrides = tmpPerEntity[tmpEntityName];
|
|
97
|
+
if (!tmpOverrides || typeof(tmpOverrides) !== 'object') continue;
|
|
98
|
+
let tmpApplied = [];
|
|
99
|
+
let tmpOverrideKeys = Object.keys(tmpOverrides);
|
|
100
|
+
for (let j = 0; j < tmpOverrideKeys.length; j++)
|
|
101
|
+
{
|
|
102
|
+
let tmpKey = tmpOverrideKeys[j];
|
|
103
|
+
if (!_RuntimeSyncProperties.hasOwnProperty(tmpKey)) continue;
|
|
104
|
+
let tmpCoerced = _RuntimeSyncProperties[tmpKey](tmpOverrides[tmpKey]);
|
|
105
|
+
if (tmpCoerced === null) continue;
|
|
106
|
+
tmpEntity[tmpKey] = tmpCoerced;
|
|
107
|
+
tmpApplied.push(`${tmpKey}=${tmpCoerced}`);
|
|
108
|
+
}
|
|
109
|
+
if (tmpApplied.length > 0)
|
|
110
|
+
{
|
|
111
|
+
pLog.info(`SyncEntityOptions: ${tmpEntityName} ← ${tmpApplied.join(', ')}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
13
116
|
module.exports = (pDataClonerService, pOratorServiceServer) =>
|
|
14
117
|
{
|
|
15
118
|
let tmpFable = pDataClonerService.fable;
|
|
@@ -43,81 +146,9 @@ module.exports = (pDataClonerService, pOratorServiceServer) =>
|
|
|
43
146
|
let tmpRequestedMode = tmpBody.SyncMode || 'Initial';
|
|
44
147
|
let tmpMaxRecords = parseInt(tmpBody.MaxRecordsPerEntity, 10) || 0;
|
|
45
148
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
tmpCloneState.SyncDeletedRecords = !!tmpBody.SyncDeletedRecords;
|
|
50
|
-
let tmpEntityNames = Object.keys(tmpFable.MeadowSync.MeadowSyncEntities);
|
|
51
|
-
for (let i = 0; i < tmpEntityNames.length; i++)
|
|
52
|
-
{
|
|
53
|
-
tmpFable.MeadowSync.MeadowSyncEntities[tmpEntityNames[i]].SyncDeletedRecords = tmpCloneState.SyncDeletedRecords;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Update MaxRecordsPerEntity on sync entities
|
|
58
|
-
if (tmpMaxRecords > 0)
|
|
59
|
-
{
|
|
60
|
-
let tmpEntityNames = Object.keys(tmpFable.MeadowSync.MeadowSyncEntities);
|
|
61
|
-
for (let i = 0; i < tmpEntityNames.length; i++)
|
|
62
|
-
{
|
|
63
|
-
tmpFable.MeadowSync.MeadowSyncEntities[tmpEntityNames[i]].MaxRecordsPerEntity = tmpMaxRecords;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Update UseAdvancedIDPagination on all sync entities
|
|
68
|
-
if (tmpBody.hasOwnProperty('UseAdvancedIDPagination'))
|
|
69
|
-
{
|
|
70
|
-
let tmpEntityNames = Object.keys(tmpFable.MeadowSync.MeadowSyncEntities);
|
|
71
|
-
for (let i = 0; i < tmpEntityNames.length; i++)
|
|
72
|
-
{
|
|
73
|
-
tmpFable.MeadowSync.MeadowSyncEntities[tmpEntityNames[i]].UseAdvancedIDPagination = !!tmpBody.UseAdvancedIDPagination;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Update DateTimePrecisionMS on MeadowSync and all sync entities
|
|
78
|
-
if (tmpBody.hasOwnProperty('DateTimePrecisionMS'))
|
|
79
|
-
{
|
|
80
|
-
let tmpPrecision = parseInt(tmpBody.DateTimePrecisionMS, 10);
|
|
81
|
-
if (!isNaN(tmpPrecision))
|
|
82
|
-
{
|
|
83
|
-
tmpFable.MeadowSync.DateTimePrecisionMS = tmpPrecision;
|
|
84
|
-
let tmpEntityNames = Object.keys(tmpFable.MeadowSync.MeadowSyncEntities);
|
|
85
|
-
for (let i = 0; i < tmpEntityNames.length; i++)
|
|
86
|
-
{
|
|
87
|
-
tmpFable.MeadowSync.MeadowSyncEntities[tmpEntityNames[i]].DateTimePrecisionMS = tmpPrecision;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Update BackSyncTimeLimit on MeadowSync and all sync entities
|
|
93
|
-
if (tmpBody.hasOwnProperty('BackSyncTimeLimit'))
|
|
94
|
-
{
|
|
95
|
-
let tmpBackSyncTimeLimit = parseInt(tmpBody.BackSyncTimeLimit, 10);
|
|
96
|
-
if (!isNaN(tmpBackSyncTimeLimit) && tmpBackSyncTimeLimit > 0)
|
|
97
|
-
{
|
|
98
|
-
tmpFable.MeadowSync.BackSyncTimeLimit = tmpBackSyncTimeLimit;
|
|
99
|
-
let tmpEntityNames = Object.keys(tmpFable.MeadowSync.MeadowSyncEntities);
|
|
100
|
-
for (let i = 0; i < tmpEntityNames.length; i++)
|
|
101
|
-
{
|
|
102
|
-
tmpFable.MeadowSync.MeadowSyncEntities[tmpEntityNames[i]].BackSyncTimeLimit = tmpBackSyncTimeLimit;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Update TrueUpPageSize on MeadowSync and all sync entities
|
|
108
|
-
if (tmpBody.hasOwnProperty('TrueUpPageSize'))
|
|
109
|
-
{
|
|
110
|
-
let tmpTrueUpPageSize = parseInt(tmpBody.TrueUpPageSize, 10);
|
|
111
|
-
if (!isNaN(tmpTrueUpPageSize) && tmpTrueUpPageSize > 0)
|
|
112
|
-
{
|
|
113
|
-
tmpFable.MeadowSync.TrueUpPageSize = tmpTrueUpPageSize;
|
|
114
|
-
let tmpEntityNames = Object.keys(tmpFable.MeadowSync.MeadowSyncEntities);
|
|
115
|
-
for (let i = 0; i < tmpEntityNames.length; i++)
|
|
116
|
-
{
|
|
117
|
-
tmpFable.MeadowSync.MeadowSyncEntities[tmpEntityNames[i]].TrueUpPageSize = tmpTrueUpPageSize;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
149
|
+
// Apply global + per-entity runtime sync overrides. See
|
|
150
|
+
// applyRuntimeSyncOverrides() at module scope.
|
|
151
|
+
applyRuntimeSyncOverrides(tmpBody, tmpFable.MeadowSync, tmpCloneState, tmpFable.log);
|
|
121
152
|
|
|
122
153
|
// If no tables specified, sync all entities
|
|
123
154
|
if (tmpSelectedTables.length === 0)
|
|
@@ -579,3 +610,7 @@ module.exports = (pDataClonerService, pOratorServiceServer) =>
|
|
|
579
610
|
return fNext();
|
|
580
611
|
});
|
|
581
612
|
};
|
|
613
|
+
|
|
614
|
+
// Exposed for unit tests.
|
|
615
|
+
module.exports._RuntimeSyncProperties = _RuntimeSyncProperties;
|
|
616
|
+
module.exports.applyRuntimeSyncOverrides = applyRuntimeSyncOverrides;
|
|
@@ -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>
|