ultravisor 1.0.2 → 1.0.4

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 (121) hide show
  1. package/.claude/launch.json +11 -0
  2. package/.claude/ultravisor-dev-config.json +3 -0
  3. package/.ultravisor.json +426 -0
  4. package/docs/README.md +63 -0
  5. package/package.json +12 -8
  6. package/source/Ultravisor.cjs +22 -3
  7. package/source/cli/Ultravisor-CLIProgram.cjs +35 -23
  8. package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
  9. package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
  10. package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
  11. package/source/config/Ultravisor-Default-Command-Configuration.cjs +5 -3
  12. package/source/services/Ultravisor-ExecutionEngine.cjs +1039 -0
  13. package/source/services/Ultravisor-ExecutionManifest.cjs +399 -0
  14. package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
  15. package/source/services/Ultravisor-Hypervisor.cjs +38 -83
  16. package/source/services/Ultravisor-StateManager.cjs +241 -0
  17. package/source/services/Ultravisor-TaskTypeRegistry.cjs +143 -0
  18. package/source/services/tasks/Ultravisor-TaskType-Base.cjs +105 -0
  19. package/source/services/tasks/control/Ultravisor-TaskType-IfConditional.cjs +148 -0
  20. package/source/services/tasks/control/Ultravisor-TaskType-LaunchOperation.cjs +187 -0
  21. package/source/services/tasks/control/Ultravisor-TaskType-SplitExecute.cjs +184 -0
  22. package/source/services/tasks/data/Ultravisor-TaskType-ReplaceString.cjs +82 -0
  23. package/source/services/tasks/data/Ultravisor-TaskType-SetValues.cjs +81 -0
  24. package/source/services/tasks/data/Ultravisor-TaskType-StringAppender.cjs +101 -0
  25. package/source/services/tasks/file-io/Ultravisor-TaskType-ReadFile.cjs +103 -0
  26. package/source/services/tasks/file-io/Ultravisor-TaskType-WriteFile.cjs +117 -0
  27. package/source/services/tasks/interaction/Ultravisor-TaskType-ErrorMessage.cjs +54 -0
  28. package/source/services/tasks/interaction/Ultravisor-TaskType-ValueInput.cjs +62 -0
  29. package/source/web_server/Ultravisor-API-Server.cjs +237 -124
  30. package/test/Ultravisor_browser_tests.js +2226 -0
  31. package/test/Ultravisor_tests.js +1143 -5830
  32. package/webinterface/css/ultravisor.css +23 -0
  33. package/webinterface/package.json +6 -3
  34. package/webinterface/source/Pict-Application-Ultravisor.js +93 -73
  35. package/webinterface/source/cards/FlowCard-CSVTransform.js +43 -0
  36. package/webinterface/source/cards/FlowCard-Command.js +86 -0
  37. package/webinterface/source/cards/FlowCard-ComprehensionIntersect.js +40 -0
  38. package/webinterface/source/cards/FlowCard-Conditional.js +87 -0
  39. package/webinterface/source/cards/FlowCard-CopyFile.js +55 -0
  40. package/webinterface/source/cards/FlowCard-End.js +29 -0
  41. package/webinterface/source/cards/FlowCard-GetJSON.js +55 -0
  42. package/webinterface/source/cards/FlowCard-GetText.js +54 -0
  43. package/webinterface/source/cards/FlowCard-Histogram.js +176 -0
  44. package/webinterface/source/cards/FlowCard-LaunchOperation.js +82 -0
  45. package/webinterface/source/cards/FlowCard-ListFiles.js +55 -0
  46. package/webinterface/source/cards/FlowCard-MeadowCount.js +44 -0
  47. package/webinterface/source/cards/FlowCard-MeadowCreate.js +44 -0
  48. package/webinterface/source/cards/FlowCard-MeadowDelete.js +45 -0
  49. package/webinterface/source/cards/FlowCard-MeadowRead.js +46 -0
  50. package/webinterface/source/cards/FlowCard-MeadowReads.js +46 -0
  51. package/webinterface/source/cards/FlowCard-MeadowUpdate.js +44 -0
  52. package/webinterface/source/cards/FlowCard-ParseCSV.js +85 -0
  53. package/webinterface/source/cards/FlowCard-ReadJSON.js +54 -0
  54. package/webinterface/source/cards/FlowCard-ReadText.js +54 -0
  55. package/webinterface/source/cards/FlowCard-RestRequest.js +59 -0
  56. package/webinterface/source/cards/FlowCard-SendJSON.js +57 -0
  57. package/webinterface/source/cards/FlowCard-Solver.js +77 -0
  58. package/webinterface/source/cards/FlowCard-Start.js +29 -0
  59. package/webinterface/source/cards/FlowCard-TemplateString.js +77 -0
  60. package/webinterface/source/cards/FlowCard-WriteJSON.js +54 -0
  61. package/webinterface/source/cards/FlowCard-WriteText.js +54 -0
  62. package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
  63. package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
  64. package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
  65. package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +8 -8
  66. package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +6 -6
  67. package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +436 -0
  68. package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +45 -43
  69. package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +34 -89
  70. package/webinterface/source/views/PictView-Ultravisor-OperationList.js +128 -13
  71. package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
  72. package/webinterface/source/views/PictView-Ultravisor-Schedule.js +18 -53
  73. package/webinterface/source/views/PictView-Ultravisor-TimingView.js +27 -14
  74. package/webinterface/source/views/PictView-Ultravisor-TopBar.js +2 -1
  75. package/.babelrc +0 -6
  76. package/.browserslistrc +0 -1
  77. package/.browserslistrc-BACKUP +0 -1
  78. package/.gulpfile-quackage-config.json +0 -7
  79. package/.gulpfile-quackage.js +0 -2
  80. package/debug/Harness.js +0 -5
  81. package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
  82. package/source/services/Ultravisor-Operation.cjs +0 -200
  83. package/source/services/Ultravisor-Task.cjs +0 -349
  84. package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
  85. package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
  86. package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
  87. package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
  88. package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
  89. package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
  90. package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
  91. package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
  92. package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
  93. package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
  94. package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
  95. package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
  96. package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
  97. package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
  98. package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
  99. package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
  100. package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
  101. package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
  102. package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
  103. package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
  104. package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
  105. package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
  106. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
  107. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
  108. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
  109. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
  110. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
  111. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
  112. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
  113. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
  114. package/webinterface/.babelrc +0 -6
  115. package/webinterface/.browserslistrc +0 -1
  116. package/webinterface/.browserslistrc-BACKUP +0 -1
  117. package/webinterface/.gulpfile-quackage-config.json +0 -7
  118. package/webinterface/.gulpfile-quackage.js +0 -2
  119. package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
  120. package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
  121. /package/docs/{cover.md → _cover.md} +0 -0
@@ -0,0 +1,314 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Ultravisor-PendingInput",
6
+
7
+ DefaultRenderable: "Ultravisor-PendingInput-Content",
8
+ DefaultDestinationAddress: "#Ultravisor-Content-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .ultravisor-pendinginput {
14
+ padding: 2em;
15
+ max-width: 1200px;
16
+ margin: 0 auto;
17
+ }
18
+ .ultravisor-pendinginput-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-pendinginput-header h1 {
27
+ margin: 0;
28
+ font-size: 2em;
29
+ font-weight: 300;
30
+ color: #e0e0e0;
31
+ }
32
+ .ultravisor-pendinginput-card {
33
+ background: #16213e;
34
+ border: 1px solid #f57f17;
35
+ border-radius: 8px;
36
+ padding: 1.5em;
37
+ margin-bottom: 1em;
38
+ }
39
+ .ultravisor-pendinginput-card-header {
40
+ display: flex;
41
+ justify-content: space-between;
42
+ align-items: center;
43
+ margin-bottom: 1em;
44
+ }
45
+ .ultravisor-pendinginput-card-header h3 {
46
+ margin: 0;
47
+ color: #e0e0e0;
48
+ font-weight: 500;
49
+ }
50
+ .ultravisor-pendinginput-meta {
51
+ color: #78909c;
52
+ font-size: 0.85em;
53
+ margin-bottom: 1em;
54
+ }
55
+ .ultravisor-pendinginput-meta code {
56
+ color: #4fc3f7;
57
+ font-size: 0.9em;
58
+ }
59
+ .ultravisor-pendinginput-task {
60
+ background: #1a1a2e;
61
+ border-radius: 4px;
62
+ padding: 1em;
63
+ margin-bottom: 0.75em;
64
+ }
65
+ .ultravisor-pendinginput-prompt {
66
+ color: #fff9c4;
67
+ font-size: 1.1em;
68
+ margin-bottom: 0.75em;
69
+ }
70
+ .ultravisor-pendinginput-address {
71
+ color: #78909c;
72
+ font-size: 0.8em;
73
+ margin-bottom: 0.75em;
74
+ }
75
+ .ultravisor-pendinginput-form {
76
+ display: flex;
77
+ gap: 0.75em;
78
+ align-items: center;
79
+ }
80
+ .ultravisor-pendinginput-form input[type="text"] {
81
+ flex: 1;
82
+ padding: 0.5em 0.75em;
83
+ border: 1px solid #2a2a4a;
84
+ border-radius: 4px;
85
+ background: #0d1117;
86
+ color: #e0e0e0;
87
+ font-size: 1em;
88
+ font-family: monospace;
89
+ }
90
+ .ultravisor-pendinginput-form input[type="text"]:focus {
91
+ outline: none;
92
+ border-color: #f57f17;
93
+ }
94
+ .ultravisor-pendinginput-submit {
95
+ padding: 0.5em 1.25em;
96
+ background-color: #f57f17;
97
+ color: #1a1a2e;
98
+ border: none;
99
+ border-radius: 4px;
100
+ font-weight: 600;
101
+ cursor: pointer;
102
+ font-size: 0.95em;
103
+ }
104
+ .ultravisor-pendinginput-submit:hover {
105
+ background-color: #ff8f00;
106
+ }
107
+ .ultravisor-pendinginput-submit:disabled {
108
+ opacity: 0.5;
109
+ cursor: not-allowed;
110
+ }
111
+ .ultravisor-pendinginput-result {
112
+ margin-top: 0.75em;
113
+ padding: 0.5em 0.75em;
114
+ border-radius: 4px;
115
+ font-size: 0.85em;
116
+ }
117
+ .ultravisor-pendinginput-result.success {
118
+ background: #1b5e20;
119
+ color: #c8e6c9;
120
+ }
121
+ .ultravisor-pendinginput-result.error {
122
+ background: #b71c1c;
123
+ color: #ffcdd2;
124
+ }
125
+ `,
126
+
127
+ Templates:
128
+ [
129
+ {
130
+ Hash: "Ultravisor-PendingInput-Template",
131
+ Template: /*html*/`
132
+ <div class="ultravisor-pendinginput">
133
+ <div class="ultravisor-pendinginput-header">
134
+ <h1>Pending Input</h1>
135
+ <button class="ultravisor-btn ultravisor-btn-secondary" onclick="{~P~}.PictApplication.showView('Ultravisor-PendingInput')">Refresh</button>
136
+ </div>
137
+ <div id="Ultravisor-PendingInput-Body"></div>
138
+ </div>
139
+ `
140
+ }
141
+ ],
142
+
143
+ Renderables:
144
+ [
145
+ {
146
+ RenderableHash: "Ultravisor-PendingInput-Content",
147
+ TemplateHash: "Ultravisor-PendingInput-Template",
148
+ DestinationAddress: "#Ultravisor-Content-Container",
149
+ RenderMethod: "replace"
150
+ }
151
+ ]
152
+ };
153
+
154
+ class UltravisorPendingInputView extends libPictView
155
+ {
156
+ constructor(pFable, pOptions, pServiceHash)
157
+ {
158
+ super(pFable, pOptions, pServiceHash);
159
+ }
160
+
161
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
162
+ {
163
+ this.pict.PictApplication.loadPendingInputs(
164
+ function ()
165
+ {
166
+ this.renderPendingInputs();
167
+ }.bind(this));
168
+
169
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
170
+ }
171
+
172
+ renderPendingInputs()
173
+ {
174
+ let tmpPendingInputs = this.pict.AppData.Ultravisor.PendingInputs;
175
+ let tmpGlobalRef = '_Pict';
176
+ let tmpViewRef = tmpGlobalRef + ".views['Ultravisor-PendingInput']";
177
+
178
+ if (!tmpPendingInputs || tmpPendingInputs.length === 0)
179
+ {
180
+ this.pict.ContentAssignment.assignContent('#Ultravisor-PendingInput-Body',
181
+ '<div class="ultravisor-empty-message">No operations waiting for input.</div>');
182
+ return;
183
+ }
184
+
185
+ let tmpHTML = '';
186
+
187
+ for (let i = 0; i < tmpPendingInputs.length; i++)
188
+ {
189
+ let tmpPending = tmpPendingInputs[i];
190
+ let tmpRunHash = tmpPending.RunHash || '';
191
+ let tmpEscRunHash = tmpRunHash.replace(/'/g, "\\'");
192
+
193
+ tmpHTML += '<div class="ultravisor-pendinginput-card">';
194
+ tmpHTML += '<div class="ultravisor-pendinginput-card-header">';
195
+ tmpHTML += '<h3>' + this.escapeHTML(tmpPending.OperationName || tmpPending.OperationHash || 'Unknown') + '</h3>';
196
+ tmpHTML += '<span class="ultravisor-manifest-status waiting">Waiting for Input</span>';
197
+ tmpHTML += '</div>';
198
+ tmpHTML += '<div class="ultravisor-pendinginput-meta">';
199
+ tmpHTML += 'Operation: <code>' + this.escapeHTML(tmpPending.OperationHash || '') + '</code>';
200
+ tmpHTML += ' &middot; Run: <code>' + this.escapeHTML(tmpRunHash) + '</code>';
201
+ if (tmpPending.StartTime)
202
+ {
203
+ tmpHTML += ' &middot; Started: ' + this.escapeHTML(tmpPending.StartTime);
204
+ }
205
+ tmpHTML += '</div>';
206
+
207
+ // Render each waiting task
208
+ let tmpWaitingTasks = tmpPending.WaitingTasks || {};
209
+ let tmpNodeHashes = Object.keys(tmpWaitingTasks);
210
+
211
+ for (let j = 0; j < tmpNodeHashes.length; j++)
212
+ {
213
+ let tmpNodeHash = tmpNodeHashes[j];
214
+ let tmpEscNodeHash = tmpNodeHash.replace(/'/g, "\\'");
215
+ let tmpTask = tmpWaitingTasks[tmpNodeHash];
216
+ let tmpInputId = 'pending-input-' + tmpRunHash + '-' + tmpNodeHash;
217
+ let tmpResultId = 'pending-result-' + tmpRunHash + '-' + tmpNodeHash;
218
+
219
+ tmpHTML += '<div class="ultravisor-pendinginput-task">';
220
+ tmpHTML += '<div class="ultravisor-pendinginput-prompt">' + this.escapeHTML(tmpTask.PromptMessage || 'Enter a value') + '</div>';
221
+ if (tmpTask.OutputAddress)
222
+ {
223
+ tmpHTML += '<div class="ultravisor-pendinginput-address">Target: <code>' + this.escapeHTML(tmpTask.OutputAddress) + '</code></div>';
224
+ }
225
+ tmpHTML += '<div class="ultravisor-pendinginput-form">';
226
+ tmpHTML += '<input type="text" id="' + tmpInputId + '" placeholder="Enter value..." />';
227
+ tmpHTML += '<button class="ultravisor-pendinginput-submit" onclick="' + tmpViewRef + '.submitInput(\'' + tmpEscRunHash + '\', \'' + tmpEscNodeHash + '\', \'' + tmpInputId + '\', \'' + tmpResultId + '\')">Submit</button>';
228
+ tmpHTML += '</div>';
229
+ tmpHTML += '<div id="' + tmpResultId + '"></div>';
230
+ tmpHTML += '</div>';
231
+ }
232
+
233
+ tmpHTML += '</div>';
234
+ }
235
+
236
+ this.pict.ContentAssignment.assignContent('#Ultravisor-PendingInput-Body', tmpHTML);
237
+ }
238
+
239
+ submitInput(pRunHash, pNodeHash, pInputId, pResultId)
240
+ {
241
+ let tmpInputEl = document.getElementById(pInputId);
242
+ if (!tmpInputEl)
243
+ {
244
+ return;
245
+ }
246
+
247
+ let tmpValue = tmpInputEl.value;
248
+
249
+ // Disable the input and button while submitting
250
+ tmpInputEl.disabled = true;
251
+ let tmpButton = tmpInputEl.parentElement.querySelector('.ultravisor-pendinginput-submit');
252
+ if (tmpButton)
253
+ {
254
+ tmpButton.disabled = true;
255
+ tmpButton.textContent = 'Submitting...';
256
+ }
257
+
258
+ this.pict.PictApplication.submitPendingInput(pRunHash, pNodeHash, tmpValue,
259
+ function (pError, pData)
260
+ {
261
+ if (pError)
262
+ {
263
+ this.pict.ContentAssignment.assignContent('#' + pResultId,
264
+ '<div class="ultravisor-pendinginput-result error">Error: ' + this.escapeHTML(pError.message || 'Request failed') + '</div>');
265
+ // Re-enable
266
+ tmpInputEl.disabled = false;
267
+ if (tmpButton)
268
+ {
269
+ tmpButton.disabled = false;
270
+ tmpButton.textContent = 'Submit';
271
+ }
272
+ return;
273
+ }
274
+
275
+ if (pData && pData.Error)
276
+ {
277
+ this.pict.ContentAssignment.assignContent('#' + pResultId,
278
+ '<div class="ultravisor-pendinginput-result error">Error: ' + this.escapeHTML(pData.Error) + '</div>');
279
+ tmpInputEl.disabled = false;
280
+ if (tmpButton)
281
+ {
282
+ tmpButton.disabled = false;
283
+ tmpButton.textContent = 'Submit';
284
+ }
285
+ return;
286
+ }
287
+
288
+ let tmpStatus = (pData && pData.Status) || 'Submitted';
289
+ this.pict.ContentAssignment.assignContent('#' + pResultId,
290
+ '<div class="ultravisor-pendinginput-result success">Input submitted — operation status: ' + this.escapeHTML(tmpStatus) + '</div>');
291
+
292
+ // Refresh the list after a brief delay so the user sees the success message
293
+ setTimeout(
294
+ function ()
295
+ {
296
+ this.pict.PictApplication.loadPendingInputs(
297
+ function ()
298
+ {
299
+ this.renderPendingInputs();
300
+ }.bind(this));
301
+ }.bind(this), 1500);
302
+ }.bind(this));
303
+ }
304
+
305
+ escapeHTML(pValue)
306
+ {
307
+ if (!pValue) return '';
308
+ return String(pValue).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
309
+ }
310
+ }
311
+
312
+ module.exports = UltravisorPendingInputView;
313
+
314
+ module.exports.default_configuration = _ViewConfiguration;
@@ -156,7 +156,7 @@ class UltravisorScheduleView extends libPictView
156
156
  }
157
157
 
158
158
  let tmpHTML = '<table class="ultravisor-schedule-table">';
159
- tmpHTML += '<thead><tr><th>GUID</th><th>Type</th><th>Target</th><th>Cron</th><th>Active</th><th>Actions</th></tr></thead>';
159
+ tmpHTML += '<thead><tr><th>GUID</th><th>Type</th><th>Target Hash</th><th>Cron</th><th>Active</th><th>Actions</th></tr></thead>';
160
160
  tmpHTML += '<tbody>';
161
161
 
162
162
  for (let i = 0; i < tmpSchedule.length; i++)
@@ -167,10 +167,10 @@ class UltravisorScheduleView extends libPictView
167
167
  let tmpActive = tmpEntry.Active ? 'yes' : 'no';
168
168
 
169
169
  tmpHTML += '<tr>';
170
- tmpHTML += '<td><code style="font-size:0.8em;">' + tmpGUID + '</code></td>';
171
- tmpHTML += '<td>' + (tmpEntry.TargetType || '') + '</td>';
172
- tmpHTML += '<td><code>' + (tmpEntry.TargetGUID || '') + '</code></td>';
173
- tmpHTML += '<td><code>' + (tmpEntry.CronExpression || tmpEntry.Parameters || '') + '</code></td>';
170
+ tmpHTML += '<td><code style="font-size:0.8em;">' + this.escapeHTML(tmpGUID) + '</code></td>';
171
+ tmpHTML += '<td>' + this.escapeHTML(tmpEntry.TargetType || '') + '</td>';
172
+ tmpHTML += '<td><code>' + this.escapeHTML(tmpEntry.TargetHash || '') + '</code></td>';
173
+ tmpHTML += '<td><code>' + this.escapeHTML(tmpEntry.CronExpression || tmpEntry.Parameters || '') + '</code></td>';
174
174
  tmpHTML += '<td><span class="ultravisor-schedule-active ' + tmpActive + '">' + (tmpEntry.Active ? 'Active' : 'Inactive') + '</span></td>';
175
175
  tmpHTML += '<td>';
176
176
  tmpHTML += '<button class="ultravisor-btn-sm ultravisor-btn-delete" onclick="if(confirm(\'Remove schedule entry?\')){ ' + tmpGlobalRef + '.PictApplication.removeScheduleEntry(\'' + tmpEscGUID + '\', function(){ ' + tmpGlobalRef + '.PictApplication.showView(\'Ultravisor-Schedule\'); }); }">Remove</button>';
@@ -189,29 +189,12 @@ class UltravisorScheduleView extends libPictView
189
189
 
190
190
  let tmpHTML = '';
191
191
 
192
- // Schedule a task
193
- tmpHTML += '<div class="ultravisor-schedule-add-section">';
194
- tmpHTML += '<h3>Schedule a Task</h3>';
195
- tmpHTML += '<div class="ultravisor-schedule-add-form">';
196
- tmpHTML += '<div class="ultravisor-form-group"><label>Task GUID</label>';
197
- tmpHTML += '<input type="text" id="Ultravisor-Schedule-TaskGUID" placeholder="e.g. MY-TASK-001"></div>';
198
- tmpHTML += '<div class="ultravisor-form-group"><label>Schedule Type</label>';
199
- tmpHTML += '<select id="Ultravisor-Schedule-TaskScheduleType">';
200
- tmpHTML += '<option value="cron">Cron</option>';
201
- tmpHTML += '<option value="daily">Daily</option>';
202
- tmpHTML += '<option value="hourly">Hourly</option>';
203
- tmpHTML += '</select></div>';
204
- tmpHTML += '<div class="ultravisor-form-group"><label>Parameters (cron expression)</label>';
205
- tmpHTML += '<input type="text" id="Ultravisor-Schedule-TaskParameters" placeholder="e.g. 0 * * * *"></div>';
206
- tmpHTML += '<button class="ultravisor-btn ultravisor-btn-primary" onclick="' + tmpViewRef + '.addTaskSchedule()">Add</button>';
207
- tmpHTML += '</div></div>';
208
-
209
192
  // Schedule an operation
210
- tmpHTML += '<div class="ultravisor-schedule-add-section" style="margin-top:1em;">';
193
+ tmpHTML += '<div class="ultravisor-schedule-add-section">';
211
194
  tmpHTML += '<h3>Schedule an Operation</h3>';
212
195
  tmpHTML += '<div class="ultravisor-schedule-add-form">';
213
- tmpHTML += '<div class="ultravisor-form-group"><label>Operation GUID</label>';
214
- tmpHTML += '<input type="text" id="Ultravisor-Schedule-OperationGUID" placeholder="e.g. MY-OP-001"></div>';
196
+ tmpHTML += '<div class="ultravisor-form-group"><label>Operation Hash</label>';
197
+ tmpHTML += '<input type="text" id="Ultravisor-Schedule-OperationHash" placeholder="e.g. OPR-0001"></div>';
215
198
  tmpHTML += '<div class="ultravisor-form-group"><label>Schedule Type</label>';
216
199
  tmpHTML += '<select id="Ultravisor-Schedule-OperationScheduleType">';
217
200
  tmpHTML += '<option value="cron">Cron</option>';
@@ -226,43 +209,19 @@ class UltravisorScheduleView extends libPictView
226
209
  this.pict.ContentAssignment.assignContent('#Ultravisor-Schedule-AddForms', tmpHTML);
227
210
  }
228
211
 
229
- addTaskSchedule()
230
- {
231
- let tmpGUID = document.getElementById('Ultravisor-Schedule-TaskGUID').value.trim();
232
- let tmpType = document.getElementById('Ultravisor-Schedule-TaskScheduleType').value;
233
- let tmpParams = document.getElementById('Ultravisor-Schedule-TaskParameters').value.trim();
234
-
235
- if (!tmpGUID)
236
- {
237
- alert('Task GUID is required.');
238
- return;
239
- }
240
-
241
- this.pict.PictApplication.scheduleTask(tmpGUID, tmpType, tmpParams,
242
- function (pError)
243
- {
244
- if (pError)
245
- {
246
- alert('Error scheduling task: ' + pError.message);
247
- return;
248
- }
249
- this.pict.PictApplication.showView('Ultravisor-Schedule');
250
- }.bind(this));
251
- }
252
-
253
212
  addOperationSchedule()
254
213
  {
255
- let tmpGUID = document.getElementById('Ultravisor-Schedule-OperationGUID').value.trim();
214
+ let tmpHash = document.getElementById('Ultravisor-Schedule-OperationHash').value.trim();
256
215
  let tmpType = document.getElementById('Ultravisor-Schedule-OperationScheduleType').value;
257
216
  let tmpParams = document.getElementById('Ultravisor-Schedule-OperationParameters').value.trim();
258
217
 
259
- if (!tmpGUID)
218
+ if (!tmpHash)
260
219
  {
261
- alert('Operation GUID is required.');
220
+ alert('Operation Hash is required.');
262
221
  return;
263
222
  }
264
223
 
265
- this.pict.PictApplication.scheduleOperation(tmpGUID, tmpType, tmpParams,
224
+ this.pict.PictApplication.scheduleOperation(tmpHash, tmpType, tmpParams,
266
225
  function (pError)
267
226
  {
268
227
  if (pError)
@@ -273,6 +232,12 @@ class UltravisorScheduleView extends libPictView
273
232
  this.pict.PictApplication.showView('Ultravisor-Schedule');
274
233
  }.bind(this));
275
234
  }
235
+
236
+ escapeHTML(pValue)
237
+ {
238
+ if (!pValue) return '';
239
+ return String(pValue).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
240
+ }
276
241
  }
277
242
 
278
243
  module.exports = UltravisorScheduleView;
@@ -235,26 +235,26 @@ class UltravisorTimingView extends libPictView
235
235
  for (let i = tmpManifests.length - 1; i >= 0; i--)
236
236
  {
237
237
  let tmpManifest = tmpManifests[i];
238
- let tmpGUIDRun = tmpManifest.GUIDRun || '';
239
- let tmpLabel = (tmpManifest.Name || tmpManifest.GUIDOperation || tmpGUIDRun);
238
+ let tmpRunHash = tmpManifest.Hash || '';
239
+ let tmpLabel = (tmpManifest.OperationHash || tmpRunHash);
240
240
  let tmpStatus = tmpManifest.Status || 'Unknown';
241
241
  let tmpTime = tmpManifest.StartTime ? tmpManifest.StartTime.replace('T', ' ').replace(/\.\d+Z$/, '') : '';
242
- tmpHTML += '<option value="' + this.escapeHTML(tmpGUIDRun) + '">' + this.escapeHTML(tmpLabel) + ' [' + tmpStatus + '] ' + tmpTime + '</option>';
242
+ tmpHTML += '<option value="' + this.escapeHTML(tmpRunHash) + '">' + this.escapeHTML(tmpLabel) + ' [' + tmpStatus + '] ' + tmpTime + '</option>';
243
243
  }
244
244
 
245
245
  tmpHTML += '</select>';
246
246
  this.pict.ContentAssignment.assignContent('#Ultravisor-Timing-Selector', tmpHTML);
247
247
  }
248
248
 
249
- onSelectManifest(pGUIDRun)
249
+ onSelectManifest(pRunHash)
250
250
  {
251
- if (!pGUIDRun)
251
+ if (!pRunHash)
252
252
  {
253
253
  this.pict.ContentAssignment.assignContent('#Ultravisor-Timing-Detail', '');
254
254
  return;
255
255
  }
256
256
 
257
- this.pict.PictApplication.loadManifest(pGUIDRun,
257
+ this.pict.PictApplication.loadManifest(pRunHash,
258
258
  function (pError, pManifest)
259
259
  {
260
260
  if (pError || !pManifest)
@@ -270,10 +270,22 @@ class UltravisorTimingView extends libPictView
270
270
 
271
271
  renderTimingVisualization(pManifest)
272
272
  {
273
- let tmpTaskResults = pManifest.TaskResults || [];
273
+ // Convert TaskManifests object to an array for visualization
274
+ let tmpTaskResults = [];
275
+ if (pManifest.TaskManifests && typeof pManifest.TaskManifests === 'object')
276
+ {
277
+ let tmpKeys = Object.keys(pManifest.TaskManifests);
278
+ for (let k = 0; k < tmpKeys.length; k++)
279
+ {
280
+ let tmpEntry = pManifest.TaskManifests[tmpKeys[k]];
281
+ tmpEntry._NodeHash = tmpKeys[k];
282
+ tmpTaskResults.push(tmpEntry);
283
+ }
284
+ }
285
+
274
286
  let tmpOperationElapsedMs = pManifest.ElapsedMs || 0;
275
- let tmpOperationElapsedFormatted = pManifest.ElapsedFormatted || this.formatMs(tmpOperationElapsedMs);
276
- let tmpAverageTaskMs = pManifest.AverageTaskMs || 0;
287
+ let tmpOperationElapsedFormatted = this.formatMs(tmpOperationElapsedMs);
288
+ let tmpAverageTaskMs = 0;
277
289
  let tmpStatus = (pManifest.Status || 'Unknown').toLowerCase();
278
290
  let tmpStatusClass = (tmpStatus === 'complete' || tmpStatus === 'error' || tmpStatus === 'running') ? tmpStatus : '';
279
291
 
@@ -287,8 +299,8 @@ class UltravisorTimingView extends libPictView
287
299
  tmpOperationElapsedFormatted = this.formatMs(tmpOperationElapsedMs);
288
300
  }
289
301
 
290
- // Compute average if not provided
291
- if (tmpAverageTaskMs <= 0 && tmpTaskResults.length > 0 && tmpOperationElapsedMs > 0)
302
+ // Compute average
303
+ if (tmpTaskResults.length > 0 && tmpOperationElapsedMs > 0)
292
304
  {
293
305
  tmpAverageTaskMs = tmpOperationElapsedMs / tmpTaskResults.length;
294
306
  }
@@ -312,7 +324,7 @@ class UltravisorTimingView extends libPictView
312
324
 
313
325
  // Summary header
314
326
  tmpHTML += '<div class="ultravisor-timing-summary">';
315
- tmpHTML += '<div class="ultravisor-timing-stat"><span class="ultravisor-timing-stat-label">Operation</span><span class="ultravisor-timing-stat-value">' + this.escapeHTML(pManifest.Name || pManifest.GUIDOperation || '') + '</span></div>';
327
+ tmpHTML += '<div class="ultravisor-timing-stat"><span class="ultravisor-timing-stat-label">Operation</span><span class="ultravisor-timing-stat-value">' + this.escapeHTML(pManifest.OperationHash || '') + '</span></div>';
316
328
  tmpHTML += '<div class="ultravisor-timing-stat"><span class="ultravisor-timing-stat-label">Status</span><span class="ultravisor-timing-stat-value ' + tmpStatusClass + '">' + this.escapeHTML(pManifest.Status || 'Unknown') + '</span></div>';
317
329
  tmpHTML += '<div class="ultravisor-timing-stat"><span class="ultravisor-timing-stat-label">Total Time</span><span class="ultravisor-timing-stat-value">' + this.escapeHTML(tmpOperationElapsedFormatted) + '</span></div>';
318
330
  tmpHTML += '<div class="ultravisor-timing-stat"><span class="ultravisor-timing-stat-label">Tasks</span><span class="ultravisor-timing-stat-value">' + tmpTaskResults.length + '</span></div>';
@@ -350,10 +362,11 @@ class UltravisorTimingView extends libPictView
350
362
  }
351
363
 
352
364
  let tmpWidthPercent = (tmpMaxTaskMs > 0) ? Math.max((tmpTaskMs / tmpMaxTaskMs) * 100, 1) : 1;
353
- let tmpBarLabel = this.escapeHTML(tmpResult.Name || tmpResult.GUIDTask || '');
365
+ let tmpNodeHash = tmpResult._NodeHash || '';
366
+ let tmpBarLabel = this.escapeHTML(tmpResult.Name || tmpNodeHash || '');
354
367
 
355
368
  tmpHTML += '<div class="ultravisor-timing-row">';
356
- tmpHTML += '<div class="ultravisor-timing-row-label" title="' + this.escapeHTML(tmpResult.GUIDTask || '') + '">' + this.escapeHTML(tmpResult.Name || tmpResult.GUIDTask || 'Task ' + (i + 1)) + '</div>';
369
+ tmpHTML += '<div class="ultravisor-timing-row-label" title="' + this.escapeHTML(tmpNodeHash) + '">' + this.escapeHTML(tmpResult.Name || tmpNodeHash || 'Task ' + (i + 1)) + '</div>';
357
370
  tmpHTML += '<div class="ultravisor-timing-row-bar-container">';
358
371
  tmpHTML += '<div class="ultravisor-timing-row-bar ' + tmpBarClass + '" style="width: ' + tmpWidthPercent.toFixed(1) + '%;">';
359
372
  if (tmpWidthPercent > 20)
@@ -82,11 +82,12 @@ const _ViewConfiguration =
82
82
  <a class="ultravisor-topbar-brand" onclick="{~P~}.PictApplication.navigateTo('/Home')">Ultravisor</a>
83
83
  <div class="ultravisor-topbar-nav">
84
84
  <a onclick="{~P~}.PictApplication.navigateTo('/Home')">Dashboard</a>
85
- <a onclick="{~P~}.PictApplication.navigateTo('/Tasks')">Tasks</a>
86
85
  <a onclick="{~P~}.PictApplication.navigateTo('/Operations')">Operations</a>
87
86
  <a onclick="{~P~}.PictApplication.navigateTo('/Schedule')">Schedule</a>
88
87
  <a onclick="{~P~}.PictApplication.navigateTo('/Manifests')">Manifests</a>
88
+ <a onclick="{~P~}.PictApplication.navigateTo('/PendingInput')">Pending Input</a>
89
89
  <a onclick="{~P~}.PictApplication.navigateTo('/Timing')">Timing</a>
90
+ <a onclick="{~P~}.PictApplication.editOperation()">Flow Editor</a>
90
91
  </div>
91
92
  <div class="ultravisor-topbar-status" id="Ultravisor-TopBar-StatusArea"></div>
92
93
  </div>
package/.babelrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/preset-env"
4
- ],
5
- "sourceMaps": "both"
6
- }
package/.browserslistrc DELETED
@@ -1 +0,0 @@
1
- > 0.01%
@@ -1 +0,0 @@
1
- since 2018
@@ -1,7 +0,0 @@
1
- {
2
- "EntrypointInputSourceFile": "/Users/stevenvelozo/Code/retold/modules/utility/ultravisor/source/Ultravisor.js",
3
- "LibraryObjectName": "Ultravisor",
4
- "LibraryOutputFolder": "/Users/stevenvelozo/Code/retold/modules/utility/ultravisor/dist/",
5
- "LibraryUniminifiedFileName": "ultravisor.compatible.js",
6
- "LibraryMinifiedFileName": "ultravisor.compatible.min.js"
7
- }
@@ -1,2 +0,0 @@
1
- require('/Users/stevenvelozo/Code/retold/node_modules/quackage/gulp/Quackage-Gulpfile.js');
2
- require('/Users/stevenvelozo/Code/retold/node_modules/quackage/gulp/Quackage-Gulpfile.js');
package/debug/Harness.js DELETED
@@ -1,5 +0,0 @@
1
- let libUltravisor = require(`../source/cli/Ultravisor-CLIProgram.cjs`);
2
-
3
- //libUltravisor.run(['node', 'Harness.js', 'explain-config']);
4
-
5
- //libUltravisor.run(['node', 'Harness.js', 'start']);