ultravisor 1.0.0 → 1.0.2

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 (96) hide show
  1. package/.babelrc +6 -0
  2. package/.browserslistrc +1 -0
  3. package/.browserslistrc-BACKUP +1 -0
  4. package/.gulpfile-quackage-config.json +7 -0
  5. package/.gulpfile-quackage.js +2 -0
  6. package/CONTRIBUTING.md +50 -0
  7. package/README.md +34 -0
  8. package/debug/Harness.js +2 -1
  9. package/docs/.nojekyll +0 -0
  10. package/docs/_sidebar.md +18 -0
  11. package/docs/_topbar.md +7 -0
  12. package/docs/architecture.md +103 -0
  13. package/docs/cover.md +15 -0
  14. package/docs/features/api.md +230 -0
  15. package/docs/features/cli.md +182 -0
  16. package/docs/features/configuration.md +245 -0
  17. package/docs/features/manifests.md +177 -0
  18. package/docs/features/operations.md +292 -0
  19. package/docs/features/scheduling.md +179 -0
  20. package/docs/features/tasks.md +1857 -0
  21. package/docs/index.html +39 -0
  22. package/docs/overview.md +75 -0
  23. package/docs/quickstart.md +167 -0
  24. package/docs/retold-catalog.json +24 -0
  25. package/docs/retold-keyword-index.json +19 -0
  26. package/package.json +5 -2
  27. package/source/Ultravisor.cjs +2 -2
  28. package/source/cli/Ultravisor-CLIProgram.cjs +38 -0
  29. package/source/cli/commands/Ultravisor-Command-ScheduleOperation.cjs +26 -2
  30. package/source/cli/commands/Ultravisor-Command-ScheduleTask.cjs +26 -2
  31. package/source/cli/commands/Ultravisor-Command-ScheduleView.cjs +22 -0
  32. package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +49 -1
  33. package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +51 -1
  34. package/source/cli/commands/Ultravisor-Command-Stop.cjs +4 -0
  35. package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +91 -0
  36. package/source/config/Ultravisor-Default-Command-Configuration.cjs +6 -1
  37. package/source/services/Ultravisor-Hypervisor-Event-Base.cjs +18 -1
  38. package/source/services/Ultravisor-Hypervisor-State.cjs +213 -0
  39. package/source/services/Ultravisor-Hypervisor.cjs +225 -1
  40. package/source/services/Ultravisor-Operation-Manifest.cjs +150 -1
  41. package/source/services/Ultravisor-Operation.cjs +190 -1
  42. package/source/services/Ultravisor-Task.cjs +339 -1
  43. package/source/services/events/Ultravisor-Hypervisor-Event-Cron.cjs +71 -1
  44. package/source/services/tasks/Ultravisor-Task-Base.cjs +264 -0
  45. package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +188 -0
  46. package/source/services/tasks/Ultravisor-Task-Command.cjs +65 -0
  47. package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +190 -0
  48. package/source/services/tasks/Ultravisor-Task-Conditional.cjs +104 -0
  49. package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +72 -0
  50. package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +336 -0
  51. package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +143 -0
  52. package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +146 -0
  53. package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +158 -0
  54. package/source/services/tasks/Ultravisor-Task-Request.cjs +56 -0
  55. package/source/services/tasks/Ultravisor-Task-Solver.cjs +89 -0
  56. package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +93 -0
  57. package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +127 -0
  58. package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +119 -0
  59. package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +109 -0
  60. package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +112 -0
  61. package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +499 -0
  62. package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +150 -0
  63. package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +110 -0
  64. package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +89 -0
  65. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +87 -0
  66. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +67 -0
  67. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +66 -0
  68. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +69 -0
  69. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +95 -0
  70. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +96 -0
  71. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +99 -0
  72. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +102 -0
  73. package/source/web_server/Ultravisor-API-Server.cjs +463 -3
  74. package/test/Ultravisor_tests.js +6097 -1
  75. package/webinterface/.babelrc +6 -0
  76. package/webinterface/.browserslistrc +1 -0
  77. package/webinterface/.browserslistrc-BACKUP +1 -0
  78. package/webinterface/.gulpfile-quackage-config.json +7 -0
  79. package/webinterface/.gulpfile-quackage.js +2 -0
  80. package/webinterface/css/ultravisor.css +121 -0
  81. package/webinterface/html/index.html +32 -0
  82. package/webinterface/package.json +39 -0
  83. package/webinterface/source/Pict-Application-Ultravisor-Configuration.json +15 -0
  84. package/webinterface/source/Pict-Application-Ultravisor.js +414 -0
  85. package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +42 -0
  86. package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +65 -0
  87. package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +236 -0
  88. package/webinterface/source/views/PictView-Ultravisor-Layout.js +83 -0
  89. package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +273 -0
  90. package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +243 -0
  91. package/webinterface/source/views/PictView-Ultravisor-OperationList.js +141 -0
  92. package/webinterface/source/views/PictView-Ultravisor-Schedule.js +280 -0
  93. package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +220 -0
  94. package/webinterface/source/views/PictView-Ultravisor-TaskList.js +248 -0
  95. package/webinterface/source/views/PictView-Ultravisor-TimingView.js +420 -0
  96. package/webinterface/source/views/PictView-Ultravisor-TopBar.js +147 -0
@@ -0,0 +1,65 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Ultravisor-BottomBar",
6
+
7
+ DefaultRenderable: "Ultravisor-BottomBar-Content",
8
+ DefaultDestinationAddress: "#Ultravisor-BottomBar-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .ultravisor-bottombar {
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ background-color: #0f3460;
18
+ color: #607d8b;
19
+ padding: 0.75em 1.5em;
20
+ font-size: 0.8em;
21
+ border-top: 1px solid #1a4a7a;
22
+ }
23
+ .ultravisor-bottombar a {
24
+ color: #4fc3f7;
25
+ text-decoration: none;
26
+ }
27
+ .ultravisor-bottombar a:hover {
28
+ color: #81d4fa;
29
+ }
30
+ `,
31
+
32
+ Templates:
33
+ [
34
+ {
35
+ Hash: "Ultravisor-BottomBar-Template",
36
+ Template: /*html*/`
37
+ <div class="ultravisor-bottombar">
38
+ Ultravisor Task Server &middot; Retold
39
+ </div>
40
+ `
41
+ }
42
+ ],
43
+
44
+ Renderables:
45
+ [
46
+ {
47
+ RenderableHash: "Ultravisor-BottomBar-Content",
48
+ TemplateHash: "Ultravisor-BottomBar-Template",
49
+ DestinationAddress: "#Ultravisor-BottomBar-Container",
50
+ RenderMethod: "replace"
51
+ }
52
+ ]
53
+ };
54
+
55
+ class UltravisorBottomBarView extends libPictView
56
+ {
57
+ constructor(pFable, pOptions, pServiceHash)
58
+ {
59
+ super(pFable, pOptions, pServiceHash);
60
+ }
61
+ }
62
+
63
+ module.exports = UltravisorBottomBarView;
64
+
65
+ module.exports.default_configuration = _ViewConfiguration;
@@ -0,0 +1,236 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Ultravisor-Dashboard",
6
+
7
+ DefaultRenderable: "Ultravisor-Dashboard-Content",
8
+ DefaultDestinationAddress: "#Ultravisor-Content-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .ultravisor-dashboard {
14
+ padding: 2em;
15
+ max-width: 1200px;
16
+ margin: 0 auto;
17
+ }
18
+ .ultravisor-dashboard-header {
19
+ margin: 0 0 1.5em 0;
20
+ padding-bottom: 1em;
21
+ border-bottom: 1px solid #2a2a4a;
22
+ }
23
+ .ultravisor-dashboard-header h1 {
24
+ margin: 0 0 0.25em 0;
25
+ font-size: 2em;
26
+ font-weight: 300;
27
+ color: #e0e0e0;
28
+ }
29
+ .ultravisor-dashboard-header p {
30
+ margin: 0;
31
+ color: #78909c;
32
+ font-size: 1.1em;
33
+ }
34
+ .ultravisor-dashboard-cards {
35
+ display: grid;
36
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
37
+ gap: 1.25em;
38
+ margin-bottom: 2em;
39
+ }
40
+ .ultravisor-stat-card {
41
+ background: #16213e;
42
+ border: 1px solid #2a2a4a;
43
+ border-radius: 8px;
44
+ padding: 1.25em;
45
+ transition: border-color 0.2s;
46
+ }
47
+ .ultravisor-stat-card:hover {
48
+ border-color: #4fc3f7;
49
+ }
50
+ .ultravisor-stat-card-label {
51
+ font-size: 0.8em;
52
+ color: #78909c;
53
+ text-transform: uppercase;
54
+ letter-spacing: 0.05em;
55
+ margin-bottom: 0.5em;
56
+ }
57
+ .ultravisor-stat-card-value {
58
+ font-size: 2em;
59
+ font-weight: 600;
60
+ color: #4fc3f7;
61
+ }
62
+ .ultravisor-stat-card-value.running {
63
+ color: #66bb6a;
64
+ }
65
+ .ultravisor-stat-card-value.stopped {
66
+ color: #ef5350;
67
+ }
68
+ .ultravisor-dashboard-actions {
69
+ display: flex;
70
+ gap: 0.75em;
71
+ margin-top: 1.5em;
72
+ }
73
+ .ultravisor-btn {
74
+ padding: 0.6em 1.25em;
75
+ border-radius: 4px;
76
+ font-size: 0.9em;
77
+ cursor: pointer;
78
+ border: none;
79
+ transition: background-color 0.15s;
80
+ }
81
+ .ultravisor-btn-primary {
82
+ background-color: #4fc3f7;
83
+ color: #0f3460;
84
+ font-weight: 600;
85
+ }
86
+ .ultravisor-btn-primary:hover {
87
+ background-color: #81d4fa;
88
+ }
89
+ .ultravisor-btn-danger {
90
+ background-color: #ef5350;
91
+ color: #fff;
92
+ font-weight: 600;
93
+ }
94
+ .ultravisor-btn-danger:hover {
95
+ background-color: #e53935;
96
+ }
97
+ .ultravisor-btn-secondary {
98
+ background-color: #37474f;
99
+ color: #e0e0e0;
100
+ }
101
+ .ultravisor-btn-secondary:hover {
102
+ background-color: #455a64;
103
+ }
104
+ .ultravisor-dashboard-section-title {
105
+ font-size: 1.1em;
106
+ font-weight: 600;
107
+ color: #b0bec5;
108
+ margin: 2em 0 1em 0;
109
+ padding-bottom: 0.5em;
110
+ border-bottom: 1px solid #2a2a4a;
111
+ }
112
+ `,
113
+
114
+ Templates:
115
+ [
116
+ {
117
+ Hash: "Ultravisor-Dashboard-Template",
118
+ Template: /*html*/`
119
+ <div class="ultravisor-dashboard">
120
+ <div class="ultravisor-dashboard-header">
121
+ <h1>Dashboard</h1>
122
+ <p>Ultravisor task server status and quick actions.</p>
123
+ </div>
124
+ <div class="ultravisor-dashboard-cards" id="Ultravisor-Dashboard-Cards"></div>
125
+ <div class="ultravisor-dashboard-section-title">Schedule Control</div>
126
+ <div class="ultravisor-dashboard-actions" id="Ultravisor-Dashboard-Actions"></div>
127
+ </div>
128
+ `
129
+ },
130
+ {
131
+ Hash: "Ultravisor-Dashboard-Cards-Template",
132
+ Template: /*html*/`
133
+ <div class="ultravisor-stat-card">
134
+ <div class="ultravisor-stat-card-label">Server Status</div>
135
+ <div class="ultravisor-stat-card-value" id="Ultravisor-Dashboard-StatusValue">{~D:AppData.Ultravisor.ServerStatus.Status~}</div>
136
+ </div>
137
+ <div class="ultravisor-stat-card">
138
+ <div class="ultravisor-stat-card-label">Tasks</div>
139
+ <div class="ultravisor-stat-card-value" id="Ultravisor-Dashboard-TaskCount">--</div>
140
+ </div>
141
+ <div class="ultravisor-stat-card">
142
+ <div class="ultravisor-stat-card-label">Operations</div>
143
+ <div class="ultravisor-stat-card-value" id="Ultravisor-Dashboard-OperationCount">--</div>
144
+ </div>
145
+ <div class="ultravisor-stat-card">
146
+ <div class="ultravisor-stat-card-label">Schedule Entries</div>
147
+ <div class="ultravisor-stat-card-value">{~D:AppData.Ultravisor.ServerStatus.ScheduleEntries~}</div>
148
+ </div>
149
+ <div class="ultravisor-stat-card">
150
+ <div class="ultravisor-stat-card-label">Schedule Running</div>
151
+ <div class="ultravisor-stat-card-value" id="Ultravisor-Dashboard-ScheduleRunning">--</div>
152
+ </div>
153
+ `
154
+ },
155
+ {
156
+ Hash: "Ultravisor-Dashboard-Actions-Template",
157
+ Template: /*html*/`
158
+ <button class="ultravisor-btn ultravisor-btn-primary" onclick="{~P~}.PictApplication.startSchedule(function(){ {~P~}.PictApplication.showView('Ultravisor-Dashboard'); })">Start Schedule</button>
159
+ <button class="ultravisor-btn ultravisor-btn-danger" onclick="{~P~}.PictApplication.stopSchedule(function(){ {~P~}.PictApplication.showView('Ultravisor-Dashboard'); })">Stop Schedule</button>
160
+ <button class="ultravisor-btn ultravisor-btn-secondary" onclick="{~P~}.PictApplication.showView('Ultravisor-Dashboard')">Refresh</button>
161
+ `
162
+ }
163
+ ],
164
+
165
+ Renderables:
166
+ [
167
+ {
168
+ RenderableHash: "Ultravisor-Dashboard-Content",
169
+ TemplateHash: "Ultravisor-Dashboard-Template",
170
+ DestinationAddress: "#Ultravisor-Content-Container",
171
+ RenderMethod: "replace"
172
+ }
173
+ ]
174
+ };
175
+
176
+ class UltravisorDashboardView extends libPictView
177
+ {
178
+ constructor(pFable, pOptions, pServiceHash)
179
+ {
180
+ super(pFable, pOptions, pServiceHash);
181
+ }
182
+
183
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
184
+ {
185
+ let tmpApp = this.pict.PictApplication;
186
+
187
+ // Load status, tasks, operations, and schedule counts
188
+ tmpApp.loadStatus(
189
+ function ()
190
+ {
191
+ let tmpCardsHTML = this.pict.parseTemplateByHash('Ultravisor-Dashboard-Cards-Template', {}, null, this.pict);
192
+ this.pict.ContentAssignment.assignContent('#Ultravisor-Dashboard-Cards', tmpCardsHTML);
193
+
194
+ let tmpActionsHTML = this.pict.parseTemplateByHash('Ultravisor-Dashboard-Actions-Template', {}, null, this.pict);
195
+ this.pict.ContentAssignment.assignContent('#Ultravisor-Dashboard-Actions', tmpActionsHTML);
196
+
197
+ // Update schedule running indicator
198
+ let tmpRunning = this.pict.AppData.Ultravisor.ServerStatus.ScheduleRunning;
199
+ let tmpRunEl = document.getElementById('Ultravisor-Dashboard-ScheduleRunning');
200
+ if (tmpRunEl)
201
+ {
202
+ tmpRunEl.textContent = tmpRunning ? 'Yes' : 'No';
203
+ tmpRunEl.className = 'ultravisor-stat-card-value ' + (tmpRunning ? 'running' : 'stopped');
204
+ }
205
+
206
+ // Load task count
207
+ tmpApp.loadTasks(
208
+ function ()
209
+ {
210
+ let tmpCountEl = document.getElementById('Ultravisor-Dashboard-TaskCount');
211
+ if (tmpCountEl)
212
+ {
213
+ tmpCountEl.textContent = this.pict.AppData.Ultravisor.TaskList.length;
214
+ }
215
+ }.bind(this));
216
+
217
+ // Load operation count
218
+ tmpApp.loadOperations(
219
+ function ()
220
+ {
221
+ let tmpCountEl = document.getElementById('Ultravisor-Dashboard-OperationCount');
222
+ if (tmpCountEl)
223
+ {
224
+ tmpCountEl.textContent = this.pict.AppData.Ultravisor.OperationList.length;
225
+ }
226
+ }.bind(this));
227
+
228
+ }.bind(this));
229
+
230
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
231
+ }
232
+ }
233
+
234
+ module.exports = UltravisorDashboardView;
235
+
236
+ module.exports.default_configuration = _ViewConfiguration;
@@ -0,0 +1,83 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Ultravisor-Layout",
6
+
7
+ DefaultRenderable: "Ultravisor-Layout-Shell",
8
+ DefaultDestinationAddress: "#Ultravisor-Application-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ #Ultravisor-Application-Container {
14
+ display: flex;
15
+ flex-direction: column;
16
+ min-height: 100vh;
17
+ }
18
+ #Ultravisor-TopBar-Container {
19
+ flex-shrink: 0;
20
+ }
21
+ #Ultravisor-Content-Container {
22
+ flex: 1;
23
+ }
24
+ #Ultravisor-BottomBar-Container {
25
+ flex-shrink: 0;
26
+ }
27
+ `,
28
+
29
+ Templates:
30
+ [
31
+ {
32
+ Hash: "Ultravisor-Layout-Shell-Template",
33
+ Template: /*html*/`
34
+ <div id="Ultravisor-TopBar-Container"></div>
35
+ <div id="Ultravisor-Content-Container"></div>
36
+ <div id="Ultravisor-BottomBar-Container"></div>
37
+ `
38
+ }
39
+ ],
40
+
41
+ Renderables:
42
+ [
43
+ {
44
+ RenderableHash: "Ultravisor-Layout-Shell",
45
+ TemplateHash: "Ultravisor-Layout-Shell-Template",
46
+ DestinationAddress: "#Ultravisor-Application-Container",
47
+ RenderMethod: "replace"
48
+ }
49
+ ]
50
+ };
51
+
52
+ class UltravisorLayoutView extends libPictView
53
+ {
54
+ constructor(pFable, pOptions, pServiceHash)
55
+ {
56
+ super(pFable, pOptions, pServiceHash);
57
+ }
58
+
59
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
60
+ {
61
+ // After the layout shell is rendered, render the child views into their containers
62
+ this.pict.views['Ultravisor-TopBar'].render();
63
+ this.pict.views['Ultravisor-BottomBar'].render();
64
+
65
+ // Render initial content -- the dashboard by default
66
+ this.pict.views['Ultravisor-Dashboard'].render();
67
+
68
+ // Inject all view CSS into the PICT-CSS style element
69
+ this.pict.CSSMap.injectCSS();
70
+
71
+ // Now resolve the router so it picks up the current hash URL
72
+ if (this.pict.providers.PictRouter)
73
+ {
74
+ this.pict.providers.PictRouter.resolve();
75
+ }
76
+
77
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
78
+ }
79
+ }
80
+
81
+ module.exports = UltravisorLayoutView;
82
+
83
+ module.exports.default_configuration = _ViewConfiguration;
@@ -0,0 +1,273 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Ultravisor-ManifestList",
6
+
7
+ DefaultRenderable: "Ultravisor-ManifestList-Content",
8
+ DefaultDestinationAddress: "#Ultravisor-Content-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .ultravisor-manifestlist {
14
+ padding: 2em;
15
+ max-width: 1200px;
16
+ margin: 0 auto;
17
+ }
18
+ .ultravisor-manifestlist-header {
19
+ display: flex;
20
+ justify-content: space-between;
21
+ align-items: center;
22
+ margin-bottom: 1.5em;
23
+ padding-bottom: 1em;
24
+ border-bottom: 1px solid #2a2a4a;
25
+ }
26
+ .ultravisor-manifestlist-header h1 {
27
+ margin: 0;
28
+ font-size: 2em;
29
+ font-weight: 300;
30
+ color: #e0e0e0;
31
+ }
32
+ .ultravisor-manifest-table {
33
+ width: 100%;
34
+ border-collapse: collapse;
35
+ }
36
+ .ultravisor-manifest-table th {
37
+ background-color: #16213e;
38
+ }
39
+ .ultravisor-manifest-table tr:hover td {
40
+ background-color: #1a2744;
41
+ }
42
+ .ultravisor-manifest-status {
43
+ display: inline-block;
44
+ padding: 0.15em 0.5em;
45
+ border-radius: 3px;
46
+ font-size: 0.8em;
47
+ font-weight: 600;
48
+ }
49
+ .ultravisor-manifest-status.complete {
50
+ background-color: #2e7d32;
51
+ color: #c8e6c9;
52
+ }
53
+ .ultravisor-manifest-status.running {
54
+ background-color: #1565c0;
55
+ color: #bbdefb;
56
+ }
57
+ .ultravisor-manifest-status.error {
58
+ background-color: #c62828;
59
+ color: #ffcdd2;
60
+ }
61
+ .ultravisor-manifest-detail {
62
+ background: #16213e;
63
+ border: 1px solid #2a2a4a;
64
+ border-radius: 8px;
65
+ padding: 1.5em;
66
+ margin-top: 1em;
67
+ display: none;
68
+ }
69
+ .ultravisor-manifest-detail.visible {
70
+ display: block;
71
+ }
72
+ .ultravisor-manifest-detail h3 {
73
+ margin: 0 0 1em 0;
74
+ color: #b0bec5;
75
+ }
76
+ .ultravisor-manifest-task-result {
77
+ background: #1a1a2e;
78
+ border-radius: 4px;
79
+ padding: 0.75em;
80
+ margin-bottom: 0.5em;
81
+ }
82
+ .ultravisor-manifest-task-result-header {
83
+ display: flex;
84
+ justify-content: space-between;
85
+ align-items: center;
86
+ margin-bottom: 0.5em;
87
+ }
88
+ .ultravisor-manifest-task-result-header code {
89
+ color: #4fc3f7;
90
+ }
91
+ .ultravisor-manifest-output {
92
+ background: #0d1117;
93
+ color: #c9d1d9;
94
+ border-radius: 4px;
95
+ padding: 0.75em;
96
+ font-family: monospace;
97
+ font-size: 0.85em;
98
+ white-space: pre-wrap;
99
+ word-break: break-all;
100
+ max-height: 200px;
101
+ overflow-y: auto;
102
+ margin-top: 0.5em;
103
+ }
104
+ .ultravisor-manifest-success-true {
105
+ color: #66bb6a;
106
+ }
107
+ .ultravisor-manifest-success-false {
108
+ color: #ef5350;
109
+ }
110
+ `,
111
+
112
+ Templates:
113
+ [
114
+ {
115
+ Hash: "Ultravisor-ManifestList-Template",
116
+ Template: /*html*/`
117
+ <div class="ultravisor-manifestlist">
118
+ <div class="ultravisor-manifestlist-header">
119
+ <h1>Execution Manifests</h1>
120
+ <button class="ultravisor-btn ultravisor-btn-secondary" onclick="{~P~}.PictApplication.showView('Ultravisor-ManifestList')">Refresh</button>
121
+ </div>
122
+ <div id="Ultravisor-ManifestList-Body"></div>
123
+ <div id="Ultravisor-ManifestList-Detail"></div>
124
+ </div>
125
+ `
126
+ }
127
+ ],
128
+
129
+ Renderables:
130
+ [
131
+ {
132
+ RenderableHash: "Ultravisor-ManifestList-Content",
133
+ TemplateHash: "Ultravisor-ManifestList-Template",
134
+ DestinationAddress: "#Ultravisor-Content-Container",
135
+ RenderMethod: "replace"
136
+ }
137
+ ]
138
+ };
139
+
140
+ class UltravisorManifestListView extends libPictView
141
+ {
142
+ constructor(pFable, pOptions, pServiceHash)
143
+ {
144
+ super(pFable, pOptions, pServiceHash);
145
+ }
146
+
147
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
148
+ {
149
+ this.pict.PictApplication.loadManifests(
150
+ function ()
151
+ {
152
+ this.renderManifestTable();
153
+ }.bind(this));
154
+
155
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
156
+ }
157
+
158
+ renderManifestTable()
159
+ {
160
+ let tmpManifests = this.pict.AppData.Ultravisor.Manifests;
161
+ let tmpGlobalRef = '_Pict';
162
+ let tmpViewRef = tmpGlobalRef + ".views['Ultravisor-ManifestList']";
163
+
164
+ if (!tmpManifests || tmpManifests.length === 0)
165
+ {
166
+ this.pict.ContentAssignment.assignContent('#Ultravisor-ManifestList-Body',
167
+ '<div class="ultravisor-empty-message">No execution manifests recorded yet. Execute a task or operation to see results here.</div>');
168
+ return;
169
+ }
170
+
171
+ let tmpHTML = '<table class="ultravisor-manifest-table">';
172
+ tmpHTML += '<thead><tr><th>Run GUID</th><th>Operation</th><th>Status</th><th>Success</th><th>Started</th><th>Actions</th></tr></thead>';
173
+ tmpHTML += '<tbody>';
174
+
175
+ for (let i = 0; i < tmpManifests.length; i++)
176
+ {
177
+ let tmpManifest = tmpManifests[i];
178
+ let tmpGUIDRun = tmpManifest.GUIDRun || '';
179
+ let tmpEscGUID = tmpGUIDRun.replace(/'/g, "\\'");
180
+ let tmpStatus = tmpManifest.Status || 'Unknown';
181
+ let tmpStatusClass = tmpStatus.toLowerCase();
182
+ if (tmpStatusClass !== 'complete' && tmpStatusClass !== 'running' && tmpStatusClass !== 'error')
183
+ {
184
+ tmpStatusClass = '';
185
+ }
186
+
187
+ tmpHTML += '<tr>';
188
+ tmpHTML += '<td><code style="font-size:0.8em;">' + tmpGUIDRun + '</code></td>';
189
+ tmpHTML += '<td>' + (tmpManifest.Name || tmpManifest.GUIDOperation || '') + '</td>';
190
+ tmpHTML += '<td><span class="ultravisor-manifest-status ' + tmpStatusClass + '">' + tmpStatus + '</span></td>';
191
+ tmpHTML += '<td><span class="ultravisor-manifest-success-' + (tmpManifest.Success ? 'true' : 'false') + '">' + (tmpManifest.Success ? 'Yes' : 'No') + '</span></td>';
192
+ tmpHTML += '<td>' + (tmpManifest.StartTime || '') + '</td>';
193
+ tmpHTML += '<td><button class="ultravisor-btn-sm ultravisor-btn-edit" onclick="' + tmpViewRef + '.showManifestDetail(\'' + tmpEscGUID + '\')">Details</button></td>';
194
+ tmpHTML += '</tr>';
195
+ }
196
+
197
+ tmpHTML += '</tbody></table>';
198
+ this.pict.ContentAssignment.assignContent('#Ultravisor-ManifestList-Body', tmpHTML);
199
+ }
200
+
201
+ showManifestDetail(pGUIDRun)
202
+ {
203
+ this.pict.PictApplication.loadManifest(pGUIDRun,
204
+ function (pError, pManifest)
205
+ {
206
+ if (pError || !pManifest)
207
+ {
208
+ this.pict.ContentAssignment.assignContent('#Ultravisor-ManifestList-Detail',
209
+ '<div class="ultravisor-manifest-detail visible"><p style="color:#ef5350;">Error loading manifest details.</p></div>');
210
+ return;
211
+ }
212
+
213
+ let tmpHTML = '<div class="ultravisor-manifest-detail visible">';
214
+ tmpHTML += '<h3>Run: ' + (pManifest.GUIDRun || '') + '</h3>';
215
+ tmpHTML += '<p><strong>Operation:</strong> ' + (pManifest.Name || pManifest.GUIDOperation || '') + '</p>';
216
+ tmpHTML += '<p><strong>Status:</strong> ' + (pManifest.Status || '') + ' &middot; <strong>Success:</strong> ' + (pManifest.Success ? 'Yes' : 'No') + '</p>';
217
+ tmpHTML += '<p><strong>Start:</strong> ' + (pManifest.StartTime || '') + ' &middot; <strong>Stop:</strong> ' + (pManifest.StopTime || '') + '</p>';
218
+
219
+ if (pManifest.Summary)
220
+ {
221
+ tmpHTML += '<p><strong>Summary:</strong> ' + this.escapeHTML(pManifest.Summary) + '</p>';
222
+ }
223
+
224
+ // Task results
225
+ let tmpTaskResults = pManifest.TaskResults || [];
226
+ if (tmpTaskResults.length > 0)
227
+ {
228
+ tmpHTML += '<h3>Task Results</h3>';
229
+ for (let i = 0; i < tmpTaskResults.length; i++)
230
+ {
231
+ let tmpResult = tmpTaskResults[i];
232
+ tmpHTML += '<div class="ultravisor-manifest-task-result">';
233
+ tmpHTML += '<div class="ultravisor-manifest-task-result-header">';
234
+ tmpHTML += '<code>' + (tmpResult.GUIDTask || '') + '</code>';
235
+ tmpHTML += '<span class="ultravisor-manifest-status ' + (tmpResult.Status || '').toLowerCase() + '">' + (tmpResult.Status || '') + '</span>';
236
+ tmpHTML += '</div>';
237
+ tmpHTML += '<p style="margin:0.25em 0; font-size:0.85em; color:#78909c;">' + (tmpResult.Name || '') + ' (' + (tmpResult.Type || '') + ')</p>';
238
+
239
+ if (tmpResult.Output)
240
+ {
241
+ tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(String(tmpResult.Output)) + '</div>';
242
+ }
243
+
244
+ if (tmpResult.Log && tmpResult.Log.length > 0)
245
+ {
246
+ tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(tmpResult.Log.join('\n')) + '</div>';
247
+ }
248
+ tmpHTML += '</div>';
249
+ }
250
+ }
251
+
252
+ // Operation log
253
+ if (pManifest.Log && pManifest.Log.length > 0)
254
+ {
255
+ tmpHTML += '<h3>Operation Log</h3>';
256
+ tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(pManifest.Log.join('\n')) + '</div>';
257
+ }
258
+
259
+ tmpHTML += '</div>';
260
+ this.pict.ContentAssignment.assignContent('#Ultravisor-ManifestList-Detail', tmpHTML);
261
+ }.bind(this));
262
+ }
263
+
264
+ escapeHTML(pValue)
265
+ {
266
+ if (!pValue) return '';
267
+ return String(pValue).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
268
+ }
269
+ }
270
+
271
+ module.exports = UltravisorManifestListView;
272
+
273
+ module.exports.default_configuration = _ViewConfiguration;