Skip to content
This repository was archived by the owner on Dec 17, 2024. It is now read-only.

Commit a156631

Browse files
committed
improve ability for wskflow to be incorporated into other views
Fixes #920
1 parent 2b7047f commit a156631

File tree

7 files changed

+86
-24
lines changed

7 files changed

+86
-24
lines changed

app/content/js/bottom-stripe.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const addModeButton = (bottomStripe, opts, entity, show) => {
3232
const {mode, label, flush, selected, selectionController, visibleWhen,
3333
fontawesome, labelBelow, // show label below the fontawesome?
3434
balloon, balloonLength, data, command=()=>mode, direct,
35-
defaultMode, actAsButton, radioButton=false, echo=false, noHistory=true} = opts
35+
defaultMode, actAsButton, radioButton=false, echo=false, noHistory=true, replSilence=true} = opts
3636

3737
if (visibleWhen && visibleWhen !== show) {
3838
// only visible when a specific mode is active!
@@ -177,7 +177,7 @@ const addModeButton = (bottomStripe, opts, entity, show) => {
177177
})
178178
}
179179
} else {
180-
repl.pexec(command(entity), { leaveBottomStripeAlonex: true, echo, noHistory })
180+
repl.pexec(command(entity), { leaveBottomStripeAlonex: true, echo, noHistory, replSilence })
181181
}
182182
}
183183
}

app/content/js/repl.js

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,71 @@ const formatOneListResult = options => (entity, idx, A) => {
8686
prefix.appendChild(prettyType)*/
8787

8888
/** add a cell to the current row of the list view we] are generating. "entityName" is the current row */
89-
const addCell = (className, value, innerClassName='', parent=entityName) => {
89+
const addCell = (className, value, innerClassName='', parent=entityName, onclick, watch) => {
9090
const cell = document.createElement('span'),
9191
inner = document.createElement('span')
9292
cell.className = className
9393
inner.className = innerClassName
94-
inner.appendChild(value.nodeName ? value : document.createTextNode(value.toString()))
94+
if (value) {
95+
inner.appendChild(value.nodeName ? value : document.createTextNode(value.toString()))
96+
} else {
97+
console.error('Invalid cell model, no value field')
98+
}
9599
cell.appendChild(inner)
96100
parent.appendChild(cell)
101+
102+
if (onclick) {
103+
cell.classList.add('clickable')
104+
cell.onclick = onclick
105+
}
106+
107+
if (watch) {
108+
const spinner = document.createElement('i')
109+
spinner.className = 'fas fa-spinner fa-pulse small-left-pad deemphasize'
110+
cell.appendChild(spinner)
111+
112+
const interval = setInterval(() => {
113+
try {
114+
Promise.resolve(watch())
115+
.then(({ value, done=false, css }) => {
116+
117+
// update the styling
118+
if (css) {
119+
inner.className = css
120+
}
121+
122+
// update the text
123+
if (value) {
124+
inner.innerText = ''
125+
inner.appendChild(value.nodeName ? value : document.createTextNode(value.toString()))
126+
}
127+
128+
// are we done polling for updates?
129+
if (!value || done) {
130+
clearInterval(interval)
131+
132+
const toRemove = cell.querySelector('.fa-spinner')
133+
cell.removeChild(toRemove)
134+
}
135+
})
136+
137+
} catch (err) {
138+
console.error('Error watching value', err)
139+
clearInterval(interval)
140+
141+
const toRemove = cell.querySelector('.fa-spinner')
142+
cell.removeChild(toRemove)
143+
}
144+
145+
}, 2000)
146+
}
147+
97148
return cell
98149
}
99150

100151
// add any attributes that should appear *before* the name column
101152
if (entity.beforeAttributes) {
102-
entity.beforeAttributes.forEach(({value, css='', outerCSS=''}) => addCell(outerCSS, value, css))
153+
entity.beforeAttributes.forEach(({value, css='', outerCSS='', onclick}) => addCell(outerCSS, value, css, undefined, onclick))
103154
}
104155

105156
// now add the clickable name
@@ -117,7 +168,7 @@ const formatOneListResult = options => (entity, idx, A) => {
117168
entityName.appendChild(entityNameGroup)
118169

119170
// name of the entity
120-
let name = entity.name
171+
let name = entity.prettyName || entity.name
121172

122173
// click handler for the list result
123174
if (typeof name === 'string') {
@@ -144,7 +195,7 @@ const formatOneListResult = options => (entity, idx, A) => {
144195
// case-specific cells
145196
//
146197
if (entity.attributes) {
147-
entity.attributes.forEach(({value, css='', outerCSS=''}) => addCell(outerCSS, value, css))
198+
entity.attributes.forEach(({value, css='', outerCSS='', watch, onclick}) => addCell(outerCSS, value, css, undefined, onclick, watch))
148199

149200
} else if (entity.type === 'actions') {
150201
// action-specific cells
@@ -281,6 +332,8 @@ const printResults = (block, nextBlock, resultDom, echo=true, execOptions, parse
281332
if (echo) {
282333
ui.showCustom(response, execOptions)
283334
ui.ok(resultDom.parentNode)
335+
} else if (execOptions && execOptions.replSilence) {
336+
ui.showCustom(response, execOptions)
284337
}
285338

286339
} else if (response.type === 'activations') {
@@ -345,7 +398,7 @@ self.init = (prefs={}) => {
345398
}
346399

347400
// focus the current prompt no matter where the user clicks
348-
document.body.onclick = evt => {
401+
document.querySelector('#main-repl').onclick = evt => {
349402
if (!window.getSelection().toString()) {
350403
// if there is no selected text, then focus
351404
// this works, because the HTML (? or chrome?) section model behavior is to clear the selection upon click
@@ -607,7 +660,7 @@ self.exec = (commandUntrimmed, execOptions) => {
607660
debug('exec', commandUntrimmed)
608661

609662
const echo = !execOptions || execOptions.echo !== false
610-
const nested = execOptions && execOptions.noHistory
663+
const nested = execOptions && execOptions.noHistory && !execOptions.replSilence
611664
if (nested) execOptions.nested = nested
612665

613666
const block = execOptions && execOptions.block || ui.getCurrentBlock(),

app/content/js/ui.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,8 @@ const ui = (function() {
962962
sidecar.entity = entity
963963
sidecar.entity.type = sidecar.entity.viewName
964964

965-
self.addNameToSidecarHeader(sidecar, entity.name, entity.packageName, undefined,
966-
entity.prettyType || entity.type, undefined, entity)
965+
self.addNameToSidecarHeader(sidecar, entity.prettyName || entity.name, entity.packageName, undefined,
966+
entity.prettyType || entity.type, entity.subtext, entity)
967967

968968
// render badges
969969
if (!entity.activationId) {

app/plugins/modules/composer/lib/composer.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -562,17 +562,21 @@ exports.handleError = (err, reject) => {
562562
}
563563

564564
/**
565-
* Render the wskflow visualization for the given fsm
565+
* Render the wskflow visualization for the given fsm.
566+
*
567+
* `container` is optional; wskflow will render in the default way in
568+
* the sidecar if we don't pass a container in
566569
*
567570
* @return { view, controller } where controller is the API exported by graph2doms
568571
*/
569-
exports.wskflow = (visualize, viewName, { fsm, input, name, packageName, viewOptions }) => {
570-
571-
const { view, controller } = visualize(fsm, undefined, undefined, undefined, undefined, viewOptions);
572+
exports.wskflow = (visualize, viewName, { fsm, input, name, packageName, viewOptions, container }) => {
573+
const { view, controller } = visualize(fsm, container, undefined, undefined, undefined, viewOptions);
572574

573-
const onclick = undefined
574-
ui.addNameToSidecarHeader(undefined, name, packageName, onclick, viewName,
575-
'This is a preview of your app, it is not yet deployed')
575+
if (!viewOptions || !viewOptions.noHeader) {
576+
const onclick = undefined
577+
ui.addNameToSidecarHeader(undefined, name, packageName, onclick, viewName,
578+
'This is a preview of your app, it is not yet deployed')
579+
}
576580

577581
return { view, controller }
578582
}

app/plugins/modules/composer/lib/viz.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const viewName = 'preview', // for back button and sidecar header
3838
*
3939
*/
4040
module.exports = (commandTree, prequire) => {
41-
const render = (input, options) => new Promise((resolve, reject) => {
41+
const render = (input, options, execOptions) => new Promise((resolve, reject) => {
4242
debug('options', options)
4343
let fsmPromise, type, extraModes=[]
4444

@@ -64,16 +64,21 @@ module.exports = (commandTree, prequire) => {
6464

6565
// create a fake action/entity record
6666
const formatForUser = defaultMode => ({fsm,code}) => {
67-
6867
// pass through cli options for the wskflow renderer
6968
const viewOptions = { }
69+
7070
if (options.functions) {
7171
// note we must be careful not to pass false; only undefined
7272
viewOptions.renderFunctionsInView = options.functions // render all inline functions directly in the view?
7373
}
7474

75+
if (execOptions.container) {
76+
// if we're rendering this inside of a given viewport, then don't modify the sidecar header
77+
viewOptions.noHeader = true
78+
}
79+
7580
const {visualize} = prequire('wskflow')
76-
const { view, controller } = wskflow(visualize, viewName, { fsm, input, name, viewOptions })
81+
const { view, controller } = wskflow(visualize, viewName, { fsm, input, name, viewOptions, container: execOptions.container })
7782
extraModes = extraModes.concat(zoomToFitButtons(controller))
7883

7984
const entity = {
@@ -177,7 +182,7 @@ module.exports = (commandTree, prequire) => {
177182
options.alreadyWatching = execOptions.alreadyWatching;
178183
}
179184

180-
render(input, options).then(resolve, reject)
185+
render(input, options, execOptions).then(resolve, reject)
181186

182187
// and set up a file watcher to re-render upon change of the file
183188
if (!execOptions || !execOptions.alreadyWatching) {

app/plugins/modules/wskflow/lib/fsm2graph.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ function fsm2graph(ir, containerElement, acts, options){
604604
// warn user about not-deployed actions (but only if !activations, i.e. not for session flow)
605605
if (notDeployed.length > 0 && !activations) {
606606
const container = document.querySelector('#sidecar .sidecar-header .sidecar-header-secondary-content .custom-header-content')
607-
if (container) {
607+
if (container && !options.noHeader) {
608608
const css = {
609609
message: 'wskflow-undeployed-action-warning',
610610
text: 'wskflow-undeployed-action-warning-text',

app/plugins/modules/wskflow/lib/graph2doms.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ function graph2doms(JSONgraph, ifReuseContainer, activations){
8181
let zoom = d3.behavior.zoom()
8282
.on("zoom", redraw);
8383

84-
let containerElement = $(`<div id="${containerId}" style="display: flex; flex: 1; width: 100%; height: 100%;"></div>`),
84+
let containerElement = ifReuseContainer || $(`<div id="${containerId}" style="display: flex; flex: 1; width: 100%; height: 100%;"></div>`),
8585
wskflowContainer = $('<div id="wskflowContainer"></div>'),
8686
enterClickMode = false;
8787

0 commit comments

Comments
 (0)