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.
Files changed (80) hide show
  1. package/BUILDING-AND-PUBLISHING.md +2 -2
  2. package/Dockerfile +1 -1
  3. package/README.md +12 -27
  4. package/build-all.js +66 -0
  5. package/diagrams/architecture.excalidraw +2966 -0
  6. package/diagrams/architecture.mmd +17 -0
  7. package/diagrams/architecture.svg +2 -0
  8. package/docs/README.md +12 -12
  9. package/docs/_brand.json +18 -0
  10. package/docs/_cover.md +1 -1
  11. package/docs/_topbar.md +1 -1
  12. package/docs/_version.json +3 -3
  13. package/docs/api/reference.md +8 -8
  14. package/docs/architecture.md +6 -84
  15. package/docs/diagrams/component-diagram.excalidraw +2807 -0
  16. package/docs/diagrams/component-diagram.mmd +14 -0
  17. package/docs/diagrams/component-diagram.svg +2 -0
  18. package/docs/diagrams/component-stack.excalidraw +1169 -0
  19. package/docs/diagrams/component-stack.mmd +6 -0
  20. package/docs/diagrams/component-stack.svg +2 -0
  21. package/docs/diagrams/hook-execution-order.excalidraw +3230 -0
  22. package/docs/diagrams/hook-execution-order.mmd +19 -0
  23. package/docs/diagrams/hook-execution-order.svg +2 -0
  24. package/docs/diagrams/initialization-flow.excalidraw +1800 -0
  25. package/docs/diagrams/initialization-flow.mmd +22 -0
  26. package/docs/diagrams/initialization-flow.svg +2 -0
  27. package/docs/index.html +6 -7
  28. package/docs/lifecycle-hooks.md +2 -21
  29. package/docs/retold-catalog.json +141 -141
  30. package/docs/retold-keyword-index.json +6818 -1608
  31. package/package.json +130 -96
  32. package/source/services/RetoldDataService-Brand.js +13 -0
  33. package/source/services/comprehension-loader/pict-app/Pict-Application-ComprehensionLoader.js +65 -15
  34. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Layout.js +28 -74
  35. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Load.js +17 -17
  36. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-SettingsPanel.js +62 -0
  37. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-Shell.js +142 -0
  38. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-StatusBar.js +125 -0
  39. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-StatusDetail.js +89 -0
  40. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-TopBar-Nav.js +42 -0
  41. package/source/services/comprehension-loader/pict-app/views/PictView-ComprehensionLoader-TopBar-User.js +48 -0
  42. package/source/services/comprehension-loader/web/comprehension-loader.js +5415 -6183
  43. package/source/services/comprehension-loader/web/comprehension-loader.js.map +1 -1
  44. package/source/services/comprehension-loader/web/comprehension-loader.min.js +75 -1
  45. package/source/services/comprehension-loader/web/comprehension-loader.min.js.map +1 -1
  46. package/source/services/comprehension-loader/web/favicons/favicon-dark.svg +13 -0
  47. package/source/services/comprehension-loader/web/favicons/favicon-light.svg +13 -0
  48. package/source/services/comprehension-loader/web/favicons/favicon.svg +13 -0
  49. package/source/services/comprehension-loader/web/index.html +3 -0
  50. package/source/services/comprehension-loader/web/pict.min.js +12 -0
  51. package/source/services/data-cloner/DataCloner-Command-Headless.js +2 -1
  52. package/source/services/data-cloner/DataCloner-Command-Sync.js +110 -75
  53. package/source/services/data-cloner/pict-app/Pict-Application-DataCloner.js +70 -47
  54. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Export.js +3 -3
  55. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Layout.js +40 -86
  56. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-SettingsPanel.js +61 -0
  57. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Shell.js +136 -0
  58. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-StatusBar.js +117 -0
  59. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-StatusDetail.js +81 -0
  60. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-Sync.js +18 -18
  61. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-TopBar-Nav.js +42 -0
  62. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-TopBar-User.js +48 -0
  63. package/source/services/data-cloner/pict-app/views/PictView-DataCloner-ViewData.js +2 -2
  64. package/source/services/data-cloner/web/data-cloner.js +5772 -7986
  65. package/source/services/data-cloner/web/data-cloner.js.map +1 -1
  66. package/source/services/data-cloner/web/data-cloner.min.js +75 -1
  67. package/source/services/data-cloner/web/data-cloner.min.js.map +1 -1
  68. package/source/services/data-cloner/web/favicons/favicon-dark.svg +13 -0
  69. package/source/services/data-cloner/web/favicons/favicon-light.svg +13 -0
  70. package/source/services/data-cloner/web/favicons/favicon.svg +13 -0
  71. package/source/services/data-cloner/web/favicons/favicons/favicon-dark.svg +13 -0
  72. package/source/services/data-cloner/web/favicons/favicons/favicon-light.svg +13 -0
  73. package/source/services/data-cloner/web/favicons/favicons/favicon.svg +13 -0
  74. package/source/services/data-cloner/web/index.html +3 -0
  75. package/source/services/data-cloner/web/pict.min.js +12 -0
  76. package/test/Bundles_smoke_tests.js +43 -0
  77. package/test/ComprehensionLoader_smoke_tests.js +95 -0
  78. package/test/DataCloner-RuntimeOverrides_tests.js +344 -0
  79. package/test/DataCloner_smoke_tests.js +87 -0
  80. package/docs/css/docuserve.css +0 -327
@@ -138,7 +138,7 @@ class ComprehensionLoaderLoadView extends libPictView
138
138
 
139
139
  let tmpCardsContainer = document.getElementById('reportSummaryCards');
140
140
  let tmpOutcomeClass = 'outcome-' + pReport.Outcome.toLowerCase();
141
- let tmpOutcomeColor = { Success: '#28a745', Partial: '#ffc107', Error: '#dc3545', Stopped: '#6c757d' }[pReport.Outcome] || '#666';
141
+ let tmpOutcomeColor = { Success: 'var(--theme-color-status-success, #28a745)', Partial: 'var(--theme-color-status-warning, #ffc107)', Error: 'var(--theme-color-status-error, #dc3545)', Stopped: 'var(--theme-color-text-secondary, #6c757d)' }[pReport.Outcome] || 'var(--theme-color-text-secondary, #666)';
142
142
 
143
143
  let tmpDurationSec = pReport.RunTimestamps.DurationSeconds || 0;
144
144
  let tmpDurationStr = tmpDurationSec < 60 ? tmpDurationSec + 's' : Math.floor(tmpDurationSec / 60) + 'm ' + (tmpDurationSec % 60) + 's';
@@ -173,13 +173,13 @@ class ComprehensionLoaderLoadView extends libPictView
173
173
  }
174
174
  else
175
175
  {
176
- let tmpHtml = '<h4 style="margin:0 0 8px; color:#dc3545; font-size:0.95em">Anomalies (' + pReport.Anomalies.length + ')</h4>';
176
+ let tmpHtml = '<h4 style="margin:0 0 8px; color:var(--theme-color-status-error, #dc3545); font-size:0.95em">Anomalies (' + pReport.Anomalies.length + ')</h4>';
177
177
  tmpHtml += '<table class="progress-table">';
178
178
  tmpHtml += '<tr><th>Entity</th><th>Type</th><th>Message</th></tr>';
179
179
  for (let i = 0; i < pReport.Anomalies.length; i++)
180
180
  {
181
181
  let tmpAnomaly = pReport.Anomalies[i];
182
- let tmpTypeColor = tmpAnomaly.Type === 'Error' ? '#dc3545' : '#6c757d';
182
+ let tmpTypeColor = tmpAnomaly.Type === 'Error' ? 'var(--theme-color-status-error, #dc3545)' : 'var(--theme-color-text-secondary, #6c757d)';
183
183
  tmpHtml += '<tr>';
184
184
  tmpHtml += '<td><strong>' + this.pict.providers.ComprehensionLoader.escapeHtml(tmpAnomaly.Entity) + '</strong></td>';
185
185
  tmpHtml += '<td style="color:' + tmpTypeColor + '">' + tmpAnomaly.Type + '</td>';
@@ -202,7 +202,7 @@ class ComprehensionLoaderLoadView extends libPictView
202
202
  let tmpEntity = pReport.Entities[i];
203
203
  let tmpDur = tmpEntity.DurationSeconds < 60 ? tmpEntity.DurationSeconds + 's' : Math.floor(tmpEntity.DurationSeconds / 60) + 'm ' + (tmpEntity.DurationSeconds % 60) + 's';
204
204
  let tmpRecs = this.pict.providers.ComprehensionLoader.formatNumber(tmpEntity.Pushed);
205
- let tmpStatusColor = { Complete: '#28a745', Error: '#dc3545' }[tmpEntity.Status] || '#666';
205
+ let tmpStatusColor = { Complete: 'var(--theme-color-status-success, #28a745)', Error: 'var(--theme-color-status-error, #dc3545)' }[tmpEntity.Status] || 'var(--theme-color-text-secondary, #666)';
206
206
  tmpHtml += '<tr>';
207
207
  tmpHtml += '<td><strong>' + this.pict.providers.ComprehensionLoader.escapeHtml(tmpEntity.Name) + '</strong></td>';
208
208
  tmpHtml += '<td>' + tmpDur + '</td>';
@@ -303,10 +303,10 @@ class ComprehensionLoaderLoadView extends libPictView
303
303
  tmpPct = Math.round((pEntity.Pushed / pEntity.Total) * 100);
304
304
  }
305
305
 
306
- let tmpBarColor = '#28a745';
307
- if (pEntity.Status === 'Error') tmpBarColor = '#dc3545';
308
- else if (pEntity.Status === 'Pushing') tmpBarColor = '#4a90d9';
309
- else if (pEntity.Status === 'Pending') tmpBarColor = '#adb5bd';
306
+ let tmpBarColor = 'var(--theme-color-status-success, #28a745)';
307
+ if (pEntity.Status === 'Error') tmpBarColor = 'var(--theme-color-status-error, #dc3545)';
308
+ else if (pEntity.Status === 'Pushing') tmpBarColor = 'var(--theme-color-brand-primary, #4a90d9)';
309
+ else if (pEntity.Status === 'Pending') tmpBarColor = 'var(--theme-color-text-muted, #adb5bd)';
310
310
 
311
311
  let tmpRow = '<tr>';
312
312
  tmpRow += '<td><strong>' + pName + '</strong></td>';
@@ -395,24 +395,24 @@ module.exports.default_configuration =
395
395
  CSS: /*css*/`
396
396
  .progress-table { width: 100%; border-collapse: collapse; margin-top: 4px; margin-bottom: 4px; }
397
397
  .progress-table th, .progress-table td { text-align: left; padding: 6px 12px; border-bottom: 1px solid var(--theme-color-border-light, #eee); font-size: 0.9em; }
398
- .progress-table th { background: #f8f9fa; font-weight: 600; }
399
- .progress-table-muted td { color: var(--theme-color-text-muted, #888); padding: 3px 12px; font-size: 0.85em; border-bottom: 1px solid #f4f5f6; }
400
- .progress-bar-container { width: 120px; height: 16px; background: #e9ecef; border-radius: 8px; overflow: hidden; display: inline-block; vertical-align: middle; }
398
+ .progress-table th { background: var(--theme-color-background-secondary, #f8f9fa); font-weight: 600; }
399
+ .progress-table-muted td { color: var(--theme-color-text-muted, #888); padding: 3px 12px; font-size: 0.85em; border-bottom: 1px solid var(--theme-color-background-secondary, #f4f5f6); }
400
+ .progress-bar-container { width: 120px; height: 16px; background: var(--theme-color-background-tertiary, #e9ecef); border-radius: 8px; overflow: hidden; display: inline-block; vertical-align: middle; }
401
401
  .progress-bar-fill { height: 100%; background: var(--theme-color-status-success, #28a745); transition: width 0.3s; }
402
- .sync-section-header { font-size: 0.8em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: #4a90d9; padding: 10px 0 2px 0; margin-top: 6px; border-top: 1px solid var(--theme-color-border-default, #e0e0e0); }
402
+ .sync-section-header { font-size: 0.8em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--theme-color-brand-primary, #4a90d9); padding: 10px 0 2px 0; margin-top: 6px; border-top: 1px solid var(--theme-color-border-default, #e0e0e0); }
403
403
  .sync-section-header:first-child { border-top: none; margin-top: 10px; }
404
- .sync-section-header-error { color: #dc3545; }
404
+ .sync-section-header-error { color: var(--theme-color-status-error, #dc3545); }
405
405
  .sync-section-header-ok { color: var(--theme-color-status-success, #28a745); }
406
406
  .sync-section-count { font-weight: 400; color: var(--theme-color-text-muted, #999); font-size: 0.95em; }
407
407
  .sync-section-overflow { font-size: 0.8em; color: var(--theme-color-text-muted, #aaa); padding: 2px 12px 6px; }
408
408
  .sync-pending-count { text-align: right; color: var(--theme-color-text-muted, #aaa); font-size: 0.85em; }
409
- .report-card { background: #f8f9fa; border-radius: 8px; padding: 12px 16px; min-width: 140px; text-align: center; border: 1px solid #e9ecef; }
409
+ .report-card { background: var(--theme-color-background-secondary, #f8f9fa); border-radius: 8px; padding: 12px 16px; min-width: 140px; text-align: center; border: 1px solid var(--theme-color-background-tertiary, #e9ecef); }
410
410
  .report-card .card-label { font-size: 0.8em; color: var(--theme-color-text-secondary, #666); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
411
411
  .report-card .card-value { font-size: 1.4em; font-weight: 700; }
412
412
  .report-card.outcome-success { border-left: 4px solid var(--theme-color-status-success, #28a745); }
413
- .report-card.outcome-partial { border-left: 4px solid #ffc107; }
414
- .report-card.outcome-error { border-left: 4px solid #dc3545; }
415
- .report-card.outcome-stopped { border-left: 4px solid #6c757d; }
413
+ .report-card.outcome-partial { border-left: 4px solid var(--theme-color-status-warning, #ffc107); }
414
+ .report-card.outcome-error { border-left: 4px solid var(--theme-color-status-error, #dc3545); }
415
+ .report-card.outcome-stopped { border-left: 4px solid var(--theme-color-text-secondary, #6c757d); }
416
416
  `,
417
417
  Templates:
418
418
  [
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ const libPictView = require('pict-view');
4
+
5
+ class ComprehensionLoaderSettingsPanelView extends libPictView
6
+ {
7
+ onAfterRender(pRenderable, pAddress, pRecord, pContent)
8
+ {
9
+ if (this.pict.CSSMap) { this.pict.CSSMap.injectCSS(); }
10
+
11
+ // Re-mount theme controls on every render — the template wipes the destination div.
12
+ let tmpTheme = this.pict.providers && this.pict.providers['Theme-Section'];
13
+ if (tmpTheme && typeof tmpTheme.mount === 'function')
14
+ {
15
+ tmpTheme.mount({
16
+ Container: '#ComprehensionLoader-Settings-Theme',
17
+ Views: ['Picker', 'ModeToggle', 'ScaleSelect']
18
+ });
19
+ }
20
+ return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
21
+ }
22
+ }
23
+
24
+ module.exports = ComprehensionLoaderSettingsPanelView;
25
+
26
+ module.exports.default_configuration =
27
+ {
28
+ ViewIdentifier: 'ComprehensionLoader-SettingsPanel',
29
+ DefaultRenderable: 'ComprehensionLoader-SettingsPanel',
30
+ DefaultDestinationAddress: '#ComprehensionLoader-Settings-Panel',
31
+ AutoRender: false,
32
+ CSS: /*css*/`
33
+ .rds-settings-body {
34
+ padding: 12px;
35
+ display: flex; flex-direction: column; gap: 16px;
36
+ color: var(--theme-color-text-primary, #333333);
37
+ }
38
+ .rds-settings-section { display: flex; flex-direction: column; gap: 6px; }
39
+ .rds-settings-label {
40
+ font-size: 0.85em;
41
+ font-weight: 600;
42
+ text-transform: uppercase;
43
+ letter-spacing: 0.04em;
44
+ color: var(--theme-color-text-secondary, #555555);
45
+ }
46
+ `,
47
+ Templates: [{
48
+ Hash: 'ComprehensionLoader-SettingsPanel',
49
+ Template: /*html*/`
50
+ <div class="rds-settings-body">
51
+ <div class="rds-settings-section">
52
+ <div class="rds-settings-label">Appearance</div>
53
+ <div id="ComprehensionLoader-Settings-Theme"></div>
54
+ </div>
55
+ </div>`
56
+ }],
57
+ Renderables: [{
58
+ RenderableHash: 'ComprehensionLoader-SettingsPanel',
59
+ TemplateHash: 'ComprehensionLoader-SettingsPanel',
60
+ DestinationAddress: '#ComprehensionLoader-Settings-Panel'
61
+ }]
62
+ };
@@ -0,0 +1,142 @@
1
+ 'use strict';
2
+
3
+ const libPictView = require('pict-view');
4
+
5
+ class ComprehensionLoaderShellView extends libPictView
6
+ {
7
+ constructor(pFable, pOptions, pServiceHash)
8
+ {
9
+ super(pFable, pOptions, pServiceHash);
10
+ this._shellPanelsBuilt = false;
11
+ }
12
+
13
+ onAfterRender(pRenderable, pAddress, pRecord, pContent)
14
+ {
15
+ if (this.pict.CSSMap) { this.pict.CSSMap.injectCSS(); }
16
+ if (!this._shellPanelsBuilt)
17
+ {
18
+ this._buildShell();
19
+ this._shellPanelsBuilt = true;
20
+ }
21
+ return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
22
+ }
23
+
24
+ _buildShell()
25
+ {
26
+ let tmpModal = this.pict.views['Pict-Section-Modal'];
27
+ let tmpMount = document.getElementById('ComprehensionLoader-Shell-Mount');
28
+ if (!tmpModal || typeof tmpModal.shell !== 'function' || !tmpMount)
29
+ {
30
+ this.log.warn('ComprehensionLoader-Shell: Pict-Section-Modal or mount not available; shell not built.');
31
+ return;
32
+ }
33
+
34
+ this._shell = tmpModal.shell(tmpMount, { PersistenceKey: 'comprehension-loader-shell' });
35
+
36
+ // Top — Theme-TopBar (BrandMark + Nav + User slots)
37
+ this._shell.addPanel({
38
+ Hash: 'topbar', Side: 'top', Mode: 'fixed', Size: 56,
39
+ ContentDestinationId: 'Theme-TopBar', ContentView: 'Theme-TopBar'
40
+ });
41
+
42
+ // Bottom — Theme-BottomBar (StatusView slot)
43
+ this._shell.addPanel({
44
+ Hash: 'bottombar', Side: 'bottom', Mode: 'fixed', Size: 36,
45
+ ContentDestinationId: 'Theme-BottomBar', ContentView: 'Theme-BottomBar'
46
+ });
47
+
48
+ // Bottom (hidden overlay) — status detail expansion
49
+ this._shell.addPanel({
50
+ Hash: 'status-detail', Side: 'bottom', Mode: 'resizable', Position: 'overlay',
51
+ Size: 320, MinSize: 200, MaxSize: 480,
52
+ Hidden: true, Collapsed: true, Title: 'Status Detail',
53
+ ContentDestinationId: 'ComprehensionLoader-StatusDetail-Panel',
54
+ ContentView: 'ComprehensionLoader-StatusDetail'
55
+ });
56
+
57
+ // Right (hidden overlay) — settings
58
+ this._shell.addPanel({
59
+ Hash: 'settings', Side: 'right', Mode: 'resizable', Position: 'overlay',
60
+ Size: 360, MinSize: 280, MaxSize: 540,
61
+ Hidden: true, Collapsed: true, Title: 'Settings',
62
+ ContentDestinationId: 'ComprehensionLoader-Settings-Panel',
63
+ ContentView: 'ComprehensionLoader-SettingsPanel'
64
+ });
65
+
66
+ // Center — the workspace (existing Layout renders here)
67
+ this._shell.center({ ContentDestinationId: 'ComprehensionLoader-Workspace' });
68
+ }
69
+
70
+ getSettingsPanel() { return this._shell ? this._shell.getPanel('settings') : null; }
71
+ getStatusDetailPanel() { return this._shell ? this._shell.getPanel('status-detail') : null; }
72
+
73
+ toggleSettingsPanel()
74
+ {
75
+ let tmpPanel = this.getSettingsPanel();
76
+ if (tmpPanel) { tmpPanel.toggle(); }
77
+ }
78
+
79
+ toggleStatusDetail()
80
+ {
81
+ let tmpPanel = this.getStatusDetailPanel();
82
+ if (!tmpPanel) { return; }
83
+ tmpPanel.toggle();
84
+
85
+ // Notify the provider so it can start/stop the higher-frequency detail poll.
86
+ let tmpProvider = this.pict.providers.ComprehensionLoader;
87
+ let tmpOpen = !tmpPanel.Collapsed;
88
+ if (tmpProvider && tmpOpen && typeof tmpProvider.onStatusDetailExpanded === 'function')
89
+ {
90
+ tmpProvider.onStatusDetailExpanded();
91
+ }
92
+ else if (tmpProvider && !tmpOpen && typeof tmpProvider.onStatusDetailCollapsed === 'function')
93
+ {
94
+ tmpProvider.onStatusDetailCollapsed();
95
+ }
96
+ }
97
+
98
+ renderTopBar()
99
+ {
100
+ let tmpNav = this.pict.views['ComprehensionLoader-TopBar-Nav'];
101
+ let tmpUser = this.pict.views['ComprehensionLoader-TopBar-User'];
102
+ if (tmpNav) { tmpNav.render(); }
103
+ if (tmpUser) { tmpUser.render(); }
104
+ }
105
+ }
106
+
107
+ module.exports = ComprehensionLoaderShellView;
108
+
109
+ module.exports.default_configuration =
110
+ {
111
+ ViewIdentifier: 'ComprehensionLoader-Shell',
112
+ DefaultRenderable: 'ComprehensionLoader-Shell',
113
+ DefaultDestinationAddress: '#ComprehensionLoader-Application-Container',
114
+ AutoRender: false,
115
+ CSS: /*css*/`
116
+ html, body { height: 100%; margin: 0; padding: 0; }
117
+ body {
118
+ background: var(--theme-color-background-primary, #f5f5f5);
119
+ color: var(--theme-color-text-primary, #333333);
120
+ font-family: var(--theme-typography-family-sans,
121
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif);
122
+ }
123
+ #ComprehensionLoader-Application-Container { height: 100%; min-height: 0; overflow: hidden; }
124
+ .pict-modal-shell-host { height: 100%; }
125
+ .pict-modal-shell { background: var(--theme-color-background-primary, #f5f5f5); }
126
+ .pict-modal-shell-panel { background: var(--theme-color-background-panel, #ffffff); }
127
+ .pict-modal-shell-center {
128
+ background: var(--theme-color-background-primary, #f5f5f5);
129
+ overflow: auto;
130
+ padding: 20px;
131
+ }
132
+ `,
133
+ Templates: [{
134
+ Hash: 'ComprehensionLoader-Shell',
135
+ Template: /*html*/`<div id="ComprehensionLoader-Shell-Mount" style="height:100%"></div>`
136
+ }],
137
+ Renderables: [{
138
+ RenderableHash: 'ComprehensionLoader-Shell',
139
+ TemplateHash: 'ComprehensionLoader-Shell',
140
+ DestinationAddress: '#ComprehensionLoader-Application-Container'
141
+ }]
142
+ };
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ const libPictView = require('pict-view');
4
+
5
+ /**
6
+ * StatusBar — renders into Theme-BottomBar's #Theme-BottomBar-Status slot.
7
+ *
8
+ * Markup preserves the same element ids (#liveStatusBar, #liveStatusMessage,
9
+ * #liveStatusMeta, #liveStatusProgressFill) that the provider's existing
10
+ * renderLiveStatus() poll handler manipulates by id — so the provider's
11
+ * imperative DOM update flow keeps working untouched.
12
+ */
13
+ class ComprehensionLoaderStatusBarView extends libPictView
14
+ {
15
+ onAfterRender(pRenderable, pAddress, pRecord, pContent)
16
+ {
17
+ if (this.pict.CSSMap) { this.pict.CSSMap.injectCSS(); }
18
+ return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
19
+ }
20
+ }
21
+
22
+ module.exports = ComprehensionLoaderStatusBarView;
23
+
24
+ module.exports.default_configuration =
25
+ {
26
+ ViewIdentifier: 'ComprehensionLoader-StatusBar',
27
+ DefaultRenderable: 'ComprehensionLoader-StatusBar',
28
+ DefaultDestinationAddress: '#Theme-BottomBar-Status',
29
+ AutoRender: false,
30
+ CSS: /*css*/`
31
+ .rds-status-bar {
32
+ display: flex; align-items: center; gap: 12px;
33
+ height: 100%; padding: 0 12px;
34
+ color: var(--theme-color-text-primary, #333333);
35
+ font-size: 0.88em;
36
+ border-top: 1px solid var(--theme-color-border-light, #e9e9e9);
37
+ border-left: 3px solid var(--theme-color-text-secondary, #6c757d);
38
+ position: relative;
39
+ }
40
+ .rds-status-bar.phase-idle { border-left-color: var(--theme-color-text-secondary, #6c757d); }
41
+ .rds-status-bar.phase-disconnected { border-left-color: var(--theme-color-status-error, #dc3545); }
42
+ .rds-status-bar.phase-ready { border-left-color: var(--theme-color-brand-primary, #4a90d9); }
43
+ .rds-status-bar.phase-loading { border-left-color: var(--theme-color-status-success, #28a745); }
44
+ .rds-status-bar.phase-stopping { border-left-color: var(--theme-color-status-warning, #ffc107); }
45
+ .rds-status-bar.phase-complete { border-left-color: var(--theme-color-status-success, #28a745); }
46
+
47
+ .rds-status-dot {
48
+ width: 10px; height: 10px; border-radius: 50%;
49
+ flex-shrink: 0;
50
+ background: var(--theme-color-text-secondary, #6c757d);
51
+ }
52
+ .rds-status-bar.phase-idle .rds-status-dot { background: var(--theme-color-text-secondary, #6c757d); }
53
+ .rds-status-bar.phase-disconnected .rds-status-dot { background: var(--theme-color-status-error, #dc3545); }
54
+ .rds-status-bar.phase-ready .rds-status-dot { background: var(--theme-color-brand-primary, #4a90d9); }
55
+ .rds-status-bar.phase-loading .rds-status-dot {
56
+ background: var(--theme-color-status-success, #28a745);
57
+ animation: rds-status-pulse 1.5s ease-in-out infinite;
58
+ }
59
+ .rds-status-bar.phase-stopping .rds-status-dot {
60
+ background: var(--theme-color-status-warning, #ffc107);
61
+ animation: rds-status-pulse 0.8s ease-in-out infinite;
62
+ }
63
+ .rds-status-bar.phase-complete .rds-status-dot { background: var(--theme-color-status-success, #28a745); }
64
+
65
+ @keyframes rds-status-pulse {
66
+ 0%, 100% { opacity: 1; transform: scale(1); }
67
+ 50% { opacity: 0.4; transform: scale(0.8); }
68
+ }
69
+
70
+ .rds-status-message { flex: 1; line-height: 1.2; }
71
+ .rds-status-meta {
72
+ display: flex; gap: 12px; flex-shrink: 0;
73
+ font-size: 0.92em; color: var(--theme-color-text-secondary, #666);
74
+ }
75
+ .rds-status-meta .live-status-meta-item { white-space: nowrap; }
76
+ .rds-status-meta .live-status-meta-item strong { color: var(--theme-color-text-primary, #333); }
77
+
78
+ .rds-status-detail-btn {
79
+ padding: 2px 8px;
80
+ background: transparent;
81
+ border: 1px solid var(--theme-color-border-default, #ccc);
82
+ border-radius: 3px;
83
+ color: var(--theme-color-text-secondary, #666);
84
+ cursor: pointer;
85
+ font-size: 0.92em;
86
+ line-height: 1;
87
+ }
88
+ .rds-status-detail-btn:hover {
89
+ background: var(--theme-color-background-hover, #f0f0f0);
90
+ color: var(--theme-color-text-primary, #333);
91
+ }
92
+
93
+ .rds-status-progress-bar {
94
+ position: absolute; left: 0; right: 0; bottom: 0;
95
+ height: 2px;
96
+ background: var(--theme-color-background-tertiary, #e9ecef);
97
+ overflow: hidden;
98
+ }
99
+ .rds-status-progress-fill {
100
+ height: 100%;
101
+ background: var(--theme-color-status-success, #28a745);
102
+ transition: width 1s ease;
103
+ }
104
+ `,
105
+ Templates: [{
106
+ Hash: 'ComprehensionLoader-StatusBar',
107
+ Template: /*html*/`
108
+ <div id="liveStatusBar" class="rds-status-bar phase-idle">
109
+ <div class="rds-status-dot live-status-dot"></div>
110
+ <div id="liveStatusMessage" class="rds-status-message live-status-message">Idle</div>
111
+ <div id="liveStatusMeta" class="rds-status-meta live-status-meta"></div>
112
+ <button class="rds-status-detail-btn"
113
+ onclick="_Pict.views['ComprehensionLoader-Shell'].toggleStatusDetail()"
114
+ title="Show detail">Detail</button>
115
+ <div class="rds-status-progress-bar live-status-progress-bar">
116
+ <div id="liveStatusProgressFill" class="rds-status-progress-fill live-status-progress-fill" style="width:0%"></div>
117
+ </div>
118
+ </div>`
119
+ }],
120
+ Renderables: [{
121
+ RenderableHash: 'ComprehensionLoader-StatusBar',
122
+ TemplateHash: 'ComprehensionLoader-StatusBar',
123
+ DestinationAddress: '#Theme-BottomBar-Status'
124
+ }]
125
+ };
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ const libPictView = require('pict-view');
4
+
5
+ /**
6
+ * StatusDetail — content for the expandable bottom overlay panel.
7
+ *
8
+ * Renders the throughput histogram slot and the running-ops / completed-ops /
9
+ * errors detail container, both of which the existing provider populates by
10
+ * direct DOM manipulation. The element ids (#X-Throughput-Histogram,
11
+ * #X-StatusDetail-Container) are preserved so the provider keeps working.
12
+ */
13
+ class ComprehensionLoaderStatusDetailView extends libPictView
14
+ {
15
+ onAfterRender(pRenderable, pAddress, pRecord, pContent)
16
+ {
17
+ if (this.pict.CSSMap) { this.pict.CSSMap.injectCSS(); }
18
+ return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
19
+ }
20
+ }
21
+
22
+ module.exports = ComprehensionLoaderStatusDetailView;
23
+
24
+ module.exports.default_configuration =
25
+ {
26
+ ViewIdentifier: 'ComprehensionLoader-StatusDetail',
27
+ DefaultRenderable: 'ComprehensionLoader-StatusDetail',
28
+ DefaultDestinationAddress: '#ComprehensionLoader-StatusDetail-Panel',
29
+ AutoRender: false,
30
+ CSS: /*css*/`
31
+ .rds-status-detail-body {
32
+ padding: 12px 20px 16px;
33
+ max-height: 100%;
34
+ overflow-y: auto;
35
+ color: var(--theme-color-text-primary, #333);
36
+ }
37
+ .rds-status-detail-section { margin-bottom: 14px; }
38
+ .rds-status-detail-section:last-child { margin-bottom: 0; }
39
+ .rds-status-detail-section-title {
40
+ font-size: 0.85em; font-weight: 600;
41
+ color: var(--theme-color-text-secondary, #555);
42
+ text-transform: uppercase; letter-spacing: 0.5px;
43
+ margin-bottom: 8px; padding-bottom: 4px;
44
+ border-bottom: 1px solid var(--theme-color-border-light, #eee);
45
+ }
46
+ .running-op-row { display: flex; align-items: center; gap: 12px; padding: 6px 0; font-size: 0.9em; }
47
+ .running-op-name { font-weight: 600; min-width: 180px; }
48
+ .running-op-bar {
49
+ flex: 1; height: 8px;
50
+ background: var(--theme-color-background-tertiary, #e9ecef);
51
+ border-radius: 4px; overflow: hidden; min-width: 120px;
52
+ }
53
+ .running-op-bar-fill {
54
+ height: 100%;
55
+ background: var(--theme-color-brand-primary, #4a90d9);
56
+ transition: width 0.5s ease;
57
+ }
58
+ .running-op-count { font-size: 0.85em; color: var(--theme-color-text-secondary, #666); white-space: nowrap; }
59
+ .running-op-pending { color: var(--theme-color-text-muted, #888); font-size: 0.85em; font-style: italic; padding: 4px 0; }
60
+ .completed-op-row { padding: 8px 0; border-bottom: 1px solid var(--theme-color-background-tertiary, #f0f0f0); }
61
+ .completed-op-row:last-child { border-bottom: none; }
62
+ .completed-op-header { display: flex; align-items: center; gap: 10px; font-size: 0.9em; margin-bottom: 4px; }
63
+ .completed-op-name { font-weight: 600; }
64
+ .completed-op-stats { color: var(--theme-color-text-secondary, #666); font-size: 0.85em; }
65
+ .completed-op-checkmark { color: var(--theme-color-status-success, #28a745); }
66
+ .error-op-row { padding: 6px 0; border-bottom: 1px solid var(--theme-color-background-tertiary, #f0f0f0); font-size: 0.9em; }
67
+ .error-op-row:last-child { border-bottom: none; }
68
+ .error-op-header { display: flex; align-items: center; gap: 8px; }
69
+ .error-op-name { font-weight: 600; color: var(--theme-color-status-error, #dc3545); }
70
+ .error-op-status { font-size: 0.82em; color: var(--theme-color-status-error, #dc3545); }
71
+ .error-op-message { font-size: 0.82em; color: var(--theme-color-text-muted, #888); margin-top: 2px; padding-left: 18px; }
72
+ `,
73
+ Templates: [{
74
+ Hash: 'ComprehensionLoader-StatusDetail',
75
+ Template: /*html*/`
76
+ <div class="rds-status-detail-body">
77
+ <div class="rds-status-detail-section">
78
+ <div class="rds-status-detail-section-title">Throughput</div>
79
+ <div id="ComprehensionLoader-Throughput-Histogram" style="height:120px"></div>
80
+ </div>
81
+ <div id="ComprehensionLoader-StatusDetail-Container"></div>
82
+ </div>`
83
+ }],
84
+ Renderables: [{
85
+ RenderableHash: 'ComprehensionLoader-StatusDetail',
86
+ TemplateHash: 'ComprehensionLoader-StatusDetail',
87
+ DestinationAddress: '#ComprehensionLoader-StatusDetail-Panel'
88
+ }]
89
+ };
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ const libPictView = require('pict-view');
4
+
5
+ class ComprehensionLoaderTopBarNavView extends libPictView
6
+ {
7
+ onAfterRender(pRenderable, pAddress, pRecord, pContent)
8
+ {
9
+ if (this.pict.CSSMap) { this.pict.CSSMap.injectCSS(); }
10
+ return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
11
+ }
12
+ }
13
+
14
+ module.exports = ComprehensionLoaderTopBarNavView;
15
+
16
+ module.exports.default_configuration =
17
+ {
18
+ ViewIdentifier: 'ComprehensionLoader-TopBar-Nav',
19
+ DefaultRenderable: 'ComprehensionLoader-TopBar-Nav',
20
+ DefaultDestinationAddress: '#Theme-TopBar-Nav',
21
+ AutoRender: false,
22
+ CSS: /*css*/`
23
+ .rds-nav {
24
+ display: flex; align-items: center; height: 100%;
25
+ padding: 0 12px; gap: 8px;
26
+ color: var(--theme-color-text-on-brand,
27
+ var(--theme-color-text-primary, #1a1a1a));
28
+ font-weight: 500;
29
+ }
30
+ .rds-nav-sep { opacity: 0.5; font-weight: 400; margin: 0 2px; }
31
+ .rds-nav-app { font-weight: 600; opacity: 0.95; }
32
+ `,
33
+ Templates: [{
34
+ Hash: 'ComprehensionLoader-TopBar-Nav',
35
+ Template: /*html*/`<div class="rds-nav"><span class="rds-nav-sep">·</span><span class="rds-nav-app">Comprehension Loader</span></div>`
36
+ }],
37
+ Renderables: [{
38
+ RenderableHash: 'ComprehensionLoader-TopBar-Nav',
39
+ TemplateHash: 'ComprehensionLoader-TopBar-Nav',
40
+ DestinationAddress: '#Theme-TopBar-Nav'
41
+ }]
42
+ };
@@ -0,0 +1,48 @@
1
+ 'use strict';
2
+
3
+ const libPictView = require('pict-view');
4
+
5
+ class ComprehensionLoaderTopBarUserView extends libPictView
6
+ {
7
+ onAfterRender(pRenderable, pAddress, pRecord, pContent)
8
+ {
9
+ if (this.pict.CSSMap) { this.pict.CSSMap.injectCSS(); }
10
+ return super.onAfterRender(pRenderable, pAddress, pRecord, pContent);
11
+ }
12
+ }
13
+
14
+ module.exports = ComprehensionLoaderTopBarUserView;
15
+
16
+ module.exports.default_configuration =
17
+ {
18
+ ViewIdentifier: 'ComprehensionLoader-TopBar-User',
19
+ DefaultRenderable: 'ComprehensionLoader-TopBar-User',
20
+ DefaultDestinationAddress: '#Theme-TopBar-User',
21
+ AutoRender: false,
22
+ CSS: /*css*/`
23
+ .rds-user { display: flex; align-items: center; height: 100%; gap: 8px; padding: 0 12px; }
24
+ .rds-user-btn {
25
+ padding: 4px 8px;
26
+ border: 1px solid var(--theme-color-border-default, #5E5549);
27
+ background: transparent;
28
+ color: var(--theme-color-text-on-brand,
29
+ var(--theme-color-text-secondary, #1a1a1a));
30
+ border-radius: 4px;
31
+ cursor: pointer;
32
+ display: inline-flex; align-items: center; justify-content: center;
33
+ font-size: 1em; line-height: 1;
34
+ }
35
+ .rds-user-btn:hover {
36
+ background: var(--theme-color-background-hover, rgba(255,255,255,0.08));
37
+ }
38
+ `,
39
+ Templates: [{
40
+ Hash: 'ComprehensionLoader-TopBar-User',
41
+ Template: /*html*/`<div class="rds-user"><button class="rds-user-btn" onclick="_Pict.views['ComprehensionLoader-Shell'].toggleSettingsPanel()" title="Settings" aria-label="Settings">{~I:Settings~}</button></div>`
42
+ }],
43
+ Renderables: [{
44
+ RenderableHash: 'ComprehensionLoader-TopBar-User',
45
+ TemplateHash: 'ComprehensionLoader-TopBar-User',
46
+ DestinationAddress: '#Theme-TopBar-User'
47
+ }]
48
+ };