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

Commit a6d4a57

Browse files
committed
some attempts to clean up wskflow
Fixes #443 Fixes #112
1 parent 51476a1 commit a6d4a57

File tree

11 files changed

+641
-314
lines changed

11 files changed

+641
-314
lines changed

app/content/css/themes/ibm.css

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ body {
2626
--color-brand-01: #3d70b2;
2727
--color-brand-01-10: hsla(214, 49%, 47%, 0.1); /* 10% opacity */
2828
--color-brand-02: #5596e6;
29+
--color-brand-03: #00b4a0;
2930
--color-ui-01: #fff;
3031
--color-ui-02: #f5f7fa;
3132
--color-ui-03: #f0f3f6;
@@ -255,23 +256,6 @@ body.subwindow sidecar {
255256
font-family: var(--font-sans-serif);
256257
}
257258

258-
#wskflowSVG .node.leaf rect {
259-
stroke: var(--color-text-01) !important;
260-
}
261-
#wskflowSVG .node.leaf rect {
262-
stroke: var(--color-text-01) !important;
263-
}
264-
#wskflowSVG .action[data-deployed="deployed"] rect, #wskflowSVG .function:not([data-status]) rect {
265-
fill: hsla(210, 94%, 67%, 1) !important;
266-
}
267-
#wskflowSVG .action[data-deployed="deployed"] rect:hover, #wskflowSVG .function:not([data-status]) rect:hover {
268-
fill: hsla(210, 94%, 57%, 1) !important;
269-
}
270-
#wskflowSVG .action[data-deployed="not-deployed"] rect {
271-
fill: var(--color-ui-04) !important;
272-
}
273-
274-
275259
/* sans 300 */
276260
@font-face {
277261
font-family: ibm-plex-sans;

app/content/css/ui.css

Lines changed: 180 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,33 +1458,211 @@ body.oops-total-catastrophe #restart-needed-warning {
14581458
display: flex;
14591459
align-items: center;
14601460
opacity: 0;
1461+
z-index: 10;
1462+
position: absolute;
1463+
pointer-events: none;
1464+
}
1465+
#qtipArrow {
1466+
position: relative;
1467+
left: 3px;
1468+
top: 1px;
1469+
color: #2E4053
1470+
}
1471+
#qtipContent {
1472+
background-color: #2E4053;
1473+
color: white;
1474+
font-size: 0.75em;
1475+
padding: 1ex;
1476+
/*display: flex;
1477+
flex-wrap: wrap;*/
1478+
margin: 0px;
1479+
margin-right: 1ex; /* don't get all squished up against the right-end edge of the window */
1480+
max-width: 40ex;
1481+
word-wrap: break-word;
14611482
}
14621483
#qtip.visible {
1463-
opacity: 1;
1484+
opacity: 0.975;
1485+
}
1486+
#qtip.qtip-pre #qtipContent {
1487+
overflow: hidden;
1488+
white-space: pre;
1489+
text-overflow: ellipsis;
1490+
display: initial !important; /* override display: flex */
14641491
}
14651492
break {
14661493
flex-basis: 100%;
14671494
}
1495+
#wskflowSVG .edge-label {
1496+
font-size: 5px;
1497+
font-weight: 300;
1498+
}
1499+
#wskflowSVG .node.clickable[data-deployed="not-deployed"]:hover,
1500+
#wskflowSVG .node.clickable:hover .edge-label,
1501+
#wskflowSVG .node.clickable[data-deployed="not-deployed"]:hover rect {
1502+
/* no hover effects for not-deployed actions */
1503+
text-decoration: none;
1504+
cursor: inherit !important;
1505+
}
1506+
#wskflowSVG[data-is-session-flow="true"] .node.leaf[data-status="not-run"] rect {
1507+
/* not-run nodes in a session flow */
1508+
mask: url(#mask-stripe);
1509+
}
1510+
#wskflowSVG[data-is-session-flow="true"] .edge-label:not(.edge-was-traversed) {
1511+
fill: var(--color-text-02) !important;
1512+
opacity: 0.6
1513+
}
1514+
#wskflowSVG[data-is-session-flow="true"] .node.leaf[data-status="not-run"] rect,
1515+
#wskflowSVG[data-is-session-flow="true"] .node.leaf[data-status="not-run"] text {
1516+
/* deemphasize not-visited nodes in session flow */
1517+
fill: var(--color-ui-04) !important;
1518+
opacity: 0.6;
1519+
}
14681520
#wskflowSVG .node rect.atom {
14691521
/* wskflow node effect */
14701522
transition: all 150ms ease-in-out;
1523+
vector-effect: non-scaling-stroke;
14711524
}
14721525
#wskflowSVG path {
14731526
/* path effects */
14741527
transition: all 150ms ease-in-out;
1528+
vector-effect: non-scaling-stroke;
1529+
stroke-width: 1.5;
1530+
stroke: var(--color-text-02) !important;
14751531
}
1476-
#wskflowSVG path.hover {
1532+
#wskflowSVG #retryIconNormal path {
1533+
/* the retry loop doesn't need a stroke */
1534+
stroke: none !important;
1535+
}
1536+
#wskflowSVG path.forwardingLink {
1537+
stroke: rgb(52, 152, 219) !important;
14771538
stroke-width: 2;
1539+
pointer-events: all;
1540+
}
1541+
#wskflowSVG path.hover, #wskflowSVG path:hover {
1542+
stroke-width: 3.5;
14781543
}
14791544
#wskflowSVG path.true-branch.hover {
1545+
stroke: orange !important;
14801546
marker-end: url(#trueEnd);
14811547
}
14821548
#wskflowSVG path.false-branch.hover {
1549+
stroke: #DC7633 !important;
14831550
marker-end: url(#falseEnd);
14841551
}
14851552
#wskflowSVG path.forwarding-edge.hover {
14861553
marker-end: url(#forwardingEnd);
14871554
}
1555+
#wskflowSVG .node.leaf.Entry rect, #wskflowSVG .node.leaf.Exit rect {
1556+
fill: var(--color-text-01);
1557+
}
1558+
#wskflowSVG .node.leaf.Entry text, #wskflowSVG .node.leaf.Exit text {
1559+
fill: var(--color-ui-02) !important;
1560+
font-weight: 300;
1561+
font-variant: small-caps;
1562+
}
1563+
#wskflowSVG .node rect, #wskflowSVG .node rect {
1564+
fill: var(--color-ui-05);
1565+
}
1566+
#wskflowSVG .node.leaf[data-status="success"] rect, #wskflowSVG .node.leaf.function[data-status="success"] rect {
1567+
fill: #2166ac !important;
1568+
stroke: var(--color-text-01) !important;
1569+
}
1570+
#wskflowSVG .node.leaf[data-status="failed"] rect, #wskflowSVG .node.leaf.function[data-status="failed"] rect {
1571+
fill: var(--color-support-01) !important;
1572+
}
1573+
#wskflowSVG .node.leaf[data-status="success"] text:not(.edge-label), #wskflowSVG .node.leaf.function[data-status="success"] text:not(.edge-label),
1574+
#wskflowSVG .node.leaf[data-status="failed"] text:not(.edge-label), #wskflowSVG .node.leaf.function[data-status="failed"] text:not(.edge-label) {
1575+
fill: var(--color-ui-01) !important;
1576+
}
1577+
#wskflowSVG .node.leaf.function[data-status="success"] text,
1578+
#wskflowSVG .node.leaf.function[data-status="failed"] text {
1579+
-webkit-font-smoothing: antialiased;
1580+
}
1581+
#wskflowSVG .node.leaf rect {
1582+
stroke: var(--color-text-01) !important;
1583+
stroke-width: 2;
1584+
}
1585+
#wskflowSVG .node.leaf rect {
1586+
stroke: var(--color-text-01) !important;
1587+
}
1588+
#wskflowSVG .action[data-deployed="deployed"] rect {
1589+
fill: var(--color-ui-02) !important;
1590+
}
1591+
#wskflowSVG .action[data-deployed="deployed"] text:not(.edge-label) {
1592+
fill: var(--color-text-01) !important;
1593+
}
1594+
#wskflowSVG .action[data-deployed="deployed"] rect:hover {
1595+
fill: var(--color-support-04) !important;
1596+
}
1597+
#wskflowSVG .action[data-deployed="not-deployed"] rect {
1598+
mask: url(#mask-stripe);
1599+
/*fill: var(--color-support-03);*/
1600+
}
1601+
#wskflowSVG .node.leaf.function rect {
1602+
/* these are represented as smaller boxes, so use a lighter stroke */
1603+
stroke-width: 1.25;
1604+
}
1605+
#wskflowSVG .node.leaf.function rect {
1606+
fill: var(--color-support-03) !important;
1607+
stroke: var(--color-ui-05) !important;
1608+
}
1609+
#qtip .qtip-prefix {
1610+
font-weight: bold;
1611+
}
1612+
#qtip .qtip-prefix.red-text {
1613+
filter: brightness(1.5); /* make it more legible against the qtip background */
1614+
padding-right: 5px;
1615+
}
1616+
#qtip .qtip-prefix.action {
1617+
color: var(--color-support-04); /* match hover color of action nodes */
1618+
}
1619+
#qtip .qtip-prefix.function {
1620+
color: var(--color-support-03);
1621+
}
1622+
#qtip .qtip-prefix.let, #qtip .qtip-prefix.literal {
1623+
color: var(--color-brand-02);
1624+
filter: brightness(2); /* too dim against the qtip background */
1625+
}
1626+
#wskflowSVG .node.leaf.let rect, #wskflowSVG .node.leaf.literal rect {
1627+
/*fill: var(--color-brand-03);
1628+
stroke: var(--color-text-01) !important;*/
1629+
fill: transparent;
1630+
stroke: transparent !important;
1631+
}
1632+
#wskflowSVG .node.leaf.let text, #wskflowSVG .node.leaf.literal text {
1633+
/*fill: var(--color-ui-01) !important;*/
1634+
fill: var(--color-brand-03) !important;
1635+
font-size: 12px;
1636+
font-weight: bold;
1637+
letter-spacing: 2px;
1638+
}
1639+
#wskflowSVG .node.leaf.function text:not(.edge-label) {
1640+
/* function nodes; use code font */
1641+
fill: var(--color-text-01) !important;
1642+
font-family: var(--font-monospace);
1643+
font-size: 0.275em;
1644+
}
1645+
#wskflowSVG .node.compound:not(.root) rect {
1646+
stroke-dasharray: 1;
1647+
stroke: var(--color-brand-01) !important;
1648+
fill: var(--color-ui-02) !important;
1649+
}
1650+
#wskflowSVG .node.try rect, #wskflowSVG .node.handler rect {
1651+
}
1652+
#wskflowSVG .node.compound text {
1653+
/* e.g. Try and Catch labels */
1654+
font-weight: bold;
1655+
}
1656+
#wskflowSVG .node.compound.try_catch.no-parents rect {
1657+
stroke: none !important;
1658+
}
1659+
#wskflowSVG .node.compound.try_catch rect {
1660+
stroke: var(--color-ui-05) !important;
1661+
fill: transparent !important;
1662+
}
1663+
#wskflowSVG .node.compound.try_catch text {
1664+
display: none;
1665+
}
14881666

14891667
/* help widget */
14901668
.help-widget {

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

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,9 @@ exports.handleError = (err, reject) => {
566566
*
567567
* @return { view, controller } where controller is the API exported by graph2doms
568568
*/
569-
exports.wskflow = (visualize, viewName, { fsm, input, name, packageName}) => {
569+
exports.wskflow = (visualize, viewName, { fsm, input, name, packageName, viewOptions }) => {
570570

571-
const { view, controller } = visualize(fsm);
571+
const { view, controller } = visualize(fsm, undefined, undefined, undefined, undefined, viewOptions);
572572

573573
const onclick = undefined
574574
ui.addNameToSidecarHeader(undefined, name, packageName, onclick, viewName,
@@ -617,13 +617,39 @@ exports.zoomToFitButtons = controller => {
617617
}
618618
}
619619

620+
/**
621+
* Turn an options struct into a cli string
622+
*
623+
* @param options is the command line options struct given by the
624+
* user.
625+
*
626+
*/
627+
const optionsToString = options => {
628+
let str = ''
629+
for (let key in options) {
630+
// underscore comes from minimist
631+
if (key !== '_' && options[key] !== undefined && key !== 'name' && key !== 'theme') {
632+
const dash = key.length === 1 ? '-' : '--',
633+
prefix = options[key] === false ? 'no-' : '', // e.g. --no-help
634+
value = options[key] === true || options[key] === false ? '' : ` ${options[key]}`
635+
636+
if (! (dash === '-' && options[key] === false)) {
637+
// avoid -no-q, i.e. single dash
638+
str = `${str} ${dash}${prefix}${key}${value}`
639+
}
640+
}
641+
}
642+
643+
return str
644+
}
645+
620646
/**
621647
* Entity view modes
622648
*
623649
*/
624-
exports.vizAndfsmViewModes = (visualize, commandPrefix, defaultMode='visualization') => [
650+
exports.vizAndfsmViewModes = (visualize, commandPrefix, defaultMode='visualization', options) => [
625651
{ mode: 'visualization', defaultMode: defaultMode==='visualization', direct: entity => {
626-
return repl.qexec(`${commandPrefix} "${entity.input}"`)
652+
return repl.qexec(`${commandPrefix} "${entity.input}" ${optionsToString(options)}`)
627653
} },
628654
{ mode: 'fsm', label: 'JSON', defaultMode: defaultMode==='fsm', direct: entity => {
629655
entity.type = 'actions'
@@ -661,7 +687,7 @@ exports.hasUnknownOptions = (options, expected) => {
661687
* like an app
662688
*
663689
*/
664-
exports.decorateAsApp = ({action, viewName='app', commandPrefix='app get', doVisualize}) => {
690+
exports.decorateAsApp = ({action, viewName='app', commandPrefix='app get', doVisualize, options}) => {
665691
action.prettyType = appBadge
666692
action.fsm = action.annotations.find(({key}) => key === 'fsm').value
667693

@@ -670,11 +696,18 @@ exports.decorateAsApp = ({action, viewName='app', commandPrefix='app get', doVis
670696
}
671697

672698
if (doVisualize) {
699+
// pass through cli options for the wskflow renderer
700+
const viewOptions = { }
701+
if (options.functions) {
702+
// note we must be careful not to pass false; only undefined
703+
viewOptions.renderFunctionsInView = options.functions // render all inline functions directly in the view?
704+
}
705+
673706
const visualize = require(path.join(__dirname, '../../wskflow/lib/visualize'))
674-
const { view, controller } = exports.wskflow(visualize, viewName, action)
707+
const { view, controller } = exports.wskflow(visualize, viewName, Object.assign({}, action, { viewOptions }))
675708

676709
action.modes = (action.modes||[]).filter(_ => _.mode !== 'code')
677-
.concat(exports.vizAndfsmViewModes(visualize, commandPrefix))
710+
.concat(exports.vizAndfsmViewModes(visualize, commandPrefix, undefined, options))
678711
.concat(exports.zoomToFitButtons(controller))
679712

680713
return view

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module.exports = (commandTree, prequire) => {
3737
appName = args[idx + 1]
3838

3939
return repl.qexec(`wsk action get "${appName}"`, undefined, undefined,
40-
Object.assign({}, execOptions, { override: true }))
40+
Object.assign({}, execOptions, { override: true, originalOptions: options }))
4141
}
4242

4343
const cmd = commandTree.listen(`/wsk/app/get`, doGet('get'), { usage: usage('get'),
@@ -63,7 +63,8 @@ module.exports = (commandTree, prequire) => {
6363

6464
if (action && action.annotations && action.annotations.find(({key}) => key === 'fsm')) {
6565
const doVisualize = execOptions.override || !execOptions.nested,
66-
content = decorateAsApp({ action, doVisualize }),
66+
options = execOptions.originalOptions || {},
67+
content = decorateAsApp({ action, doVisualize, options }),
6768
input = `/${response.namespace}/${response.name}`
6869

6970
if (doVisualize) {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ exports.app_get = command => ({
102102
header: 'Displays the details of a given composition',
103103
example: `app ${command} <appName>`,
104104
required: [{ name: 'appName', docs: 'the name of your composition', entity: 'action' }],
105-
optional: [{ name: '--cli', boolean: true, docs: 'display the results textually (headless mode only)' }],
105+
optional: [{ name: '--cli', boolean: true, docs: 'display the results textually (headless mode only)' },
106+
{ name: '--functions', alias: '-f', boolean: true, docs: 'show all functions directly in the view' }
107+
],
106108
parents: ['composer', { command: 'composer app' }],
107109
related: ['app create', 'app invoke', 'app list']
108110
})
@@ -161,6 +163,7 @@ exports.preview = command => ({
161163
oneof: [{ name: 'src.js', docs: 'generate a preview of a Composer source file', file: true },
162164
{ name: 'src.json', docs: 'ibid, but for a pre-compiled composition', file: true }],
163165
optional: [{ name: '--fsm', boolean: true, docs: 'validate and show raw FSM' },
166+
{ name: '--functions', alias: '-f', boolean: true, docs: 'show all functions directly in the view' },
164167
{ name: '--env', alias: '-e', docs: 'Assign a value to an environment variable', narg: 2 }],
165168
sampleInputs: sampleInputs(command),
166169
parents: ['composer', { command: 'composer app' }],

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,16 @@ module.exports = (commandTree, prequire) => {
6464

6565
// create a fake action/entity record
6666
const formatForUser = defaultMode => ({fsm,code}) => {
67-
68-
const {visualize} = prequire('wskflow')
69-
const { view, controller } = wskflow(visualize, viewName, { fsm, input, name })
67+
68+
// pass through cli options for the wskflow renderer
69+
const viewOptions = { }
70+
if (options.functions) {
71+
// note we must be careful not to pass false; only undefined
72+
viewOptions.renderFunctionsInView = options.functions // render all inline functions directly in the view?
73+
}
74+
75+
const {visualize} = prequire('wskflow')
76+
const { view, controller } = wskflow(visualize, viewName, { fsm, input, name, viewOptions })
7077
extraModes = extraModes.concat(zoomToFitButtons(controller))
7178

7279
const entity = {
@@ -81,7 +88,7 @@ module.exports = (commandTree, prequire) => {
8188
exec: {
8289
kind: 'source'
8390
},
84-
modes: vizAndfsmViewModes(visualize, viewName, defaultMode).concat(extraModes),
91+
modes: vizAndfsmViewModes(visualize, viewName, defaultMode, options).concat(extraModes),
8592
annotations: [
8693
{ key: 'wskng.combinators',
8794
value: [{ role: 'replacement', type: 'composition', badge: type } ]

0 commit comments

Comments
 (0)