From bf99b19140fe9840adf2673b042da029b07bf7c2 Mon Sep 17 00:00:00 2001 From: Michael Mancini Date: Mon, 7 Mar 2022 17:10:34 -0500 Subject: [PATCH 1/7] hotkeys --- apps/st2-workflows/workflows.component.js | 47 +++++++++++------ modules/st2flow-canvas/index.js | 64 +++++++++++++++++++---- modules/st2flow-palette/action.js | 15 +++++- modules/st2flow-palette/style.css | 2 + tasks/lint.js | 2 +- 5 files changed, 102 insertions(+), 28 deletions(-) diff --git a/apps/st2-workflows/workflows.component.js b/apps/st2-workflows/workflows.component.js index 8cd73ff75..fce01333b 100644 --- a/apps/st2-workflows/workflows.component.js +++ b/apps/st2-workflows/workflows.component.js @@ -34,18 +34,6 @@ import globalStore from '@stackstorm/module-store'; import store from './store'; import style from './style.css'; -function guardKeyHandlers(obj, names) { - const filteredObj = pick(obj, names); - return mapValues(filteredObj, fn => { - return e => { - if(e.target === document.body) { - e.preventDefault(); - fn.call(obj); - } - }; - }); -} - const POLL_INTERVAL = 5000; @connect( @@ -296,11 +284,39 @@ export default class Workflows extends Component { style = style keyMap = { - undo: [ 'ctrl+z', 'meta+z' ], - redo: [ 'ctrl+shift+z', 'meta+shift+z' ], + copy: [ 'ctrl+c', 'command+c', 'meta+c' ], + cut: [ 'ctrl+x', 'command+x', 'meta+x' ], + paste: [ 'ctrl+v', 'command+v', 'meta+v' ], + open: [ 'ctrl+o', 'command+o', 'meta+o' ], + undo: [ 'ctrl+z', 'command+z', 'meta+z' ], + redo: [ 'ctrl+shift+z', 'command+shift+z', 'meta+shift+z' ], + save: [ 'ctrl+s', 'command+s', 'meta+s' ], handleTaskDelete: [ 'del', 'backspace' ], } + keyHandlers = { + undo: () => { + store.dispatch({ type: 'FLOW_UNDO' }); + }, + redo: () => { + store.dispatch({ type: 'FLOW_REDO' }); + }, + save: (x) => { + x.preventDefault(); + x.stopPropagation(); + this.save().then(() => null); + }, + copy: () => { + store.dispatch({ type: 'PUSH_WARNING', source: 'icon-save', message: 'Select a task to copy' }); + }, + cut: () => { + store.dispatch({ type: 'PUSH_WARNING', source: 'icon-save', message: 'Nothing to cut' }); + }, + paste: () => { + store.dispatch({ type: 'PUSH_WARNING', source: 'icon-save', message: 'Nothing to paste' }); + }, + } + render() { // const { isCollapsed = {}, toggleCollapse, actions, undo, redo, layout, meta, input, dirty } = this.props; const { isCollapsed = {}, actions, undo, redo, layout, meta, input, dirty} = this.props; @@ -326,8 +342,7 @@ export default class Workflows extends Component { this.props.fetchActions()} saveData={e => this.save()} dirtyflag={this.props.dirty}> diff --git a/modules/st2flow-canvas/index.js b/modules/st2flow-canvas/index.js index 040c2a836..a3210a21c 100644 --- a/modules/st2flow-canvas/index.js +++ b/modules/st2flow-canvas/index.js @@ -229,10 +229,13 @@ export default class Canvas extends Component { dirtyflag: PropTypes.bool, fetchActionscalled: PropTypes.func, saveData: PropTypes.func, + undo: PropTypes.func, + redo: PropTypes.func, } state = { scale: 0, + copiedTask: null, } componentDidMount() { @@ -714,17 +717,60 @@ export default class Canvas extends Component { style={{height: '100%'}} focused={true} attach={document.body} - handlers={{handleTaskDelete: e => { - // This will break if canvas elements (tasks/transitions) become focus targets with - // tabindex or automatically focusing elements. But in that case, the Task already - // has a handler for delete waiting. - if(e.target === document.body) { - e.preventDefault(); - if(selectedTask) { + keyMap={{ + copy: [ 'ctrl+c', 'command+c', 'meta+c' ], + cut: [ 'ctrl+x', 'command+x', 'meta+x' ], + paste: [ 'ctrl+v', 'command+v', 'meta+v' ], + open: [ 'ctrl+o', 'command+o', 'meta+o' ], + undo: [ 'ctrl+z', 'command+z', 'meta+z' ], + redo: [ 'ctrl+shift+z', 'command+shift+z', 'meta+shift+z' ], + }} + handlers={{ + copy: () => { + if (selectedTask) { + this.setState({ copiedTask: selectedTask }); + } + }, + cut: () => { + if (selectedTask) { + this.setState({ copiedTask: selectedTask }); this.handleTaskDelete(selectedTask); } - } - }}} + }, + paste: () => { + const { copiedTask } = this.state; + if (copiedTask) { + const taskHeight = copiedTask.size.y; + const taskCoords = copiedTask.coords; + + const newCoords = { + x: taskCoords.x, + y: taskCoords.y + taskHeight + 10 + }; + + const lastIndex = tasks + .map(task => (task.name.match(/task(\d+)/) || [])[1]) + .reduce((acc, item) => Math.max(acc, item || 0), 0); + + this.props.issueModelCommand('addTask', { + name: `task${lastIndex + 1}`, + action: copiedTask.action, + coords: Vector.max(newCoords, new Vector(0, 0)), + }); + } + }, + open: () => { + if (selectedTask) { + window.open(`${location.origin}/#/action/${selectedTask.action}`, '_blank'); + } + }, + undo: () => { + this.props.undo(); + }, + redo: () => { + this.props.redo(); + }, + }} >
+
{ action.ref }
{ action.description }
-
+ ); } } diff --git a/modules/st2flow-palette/style.css b/modules/st2flow-palette/style.css index c83412b08..7cadbc3de 100644 --- a/modules/st2flow-palette/style.css +++ b/modules/st2flow-palette/style.css @@ -35,6 +35,8 @@ limitations under the License. position: relative; + display: block; + &-name { color: #2d2d2d; font-size: 14px; diff --git a/tasks/lint.js b/tasks/lint.js index 71ff083e4..e8c6aae8b 100644 --- a/tasks/lint.js +++ b/tasks/lint.js @@ -21,7 +21,7 @@ const plugins = require('gulp-load-plugins')(settings.plugins); gulp.task('lint', (done) => gulp.src(settings.lint, { cwd: settings.dev }) .pipe(plugins.plumber()) - .pipe(plugins.eslint()) + .pipe(plugins.eslint({ fix: true })) .pipe(plugins.eslint.format()) .pipe(plugins.eslint.failAfterError()) .on('end', () => done()) From ceef6897bccf5a5663c9659dd1c704af9fd63572 Mon Sep 17 00:00:00 2001 From: Michael Mancini Date: Mon, 7 Mar 2022 18:46:18 -0500 Subject: [PATCH 2/7] lint fix --- apps/st2-workflows/workflows.component.js | 2 +- modules/st2flow-palette/action.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/st2-workflows/workflows.component.js b/apps/st2-workflows/workflows.component.js index fce01333b..7e7ac33f9 100644 --- a/apps/st2-workflows/workflows.component.js +++ b/apps/st2-workflows/workflows.component.js @@ -18,7 +18,7 @@ import React, { Component } from 'react'; import { Provider, connect } from 'react-redux'; import { PropTypes } from 'prop-types'; import { HotKeys } from 'react-hotkeys'; -import { pick, mapValues, get } from 'lodash'; +import { mapValues, get } from 'lodash'; import cx from 'classnames'; import url from 'url'; import Menu from '@stackstorm/module-menu'; diff --git a/modules/st2flow-palette/action.js b/modules/st2flow-palette/action.js index f5f5c75b1..539dadcce 100644 --- a/modules/st2flow-palette/action.js +++ b/modules/st2flow-palette/action.js @@ -67,6 +67,9 @@ export default class Action extends Component<{ render() { const { action } = this.props; + + const href = `${location.origin}/#/action/${action.ref}`; + const supportedRunnerTypes = { 'orquesta': href, 'mistral-v2': href From f7b10933cb84105d19640eb1c7a088c9b6a46832 Mon Sep 17 00:00:00 2001 From: Michael Mancini Date: Tue, 12 Apr 2022 15:52:35 -0400 Subject: [PATCH 3/7] change copy/paste shortcut when inputs & textareas are focused --- apps/st2-workflows/workflows.component.js | 2 +- modules/st2flow-canvas/index.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/st2-workflows/workflows.component.js b/apps/st2-workflows/workflows.component.js index 7e7ac33f9..6e090f18a 100644 --- a/apps/st2-workflows/workflows.component.js +++ b/apps/st2-workflows/workflows.component.js @@ -344,7 +344,7 @@ export default class Workflows extends Component { keyMap={this.keyMap} handlers={this.keyHandlers} > - this.props.fetchActions()} saveData={e => this.save()} dirtyflag={this.props.dirty}> + this.props.fetchActions()} saveData={e => this.save()} dirtyflag={this.props.dirty} undo={this.keyHandlers.undo} redo={this.keyHandlers.redo}> undo()} /> redo()} /> diff --git a/modules/st2flow-canvas/index.js b/modules/st2flow-canvas/index.js index a3210a21c..09d09fe7d 100644 --- a/modules/st2flow-canvas/index.js +++ b/modules/st2flow-canvas/index.js @@ -738,6 +738,11 @@ export default class Canvas extends Component { } }, paste: () => { + if (document.activeElement.tagName === 'TEXTAREA' || document.activeElement.tagName === 'INPUT') { + // allow regular copy/paste from clipboard when inputs or textareas are focused + return; + } + const { copiedTask } = this.state; if (copiedTask) { const taskHeight = copiedTask.size.y; From 7d66d843fb1be4037ec0f156291b82cc630d04a5 Mon Sep 17 00:00:00 2001 From: Michael Mancini Date: Tue, 12 Apr 2022 16:31:32 -0400 Subject: [PATCH 4/7] save toast message --- apps/st2-workflows/workflows.component.js | 13 +++++++++---- modules/st2flow-canvas/index.js | 7 +++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/st2-workflows/workflows.component.js b/apps/st2-workflows/workflows.component.js index 6e090f18a..c418af19c 100644 --- a/apps/st2-workflows/workflows.component.js +++ b/apps/st2-workflows/workflows.component.js @@ -302,9 +302,14 @@ export default class Workflows extends Component { store.dispatch({ type: 'FLOW_REDO' }); }, save: (x) => { - x.preventDefault(); - x.stopPropagation(); - this.save().then(() => null); + if (x) { + x.preventDefault(); + x.stopPropagation(); + } + + this.save() + .then(() => store.dispatch({ type: 'PUSH_SUCCESS', source: 'icon-save', message: 'Workflow saved.' })) + .catch(() => store.dispatch({ type: 'PUSH_SUCCESS', source: 'icon-save', message: 'Error saving workflow.' })); }, copy: () => { store.dispatch({ type: 'PUSH_WARNING', source: 'icon-save', message: 'Select a task to copy' }); @@ -344,7 +349,7 @@ export default class Workflows extends Component { keyMap={this.keyMap} handlers={this.keyHandlers} > - this.props.fetchActions()} saveData={e => this.save()} dirtyflag={this.props.dirty} undo={this.keyHandlers.undo} redo={this.keyHandlers.redo}> + this.props.fetchActions()} save={this.keyHandlers.save} dirtyflag={this.props.dirty} undo={this.keyHandlers.undo} redo={this.keyHandlers.redo}> undo()} /> redo()} /> diff --git a/modules/st2flow-canvas/index.js b/modules/st2flow-canvas/index.js index 09d09fe7d..456756a0b 100644 --- a/modules/st2flow-canvas/index.js +++ b/modules/st2flow-canvas/index.js @@ -231,6 +231,7 @@ export default class Canvas extends Component { saveData: PropTypes.func, undo: PropTypes.func, redo: PropTypes.func, + save: PropTypes.func, } state = { @@ -724,6 +725,7 @@ export default class Canvas extends Component { open: [ 'ctrl+o', 'command+o', 'meta+o' ], undo: [ 'ctrl+z', 'command+z', 'meta+z' ], redo: [ 'ctrl+shift+z', 'command+shift+z', 'meta+shift+z' ], + save: [ 'ctrl+s', 'command+s', 'meta+s' ], }} handlers={{ copy: () => { @@ -775,6 +777,11 @@ export default class Canvas extends Component { redo: () => { this.props.redo(); }, + save: (e) => { + e.preventDefault(); + e.stopPropagation(); + this.props.save(); + } }} >
Date: Thu, 6 Oct 2022 16:32:05 -0400 Subject: [PATCH 5/7] catch saving hotkey error + small fix (cherry picked from commit 58849e86a5455acb648e3f5a16ff5e7a4e3345f9) --- apps/st2-workflows/workflows.component.js | 15 ++++++++++----- modules/st2flow-palette/action.js | 4 ++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/st2-workflows/workflows.component.js b/apps/st2-workflows/workflows.component.js index c418af19c..2030d60e3 100644 --- a/apps/st2-workflows/workflows.component.js +++ b/apps/st2-workflows/workflows.component.js @@ -273,7 +273,7 @@ export default class Workflows extends Component { // don't need to return anything to the store. the handler will change dirty. return {}; })(); - + store.dispatch({ type: 'SAVE_WORKFLOW', promise, @@ -301,15 +301,20 @@ export default class Workflows extends Component { redo: () => { store.dispatch({ type: 'FLOW_REDO' }); }, - save: (x) => { + save: async (x) => { if (x) { x.preventDefault(); x.stopPropagation(); } - this.save() - .then(() => store.dispatch({ type: 'PUSH_SUCCESS', source: 'icon-save', message: 'Workflow saved.' })) - .catch(() => store.dispatch({ type: 'PUSH_SUCCESS', source: 'icon-save', message: 'Error saving workflow.' })); + try { + await this.save(); + store.dispatch({ type: 'PUSH_SUCCESS', source: 'icon-save', message: 'Workflow saved.' }); + } + catch(e) { + const faultString = get(e, 'response.data.faultstring'); + store.dispatch({ type: 'PUSH_ERROR', source: 'icon-save', error: `Error saving workflow: ${faultString}` }); + } }, copy: () => { store.dispatch({ type: 'PUSH_WARNING', source: 'icon-save', message: 'Select a task to copy' }); diff --git a/modules/st2flow-palette/action.js b/modules/st2flow-palette/action.js index 539dadcce..adf759151 100644 --- a/modules/st2flow-palette/action.js +++ b/modules/st2flow-palette/action.js @@ -76,7 +76,7 @@ export default class Action extends Component<{ }; return ( -
{ action.ref }
{ action.description }
-
+
); } } From 3ff07daec5a3dc0e240d509e8a6c96042dfadc98 Mon Sep 17 00:00:00 2001 From: Youssef Date: Fri, 7 Oct 2022 13:56:12 -0400 Subject: [PATCH 6/7] fix hotkey actions running twice (cherry picked from commit b423602d1b69d6937e281ce4e5b0cbc1a86f307a) --- apps/st2-workflows/workflows.component.js | 18 ++---------------- modules/st2flow-canvas/index.js | 18 +++++++++--------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/apps/st2-workflows/workflows.component.js b/apps/st2-workflows/workflows.component.js index 2030d60e3..a847a1b36 100644 --- a/apps/st2-workflows/workflows.component.js +++ b/apps/st2-workflows/workflows.component.js @@ -17,7 +17,6 @@ import React, { Component } from 'react'; // import ReactDOM from 'react-dom'; import { Provider, connect } from 'react-redux'; import { PropTypes } from 'prop-types'; -import { HotKeys } from 'react-hotkeys'; import { mapValues, get } from 'lodash'; import cx from 'classnames'; import url from 'url'; @@ -283,17 +282,6 @@ export default class Workflows extends Component { style = style - keyMap = { - copy: [ 'ctrl+c', 'command+c', 'meta+c' ], - cut: [ 'ctrl+x', 'command+x', 'meta+x' ], - paste: [ 'ctrl+v', 'command+v', 'meta+v' ], - open: [ 'ctrl+o', 'command+o', 'meta+o' ], - undo: [ 'ctrl+z', 'command+z', 'meta+z' ], - redo: [ 'ctrl+shift+z', 'command+shift+z', 'meta+shift+z' ], - save: [ 'ctrl+s', 'command+s', 'meta+s' ], - handleTaskDelete: [ 'del', 'backspace' ], - } - keyHandlers = { undo: () => { store.dispatch({ type: 'FLOW_UNDO' }); @@ -349,10 +337,8 @@ export default class Workflows extends Component {
{ !isCollapsed.palette && } - this.props.fetchActions()} save={this.keyHandlers.save} dirtyflag={this.props.dirty} undo={this.keyHandlers.undo} redo={this.keyHandlers.redo}> @@ -404,7 +390,7 @@ export default class Workflows extends Component { - +
{ !isCollapsed.details &&
} diff --git a/modules/st2flow-canvas/index.js b/modules/st2flow-canvas/index.js index 456756a0b..ee77a8191 100644 --- a/modules/st2flow-canvas/index.js +++ b/modules/st2flow-canvas/index.js @@ -719,13 +719,13 @@ export default class Canvas extends Component { focused={true} attach={document.body} keyMap={{ - copy: [ 'ctrl+c', 'command+c', 'meta+c' ], - cut: [ 'ctrl+x', 'command+x', 'meta+x' ], - paste: [ 'ctrl+v', 'command+v', 'meta+v' ], - open: [ 'ctrl+o', 'command+o', 'meta+o' ], - undo: [ 'ctrl+z', 'command+z', 'meta+z' ], - redo: [ 'ctrl+shift+z', 'command+shift+z', 'meta+shift+z' ], - save: [ 'ctrl+s', 'command+s', 'meta+s' ], + copy: [ 'ctrl+c', 'command+c' ], + cut: [ 'ctrl+x', 'command+x' ], + paste: [ 'ctrl+v', 'command+v' ], + open: [ 'ctrl+o', 'command+o' ], + undo: [ 'ctrl+z', 'command+z' ], + redo: [ 'ctrl+shift+z', 'command+shift+z' ], + save: [ 'ctrl+s', 'command+s' ], }} handlers={{ copy: () => { @@ -752,7 +752,7 @@ export default class Canvas extends Component { const newCoords = { x: taskCoords.x, - y: taskCoords.y + taskHeight + 10 + y: taskCoords.y + taskHeight + 10, }; const lastIndex = tasks @@ -781,7 +781,7 @@ export default class Canvas extends Component { e.preventDefault(); e.stopPropagation(); this.props.save(); - } + }, }} >
Date: Mon, 10 Oct 2022 19:24:12 +0100 Subject: [PATCH 7/7] Add a changelog for the new Hotkey Shortcuts in Workflow Designer --- CHANGELOG.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 635d40ac2..d87a4a95c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -11,6 +11,11 @@ Added Contributed by @ParthS007 +* Added new Hotkey Shortcuts for Workflow Designer: Save (ctrl/cmd + s), Open (ctrl/cmd + o), + Undo/Redo (ctrl/cmd + z, shift + z), Copy/Cut/Paste (ctrl/cmd + c/x/v). #963, #991 + + Contributed by @Jappzy and @cded from @Bitovi + Changed ~~~~~~~ * Updated nodejs from `14.16.1` to `14.20.1`, fixing the local build under ARM processor architecture. #880