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.
- package/.claude/launch.json +11 -0
- package/.claude/ultravisor-dev-config.json +3 -0
- package/.ultravisor.json +426 -0
- package/docs/README.md +63 -0
- package/package.json +12 -8
- package/source/Ultravisor.cjs +22 -3
- package/source/cli/Ultravisor-CLIProgram.cjs +35 -23
- package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
- package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
- package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
- package/source/config/Ultravisor-Default-Command-Configuration.cjs +5 -3
- package/source/services/Ultravisor-ExecutionEngine.cjs +1039 -0
- package/source/services/Ultravisor-ExecutionManifest.cjs +399 -0
- package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
- package/source/services/Ultravisor-Hypervisor.cjs +38 -83
- package/source/services/Ultravisor-StateManager.cjs +241 -0
- package/source/services/Ultravisor-TaskTypeRegistry.cjs +143 -0
- package/source/services/tasks/Ultravisor-TaskType-Base.cjs +105 -0
- package/source/services/tasks/control/Ultravisor-TaskType-IfConditional.cjs +148 -0
- package/source/services/tasks/control/Ultravisor-TaskType-LaunchOperation.cjs +187 -0
- package/source/services/tasks/control/Ultravisor-TaskType-SplitExecute.cjs +184 -0
- package/source/services/tasks/data/Ultravisor-TaskType-ReplaceString.cjs +82 -0
- package/source/services/tasks/data/Ultravisor-TaskType-SetValues.cjs +81 -0
- package/source/services/tasks/data/Ultravisor-TaskType-StringAppender.cjs +101 -0
- package/source/services/tasks/file-io/Ultravisor-TaskType-ReadFile.cjs +103 -0
- package/source/services/tasks/file-io/Ultravisor-TaskType-WriteFile.cjs +117 -0
- package/source/services/tasks/interaction/Ultravisor-TaskType-ErrorMessage.cjs +54 -0
- package/source/services/tasks/interaction/Ultravisor-TaskType-ValueInput.cjs +62 -0
- package/source/web_server/Ultravisor-API-Server.cjs +237 -124
- package/test/Ultravisor_browser_tests.js +2226 -0
- package/test/Ultravisor_tests.js +1143 -5830
- package/webinterface/css/ultravisor.css +23 -0
- package/webinterface/package.json +6 -3
- package/webinterface/source/Pict-Application-Ultravisor.js +93 -73
- package/webinterface/source/cards/FlowCard-CSVTransform.js +43 -0
- package/webinterface/source/cards/FlowCard-Command.js +86 -0
- package/webinterface/source/cards/FlowCard-ComprehensionIntersect.js +40 -0
- package/webinterface/source/cards/FlowCard-Conditional.js +87 -0
- package/webinterface/source/cards/FlowCard-CopyFile.js +55 -0
- package/webinterface/source/cards/FlowCard-End.js +29 -0
- package/webinterface/source/cards/FlowCard-GetJSON.js +55 -0
- package/webinterface/source/cards/FlowCard-GetText.js +54 -0
- package/webinterface/source/cards/FlowCard-Histogram.js +176 -0
- package/webinterface/source/cards/FlowCard-LaunchOperation.js +82 -0
- package/webinterface/source/cards/FlowCard-ListFiles.js +55 -0
- package/webinterface/source/cards/FlowCard-MeadowCount.js +44 -0
- package/webinterface/source/cards/FlowCard-MeadowCreate.js +44 -0
- package/webinterface/source/cards/FlowCard-MeadowDelete.js +45 -0
- package/webinterface/source/cards/FlowCard-MeadowRead.js +46 -0
- package/webinterface/source/cards/FlowCard-MeadowReads.js +46 -0
- package/webinterface/source/cards/FlowCard-MeadowUpdate.js +44 -0
- package/webinterface/source/cards/FlowCard-ParseCSV.js +85 -0
- package/webinterface/source/cards/FlowCard-ReadJSON.js +54 -0
- package/webinterface/source/cards/FlowCard-ReadText.js +54 -0
- package/webinterface/source/cards/FlowCard-RestRequest.js +59 -0
- package/webinterface/source/cards/FlowCard-SendJSON.js +57 -0
- package/webinterface/source/cards/FlowCard-Solver.js +77 -0
- package/webinterface/source/cards/FlowCard-Start.js +29 -0
- package/webinterface/source/cards/FlowCard-TemplateString.js +77 -0
- package/webinterface/source/cards/FlowCard-WriteJSON.js +54 -0
- package/webinterface/source/cards/FlowCard-WriteText.js +54 -0
- package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
- package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
- package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
- package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +8 -8
- package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +6 -6
- package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +436 -0
- package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +45 -43
- package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +34 -89
- package/webinterface/source/views/PictView-Ultravisor-OperationList.js +128 -13
- package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
- package/webinterface/source/views/PictView-Ultravisor-Schedule.js +18 -53
- package/webinterface/source/views/PictView-Ultravisor-TimingView.js +27 -14
- package/webinterface/source/views/PictView-Ultravisor-TopBar.js +2 -1
- package/.babelrc +0 -6
- package/.browserslistrc +0 -1
- package/.browserslistrc-BACKUP +0 -1
- package/.gulpfile-quackage-config.json +0 -7
- package/.gulpfile-quackage.js +0 -2
- package/debug/Harness.js +0 -5
- package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
- package/source/services/Ultravisor-Operation.cjs +0 -200
- package/source/services/Ultravisor-Task.cjs +0 -349
- package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
- package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
- package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
- package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
- package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
- package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
- package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
- package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
- package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
- package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
- package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
- package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
- package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
- package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
- package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
- package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
- package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
- package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
- package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
- package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
- package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
- package/webinterface/.babelrc +0 -6
- package/webinterface/.browserslistrc +0 -1
- package/webinterface/.browserslistrc-BACKUP +0 -1
- package/webinterface/.gulpfile-quackage-config.json +0 -7
- package/webinterface/.gulpfile-quackage.js +0 -2
- package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
- package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
- /package/docs/{cover.md → _cover.md} +0 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
const libPictSectionFlow = require('pict-section-flow');
|
|
3
|
+
|
|
4
|
+
// Flow control cards
|
|
5
|
+
const libFlowCardStart = require('../cards/FlowCard-Start.js');
|
|
6
|
+
const libFlowCardEnd = require('../cards/FlowCard-End.js');
|
|
7
|
+
|
|
8
|
+
// Core/Control cards
|
|
9
|
+
const libFlowCardCommand = require('../cards/FlowCard-Command.js');
|
|
10
|
+
const libFlowCardConditional = require('../cards/FlowCard-Conditional.js');
|
|
11
|
+
const libFlowCardSolver = require('../cards/FlowCard-Solver.js');
|
|
12
|
+
const libFlowCardTemplateString = require('../cards/FlowCard-TemplateString.js');
|
|
13
|
+
const libFlowCardLaunchOperation = require('../cards/FlowCard-LaunchOperation.js');
|
|
14
|
+
|
|
15
|
+
// File I/O cards
|
|
16
|
+
const libFlowCardReadText = require('../cards/FlowCard-ReadText.js');
|
|
17
|
+
const libFlowCardWriteText = require('../cards/FlowCard-WriteText.js');
|
|
18
|
+
const libFlowCardReadJSON = require('../cards/FlowCard-ReadJSON.js');
|
|
19
|
+
const libFlowCardWriteJSON = require('../cards/FlowCard-WriteJSON.js');
|
|
20
|
+
const libFlowCardListFiles = require('../cards/FlowCard-ListFiles.js');
|
|
21
|
+
const libFlowCardCopyFile = require('../cards/FlowCard-CopyFile.js');
|
|
22
|
+
|
|
23
|
+
// REST/HTTP cards
|
|
24
|
+
const libFlowCardGetJSON = require('../cards/FlowCard-GetJSON.js');
|
|
25
|
+
const libFlowCardGetText = require('../cards/FlowCard-GetText.js');
|
|
26
|
+
const libFlowCardSendJSON = require('../cards/FlowCard-SendJSON.js');
|
|
27
|
+
const libFlowCardRestRequest = require('../cards/FlowCard-RestRequest.js');
|
|
28
|
+
|
|
29
|
+
// Meadow cards
|
|
30
|
+
const libFlowCardMeadowCreate = require('../cards/FlowCard-MeadowCreate.js');
|
|
31
|
+
const libFlowCardMeadowRead = require('../cards/FlowCard-MeadowRead.js');
|
|
32
|
+
const libFlowCardMeadowReads = require('../cards/FlowCard-MeadowReads.js');
|
|
33
|
+
const libFlowCardMeadowUpdate = require('../cards/FlowCard-MeadowUpdate.js');
|
|
34
|
+
const libFlowCardMeadowDelete = require('../cards/FlowCard-MeadowDelete.js');
|
|
35
|
+
const libFlowCardMeadowCount = require('../cards/FlowCard-MeadowCount.js');
|
|
36
|
+
const libFlowCardCSVTransform = require('../cards/FlowCard-CSVTransform.js');
|
|
37
|
+
const libFlowCardComprehensionIntersect = require('../cards/FlowCard-ComprehensionIntersect.js');
|
|
38
|
+
|
|
39
|
+
// Pipeline cards
|
|
40
|
+
const libFlowCardParseCSV = require('../cards/FlowCard-ParseCSV.js');
|
|
41
|
+
const libFlowCardHistogram = require('../cards/FlowCard-Histogram.js');
|
|
42
|
+
|
|
43
|
+
const _ViewConfiguration =
|
|
44
|
+
{
|
|
45
|
+
ViewIdentifier: "Ultravisor-FlowEditor",
|
|
46
|
+
|
|
47
|
+
DefaultRenderable: "Ultravisor-FlowEditor-Content",
|
|
48
|
+
DefaultDestinationAddress: "#Ultravisor-Content-Container",
|
|
49
|
+
|
|
50
|
+
AutoRender: false,
|
|
51
|
+
|
|
52
|
+
CSS: /*css*/`
|
|
53
|
+
.ultravisor-floweditor {
|
|
54
|
+
padding: 0.75em;
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
flex: 1;
|
|
58
|
+
height: calc(100vh - 56px - 39px - 0.75em);
|
|
59
|
+
min-height: 400px;
|
|
60
|
+
box-sizing: border-box;
|
|
61
|
+
}
|
|
62
|
+
.ultravisor-floweditor-header {
|
|
63
|
+
flex-shrink: 0;
|
|
64
|
+
display: flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
justify-content: space-between;
|
|
67
|
+
margin-bottom: 0.75em;
|
|
68
|
+
padding-bottom: 0.75em;
|
|
69
|
+
border-bottom: 1px solid #2a2a4a;
|
|
70
|
+
}
|
|
71
|
+
.ultravisor-floweditor-header h1 {
|
|
72
|
+
margin: 0;
|
|
73
|
+
font-size: 1.8em;
|
|
74
|
+
font-weight: 300;
|
|
75
|
+
color: #e0e0e0;
|
|
76
|
+
}
|
|
77
|
+
.ultravisor-flow-actions {
|
|
78
|
+
display: flex;
|
|
79
|
+
gap: 0.5em;
|
|
80
|
+
align-items: center;
|
|
81
|
+
flex-wrap: wrap;
|
|
82
|
+
}
|
|
83
|
+
.ultravisor-flow-meta {
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
display: flex;
|
|
86
|
+
gap: 0.75em;
|
|
87
|
+
align-items: center;
|
|
88
|
+
margin-bottom: 0.5em;
|
|
89
|
+
padding-bottom: 0.5em;
|
|
90
|
+
border-bottom: 1px solid #1a1a2e;
|
|
91
|
+
}
|
|
92
|
+
.ultravisor-flow-meta label {
|
|
93
|
+
font-size: 0.8em;
|
|
94
|
+
font-weight: 600;
|
|
95
|
+
color: #78909c;
|
|
96
|
+
text-transform: uppercase;
|
|
97
|
+
margin-right: 0.25em;
|
|
98
|
+
}
|
|
99
|
+
.ultravisor-flow-meta input {
|
|
100
|
+
flex: 1;
|
|
101
|
+
min-width: 120px;
|
|
102
|
+
}
|
|
103
|
+
.ultravisor-flow-meta-hash {
|
|
104
|
+
font-size: 0.8em;
|
|
105
|
+
color: #607d8b;
|
|
106
|
+
font-family: monospace;
|
|
107
|
+
}
|
|
108
|
+
#Ultravisor-FlowEditor-Container {
|
|
109
|
+
flex: 1;
|
|
110
|
+
min-height: 0;
|
|
111
|
+
}
|
|
112
|
+
`,
|
|
113
|
+
|
|
114
|
+
Templates:
|
|
115
|
+
[
|
|
116
|
+
{
|
|
117
|
+
Hash: "Ultravisor-FlowEditor-Template",
|
|
118
|
+
Template: /*html*/`
|
|
119
|
+
<div class="ultravisor-floweditor">
|
|
120
|
+
<div class="ultravisor-floweditor-header">
|
|
121
|
+
<h1 id="Ultravisor-FlowEditor-Title">Flow Editor</h1>
|
|
122
|
+
<div class="ultravisor-flow-actions">
|
|
123
|
+
<button class="ultravisor-btn ultravisor-btn-primary" onclick="{~P~}.views['Ultravisor-FlowEditor'].saveOperation()">Save Operation</button>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
<div class="ultravisor-flow-meta">
|
|
127
|
+
<span id="Ultravisor-FlowEditor-HashDisplay" class="ultravisor-flow-meta-hash"></span>
|
|
128
|
+
<label>Name</label>
|
|
129
|
+
<input type="text" id="Ultravisor-FlowEditor-Name" placeholder="Operation name...">
|
|
130
|
+
<label>Description</label>
|
|
131
|
+
<input type="text" id="Ultravisor-FlowEditor-Description" placeholder="Description...">
|
|
132
|
+
</div>
|
|
133
|
+
<div id="Ultravisor-FlowEditor-Container"></div>
|
|
134
|
+
</div>
|
|
135
|
+
`
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
|
|
139
|
+
Renderables:
|
|
140
|
+
[
|
|
141
|
+
{
|
|
142
|
+
RenderableHash: "Ultravisor-FlowEditor-Content",
|
|
143
|
+
TemplateHash: "Ultravisor-FlowEditor-Template",
|
|
144
|
+
DestinationAddress: "#Ultravisor-Content-Container",
|
|
145
|
+
RenderMethod: "replace"
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
class UltravisorFlowEditorView extends libPictView
|
|
151
|
+
{
|
|
152
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
153
|
+
{
|
|
154
|
+
super(pFable, pOptions, pServiceHash);
|
|
155
|
+
|
|
156
|
+
this._FlowView = null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Build a map of FlowCard node type configurations keyed by hash.
|
|
161
|
+
* These are passed as NodeTypes in the FlowView options so they
|
|
162
|
+
* are available from the moment the NodeTypeProvider is created,
|
|
163
|
+
* before the toolbar renders.
|
|
164
|
+
*/
|
|
165
|
+
_buildFlowCardNodeTypes()
|
|
166
|
+
{
|
|
167
|
+
let tmpCardClasses =
|
|
168
|
+
[
|
|
169
|
+
// Flow control
|
|
170
|
+
libFlowCardStart,
|
|
171
|
+
libFlowCardEnd,
|
|
172
|
+
// Core
|
|
173
|
+
libFlowCardCommand,
|
|
174
|
+
libFlowCardConditional,
|
|
175
|
+
libFlowCardSolver,
|
|
176
|
+
libFlowCardTemplateString,
|
|
177
|
+
libFlowCardLaunchOperation,
|
|
178
|
+
// File I/O
|
|
179
|
+
libFlowCardReadText,
|
|
180
|
+
libFlowCardWriteText,
|
|
181
|
+
libFlowCardReadJSON,
|
|
182
|
+
libFlowCardWriteJSON,
|
|
183
|
+
libFlowCardListFiles,
|
|
184
|
+
libFlowCardCopyFile,
|
|
185
|
+
// REST
|
|
186
|
+
libFlowCardGetJSON,
|
|
187
|
+
libFlowCardGetText,
|
|
188
|
+
libFlowCardSendJSON,
|
|
189
|
+
libFlowCardRestRequest,
|
|
190
|
+
// Meadow
|
|
191
|
+
libFlowCardMeadowCreate,
|
|
192
|
+
libFlowCardMeadowRead,
|
|
193
|
+
libFlowCardMeadowReads,
|
|
194
|
+
libFlowCardMeadowUpdate,
|
|
195
|
+
libFlowCardMeadowDelete,
|
|
196
|
+
libFlowCardMeadowCount,
|
|
197
|
+
libFlowCardCSVTransform,
|
|
198
|
+
libFlowCardComprehensionIntersect,
|
|
199
|
+
// Pipeline
|
|
200
|
+
libFlowCardParseCSV,
|
|
201
|
+
libFlowCardHistogram
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
let tmpNodeTypes = {};
|
|
205
|
+
|
|
206
|
+
for (let i = 0; i < tmpCardClasses.length; i++)
|
|
207
|
+
{
|
|
208
|
+
let tmpCard = new tmpCardClasses[i](this.fable, {}, `FlowCard-${i}`);
|
|
209
|
+
let tmpConfig = tmpCard.getNodeTypeConfiguration();
|
|
210
|
+
// Ultravisor flow cards render port labels outside the node
|
|
211
|
+
// boundary to avoid overlapping body content
|
|
212
|
+
tmpConfig.PortLabelsOutside = true;
|
|
213
|
+
tmpNodeTypes[tmpConfig.Hash] = tmpConfig;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return tmpNodeTypes;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
|
|
220
|
+
{
|
|
221
|
+
// Populate the metadata fields from CurrentEditOperation
|
|
222
|
+
let tmpOp = this.pict.AppData.Ultravisor.CurrentEditOperation;
|
|
223
|
+
if (tmpOp)
|
|
224
|
+
{
|
|
225
|
+
let tmpTitleEl = document.getElementById('Ultravisor-FlowEditor-Title');
|
|
226
|
+
if (tmpTitleEl)
|
|
227
|
+
{
|
|
228
|
+
tmpTitleEl.textContent = tmpOp.Hash ? ('Flow Editor: ' + (tmpOp.Name || tmpOp.Hash)) : 'Flow Editor: New Operation';
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
let tmpHashEl = document.getElementById('Ultravisor-FlowEditor-HashDisplay');
|
|
232
|
+
if (tmpHashEl && tmpOp.Hash)
|
|
233
|
+
{
|
|
234
|
+
tmpHashEl.textContent = tmpOp.Hash;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
let tmpNameEl = document.getElementById('Ultravisor-FlowEditor-Name');
|
|
238
|
+
if (tmpNameEl)
|
|
239
|
+
{
|
|
240
|
+
tmpNameEl.value = tmpOp.Name || '';
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let tmpDescEl = document.getElementById('Ultravisor-FlowEditor-Description');
|
|
244
|
+
if (tmpDescEl)
|
|
245
|
+
{
|
|
246
|
+
tmpDescEl.value = tmpOp.Description || '';
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Create and render the flow section view into its container
|
|
251
|
+
if (!this._FlowView)
|
|
252
|
+
{
|
|
253
|
+
this._FlowView = this.pict.addView('Ultravisor-FlowDiagram',
|
|
254
|
+
{
|
|
255
|
+
ViewIdentifier: 'Ultravisor-FlowDiagram',
|
|
256
|
+
|
|
257
|
+
DefaultRenderable: 'Flow-Container',
|
|
258
|
+
DefaultDestinationAddress: '#Ultravisor-FlowEditor-Container',
|
|
259
|
+
|
|
260
|
+
AutoRender: false,
|
|
261
|
+
|
|
262
|
+
FlowDataAddress: 'AppData.Ultravisor.Flows.Current',
|
|
263
|
+
|
|
264
|
+
TargetElementAddress: '#Flow-SVG-Container',
|
|
265
|
+
|
|
266
|
+
EnableToolbar: true,
|
|
267
|
+
EnablePanning: true,
|
|
268
|
+
EnableZooming: true,
|
|
269
|
+
EnableNodeDragging: true,
|
|
270
|
+
EnableConnectionCreation: true,
|
|
271
|
+
EnableGridSnap: false,
|
|
272
|
+
GridSnapSize: 20,
|
|
273
|
+
|
|
274
|
+
MinZoom: 0.1,
|
|
275
|
+
MaxZoom: 5.0,
|
|
276
|
+
ZoomStep: 0.1,
|
|
277
|
+
|
|
278
|
+
DefaultNodeType: 'default',
|
|
279
|
+
DefaultNodeWidth: 180,
|
|
280
|
+
DefaultNodeHeight: 80,
|
|
281
|
+
|
|
282
|
+
// Pre-register FlowCard node types so they are available
|
|
283
|
+
// when the NodeTypeProvider is created, before toolbar renders
|
|
284
|
+
NodeTypes: this._buildFlowCardNodeTypes(),
|
|
285
|
+
|
|
286
|
+
Renderables:
|
|
287
|
+
[
|
|
288
|
+
{
|
|
289
|
+
RenderableHash: 'Flow-Container',
|
|
290
|
+
TemplateHash: 'Flow-Container-Template',
|
|
291
|
+
DestinationAddress: '#Ultravisor-FlowEditor-Container',
|
|
292
|
+
RenderMethod: 'replace'
|
|
293
|
+
}
|
|
294
|
+
]
|
|
295
|
+
},
|
|
296
|
+
libPictSectionFlow
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Initialize default empty flow if none exists
|
|
301
|
+
if (!this.pict.AppData.Ultravisor.Flows.Current)
|
|
302
|
+
{
|
|
303
|
+
this.pict.AppData.Ultravisor.Flows.Current =
|
|
304
|
+
{
|
|
305
|
+
Nodes: [],
|
|
306
|
+
Connections: [],
|
|
307
|
+
ViewState: { PanX: 0, PanY: 0, Zoom: 1, SelectedNodeHash: null, SelectedConnectionHash: null }
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Reset the flow view's render state so it re-initializes SVG elements
|
|
312
|
+
// when re-rendered (e.g. after navigating away and back)
|
|
313
|
+
this._FlowView.initialRenderComplete = false;
|
|
314
|
+
this._FlowView.render();
|
|
315
|
+
|
|
316
|
+
// Re-inject CSS after the flow view creates its dynamic styles
|
|
317
|
+
this.pict.CSSMap.injectCSS();
|
|
318
|
+
|
|
319
|
+
return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
loadExample(pExampleName)
|
|
323
|
+
{
|
|
324
|
+
let tmpFlowData = null;
|
|
325
|
+
|
|
326
|
+
if (pExampleName === 'CSVPipeline')
|
|
327
|
+
{
|
|
328
|
+
tmpFlowData = require('../data/ExampleFlow-CSVPipeline.js');
|
|
329
|
+
}
|
|
330
|
+
else if (pExampleName === 'MeadowPipeline')
|
|
331
|
+
{
|
|
332
|
+
tmpFlowData = require('../data/ExampleFlow-MeadowPipeline.js');
|
|
333
|
+
}
|
|
334
|
+
else if (pExampleName === 'FileProcessor')
|
|
335
|
+
{
|
|
336
|
+
tmpFlowData = require('../data/ExampleFlow-FileProcessor.js');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (tmpFlowData)
|
|
340
|
+
{
|
|
341
|
+
this.pict.AppData.Ultravisor.Flows.Current = JSON.parse(JSON.stringify(tmpFlowData));
|
|
342
|
+
if (this._FlowView)
|
|
343
|
+
{
|
|
344
|
+
this._FlowView.setFlowData(this.pict.AppData.Ultravisor.Flows.Current);
|
|
345
|
+
// Zoom to fit after a brief delay to allow the DOM to update
|
|
346
|
+
let tmpFlowView = this._FlowView;
|
|
347
|
+
setTimeout(function()
|
|
348
|
+
{
|
|
349
|
+
if (tmpFlowView._ViewportManager)
|
|
350
|
+
{
|
|
351
|
+
tmpFlowView._ViewportManager.zoomToFit();
|
|
352
|
+
}
|
|
353
|
+
}, 100);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
saveOperation()
|
|
359
|
+
{
|
|
360
|
+
if (!this._FlowView)
|
|
361
|
+
{
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
let tmpFlowData = this._FlowView.getFlowData();
|
|
366
|
+
if (!tmpFlowData || !tmpFlowData.Nodes || tmpFlowData.Nodes.length === 0)
|
|
367
|
+
{
|
|
368
|
+
alert('No flow data to save. Add some nodes first.');
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Read the metadata from the form fields
|
|
373
|
+
let tmpName = document.getElementById('Ultravisor-FlowEditor-Name').value.trim();
|
|
374
|
+
let tmpDescription = document.getElementById('Ultravisor-FlowEditor-Description').value.trim();
|
|
375
|
+
|
|
376
|
+
if (!tmpName)
|
|
377
|
+
{
|
|
378
|
+
alert('Please enter an operation name.');
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// Build the operation data with the graph
|
|
383
|
+
let tmpOpData =
|
|
384
|
+
{
|
|
385
|
+
Name: tmpName,
|
|
386
|
+
Description: tmpDescription,
|
|
387
|
+
Graph:
|
|
388
|
+
{
|
|
389
|
+
Nodes: tmpFlowData.Nodes,
|
|
390
|
+
Connections: tmpFlowData.Connections,
|
|
391
|
+
ViewState: tmpFlowData.ViewState || {}
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
// Include Hash if editing an existing operation
|
|
396
|
+
let tmpOp = this.pict.AppData.Ultravisor.CurrentEditOperation;
|
|
397
|
+
if (tmpOp && tmpOp.Hash)
|
|
398
|
+
{
|
|
399
|
+
tmpOpData.Hash = tmpOp.Hash;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
this.pict.PictApplication.saveOperation(tmpOpData,
|
|
403
|
+
function (pError, pData)
|
|
404
|
+
{
|
|
405
|
+
if (pError)
|
|
406
|
+
{
|
|
407
|
+
alert('Error saving operation: ' + pError.message);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Update the current edit operation with the saved data
|
|
412
|
+
if (pData && pData.Hash)
|
|
413
|
+
{
|
|
414
|
+
if (!this.pict.AppData.Ultravisor.CurrentEditOperation)
|
|
415
|
+
{
|
|
416
|
+
this.pict.AppData.Ultravisor.CurrentEditOperation = {};
|
|
417
|
+
}
|
|
418
|
+
this.pict.AppData.Ultravisor.CurrentEditOperation.Hash = pData.Hash;
|
|
419
|
+
this.pict.AppData.Ultravisor.CurrentEditOperation.Name = tmpName;
|
|
420
|
+
this.pict.AppData.Ultravisor.CurrentEditOperation.Description = tmpDescription;
|
|
421
|
+
|
|
422
|
+
let tmpHashEl = document.getElementById('Ultravisor-FlowEditor-HashDisplay');
|
|
423
|
+
if (tmpHashEl)
|
|
424
|
+
{
|
|
425
|
+
tmpHashEl.textContent = pData.Hash;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
alert('Operation saved successfully.');
|
|
430
|
+
}.bind(this));
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
module.exports = UltravisorFlowEditorView;
|
|
435
|
+
|
|
436
|
+
module.exports.default_configuration = _ViewConfiguration;
|
|
@@ -58,6 +58,10 @@ const _ViewConfiguration =
|
|
|
58
58
|
background-color: #c62828;
|
|
59
59
|
color: #ffcdd2;
|
|
60
60
|
}
|
|
61
|
+
.ultravisor-manifest-status.waiting {
|
|
62
|
+
background-color: #f57f17;
|
|
63
|
+
color: #fff9c4;
|
|
64
|
+
}
|
|
61
65
|
.ultravisor-manifest-detail {
|
|
62
66
|
background: #16213e;
|
|
63
67
|
border: 1px solid #2a2a4a;
|
|
@@ -101,12 +105,6 @@ const _ViewConfiguration =
|
|
|
101
105
|
overflow-y: auto;
|
|
102
106
|
margin-top: 0.5em;
|
|
103
107
|
}
|
|
104
|
-
.ultravisor-manifest-success-true {
|
|
105
|
-
color: #66bb6a;
|
|
106
|
-
}
|
|
107
|
-
.ultravisor-manifest-success-false {
|
|
108
|
-
color: #ef5350;
|
|
109
|
-
}
|
|
110
108
|
`,
|
|
111
109
|
|
|
112
110
|
Templates:
|
|
@@ -169,28 +167,28 @@ class UltravisorManifestListView extends libPictView
|
|
|
169
167
|
}
|
|
170
168
|
|
|
171
169
|
let tmpHTML = '<table class="ultravisor-manifest-table">';
|
|
172
|
-
tmpHTML += '<thead><tr><th>Run
|
|
170
|
+
tmpHTML += '<thead><tr><th>Run Hash</th><th>Operation</th><th>Status</th><th>Elapsed</th><th>Started</th><th>Actions</th></tr></thead>';
|
|
173
171
|
tmpHTML += '<tbody>';
|
|
174
172
|
|
|
175
173
|
for (let i = 0; i < tmpManifests.length; i++)
|
|
176
174
|
{
|
|
177
175
|
let tmpManifest = tmpManifests[i];
|
|
178
|
-
let
|
|
179
|
-
let
|
|
176
|
+
let tmpRunHash = tmpManifest.Hash || '';
|
|
177
|
+
let tmpEscHash = tmpRunHash.replace(/'/g, "\\'");
|
|
180
178
|
let tmpStatus = tmpManifest.Status || 'Unknown';
|
|
181
179
|
let tmpStatusClass = tmpStatus.toLowerCase();
|
|
182
|
-
if (tmpStatusClass !== 'complete' && tmpStatusClass !== 'running' && tmpStatusClass !== 'error')
|
|
180
|
+
if (tmpStatusClass !== 'complete' && tmpStatusClass !== 'running' && tmpStatusClass !== 'error' && tmpStatusClass !== 'waiting')
|
|
183
181
|
{
|
|
184
182
|
tmpStatusClass = '';
|
|
185
183
|
}
|
|
186
184
|
|
|
187
185
|
tmpHTML += '<tr>';
|
|
188
|
-
tmpHTML += '<td><code style="font-size:0.8em;">' +
|
|
189
|
-
tmpHTML += '<td>' + (tmpManifest.
|
|
190
|
-
tmpHTML += '<td><span class="ultravisor-manifest-status ' + tmpStatusClass + '">' + tmpStatus + '</span></td>';
|
|
191
|
-
tmpHTML += '<td
|
|
192
|
-
tmpHTML += '<td>' + (tmpManifest.StartTime || '') + '</td>';
|
|
193
|
-
tmpHTML += '<td><button class="ultravisor-btn-sm ultravisor-btn-edit" onclick="' + tmpViewRef + '.showManifestDetail(\'' +
|
|
186
|
+
tmpHTML += '<td><code style="font-size:0.8em;">' + this.escapeHTML(tmpRunHash) + '</code></td>';
|
|
187
|
+
tmpHTML += '<td>' + this.escapeHTML(tmpManifest.OperationHash || '') + '</td>';
|
|
188
|
+
tmpHTML += '<td><span class="ultravisor-manifest-status ' + tmpStatusClass + '">' + this.escapeHTML(tmpStatus) + '</span></td>';
|
|
189
|
+
tmpHTML += '<td>' + (tmpManifest.ElapsedMs ? tmpManifest.ElapsedMs + 'ms' : '') + '</td>';
|
|
190
|
+
tmpHTML += '<td>' + this.escapeHTML(tmpManifest.StartTime || '') + '</td>';
|
|
191
|
+
tmpHTML += '<td><button class="ultravisor-btn-sm ultravisor-btn-edit" onclick="' + tmpViewRef + '.showManifestDetail(\'' + tmpEscHash + '\')">Details</button></td>';
|
|
194
192
|
tmpHTML += '</tr>';
|
|
195
193
|
}
|
|
196
194
|
|
|
@@ -198,9 +196,9 @@ class UltravisorManifestListView extends libPictView
|
|
|
198
196
|
this.pict.ContentAssignment.assignContent('#Ultravisor-ManifestList-Body', tmpHTML);
|
|
199
197
|
}
|
|
200
198
|
|
|
201
|
-
showManifestDetail(
|
|
199
|
+
showManifestDetail(pRunHash)
|
|
202
200
|
{
|
|
203
|
-
this.pict.PictApplication.loadManifest(
|
|
201
|
+
this.pict.PictApplication.loadManifest(pRunHash,
|
|
204
202
|
function (pError, pManifest)
|
|
205
203
|
{
|
|
206
204
|
if (pError || !pManifest)
|
|
@@ -211,48 +209,52 @@ class UltravisorManifestListView extends libPictView
|
|
|
211
209
|
}
|
|
212
210
|
|
|
213
211
|
let tmpHTML = '<div class="ultravisor-manifest-detail visible">';
|
|
214
|
-
tmpHTML += '<h3>Run: ' + (pManifest.
|
|
215
|
-
tmpHTML += '<p><strong>Operation:</strong> ' + (pManifest.
|
|
216
|
-
tmpHTML += '<p><strong>Status:</strong> ' + (pManifest.Status || '') + '
|
|
217
|
-
tmpHTML += '<p><strong>Start:</strong> ' + (pManifest.StartTime || '') + ' · <strong>Stop:</strong> ' + (pManifest.StopTime || '') + '</p>';
|
|
212
|
+
tmpHTML += '<h3>Run: ' + this.escapeHTML(pManifest.Hash || '') + '</h3>';
|
|
213
|
+
tmpHTML += '<p><strong>Operation:</strong> ' + this.escapeHTML(pManifest.OperationHash || '') + '</p>';
|
|
214
|
+
tmpHTML += '<p><strong>Status:</strong> ' + this.escapeHTML(pManifest.Status || '') + '</p>';
|
|
215
|
+
tmpHTML += '<p><strong>Start:</strong> ' + this.escapeHTML(pManifest.StartTime || '') + ' · <strong>Stop:</strong> ' + this.escapeHTML(pManifest.StopTime || '') + '</p>';
|
|
216
|
+
tmpHTML += '<p><strong>Elapsed:</strong> ' + (pManifest.ElapsedMs || 0) + 'ms</p>';
|
|
218
217
|
|
|
219
|
-
|
|
218
|
+
// Task Outputs
|
|
219
|
+
if (pManifest.TaskOutputs && Object.keys(pManifest.TaskOutputs).length > 0)
|
|
220
220
|
{
|
|
221
|
-
tmpHTML += '<
|
|
221
|
+
tmpHTML += '<h3>Task Outputs</h3>';
|
|
222
|
+
tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(JSON.stringify(pManifest.TaskOutputs, null, 2)) + '</div>';
|
|
222
223
|
}
|
|
223
224
|
|
|
224
|
-
// Task
|
|
225
|
-
|
|
226
|
-
if (tmpTaskResults.length > 0)
|
|
225
|
+
// Task Manifests (object keyed by node hash)
|
|
226
|
+
if (pManifest.TaskManifests && Object.keys(pManifest.TaskManifests).length > 0)
|
|
227
227
|
{
|
|
228
|
-
tmpHTML += '<h3>Task
|
|
229
|
-
|
|
228
|
+
tmpHTML += '<h3>Task Manifests</h3>';
|
|
229
|
+
let tmpNodeHashes = Object.keys(pManifest.TaskManifests);
|
|
230
|
+
for (let i = 0; i < tmpNodeHashes.length; i++)
|
|
230
231
|
{
|
|
231
|
-
let
|
|
232
|
+
let tmpNodeHash = tmpNodeHashes[i];
|
|
233
|
+
let tmpTaskManifest = pManifest.TaskManifests[tmpNodeHash];
|
|
232
234
|
tmpHTML += '<div class="ultravisor-manifest-task-result">';
|
|
233
235
|
tmpHTML += '<div class="ultravisor-manifest-task-result-header">';
|
|
234
|
-
tmpHTML += '<code>' + (
|
|
235
|
-
tmpHTML += '<span class="ultravisor-manifest-status ' + (
|
|
236
|
+
tmpHTML += '<code>' + this.escapeHTML(tmpNodeHash) + '</code>';
|
|
237
|
+
tmpHTML += '<span class="ultravisor-manifest-status ' + (tmpTaskManifest.Status || '').toLowerCase() + '">' + this.escapeHTML(tmpTaskManifest.Status || '') + '</span>';
|
|
236
238
|
tmpHTML += '</div>';
|
|
237
|
-
|
|
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)
|
|
239
|
+
if (tmpTaskManifest.Output)
|
|
245
240
|
{
|
|
246
|
-
tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(
|
|
241
|
+
tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(JSON.stringify(tmpTaskManifest.Output, null, 2)) + '</div>';
|
|
247
242
|
}
|
|
248
243
|
tmpHTML += '</div>';
|
|
249
244
|
}
|
|
250
245
|
}
|
|
251
246
|
|
|
252
|
-
//
|
|
247
|
+
// Errors
|
|
248
|
+
if (pManifest.Errors && pManifest.Errors.length > 0)
|
|
249
|
+
{
|
|
250
|
+
tmpHTML += '<h3 style="color:#ef5350;">Errors</h3>';
|
|
251
|
+
tmpHTML += '<div class="ultravisor-manifest-output" style="border: 1px solid #ef5350;">' + this.escapeHTML(pManifest.Errors.join('\n')) + '</div>';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Log
|
|
253
255
|
if (pManifest.Log && pManifest.Log.length > 0)
|
|
254
256
|
{
|
|
255
|
-
tmpHTML += '<h3>
|
|
257
|
+
tmpHTML += '<h3>Log</h3>';
|
|
256
258
|
tmpHTML += '<div class="ultravisor-manifest-output">' + this.escapeHTML(pManifest.Log.join('\n')) + '</div>';
|
|
257
259
|
}
|
|
258
260
|
|