composition readonly implementation
Issue-ID: SDC-1591
Change-Id: I4a009fe28fb32d9c2407d69087ab9c17f8ac5b2d
Signed-off-by: Stanislav Vishnevetskiy <shlomo-stanisla.vishnevetskiy@amdocs.com>
diff --git a/workflow-designer-ui/src/main/frontend/package.json b/workflow-designer-ui/src/main/frontend/package.json
index 62b06cb..31d9ed0 100644
--- a/workflow-designer-ui/src/main/frontend/package.json
+++ b/workflow-designer-ui/src/main/frontend/package.json
@@ -26,6 +26,7 @@
"http-proxy-middleware": "^0.17.4",
"inherits": "^2.0.3",
"lodash.assign": "^4.2.0",
+ "lodash.foreach": "^4.5.0",
"lodash.isempty": "^4.4.0",
"lodash.isequal": "^4.5.0",
"lodash.map": "^4.6.0",
diff --git a/workflow-designer-ui/src/main/frontend/resources/scss/features/_composition.scss b/workflow-designer-ui/src/main/frontend/resources/scss/features/_composition.scss
index 6554219..f442177 100644
--- a/workflow-designer-ui/src/main/frontend/resources/scss/features/_composition.scss
+++ b/workflow-designer-ui/src/main/frontend/resources/scss/features/_composition.scss
@@ -55,6 +55,9 @@
fill: $blue;
cursor: pointer;
}
+ &.disabled {
+ fill: $gray;
+ }
.svg-icon {
width: 25px;
height: 23px;
diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js b/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js
index c9fc4b5..b91ceda 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js
@@ -23,6 +23,7 @@
import { activitiesSelector } from 'features/activities/activitiesSelectors';
import { getInputOutputForComposition } from 'features/version/inputOutput/inputOutputSelectors';
import { getVersionInfo } from 'features/version/general/generalSelectors';
+import { getIsCertified } from 'features/version/general/generalSelectors';
function mapStateToProps(state) {
return {
composition: getComposition(state),
@@ -30,7 +31,8 @@
versionName: getVersionInfo(state).name,
activities: activitiesSelector(state),
inputOutput: getInputOutputForComposition(state),
- errors: getErrors(state)
+ errors: getErrors(state),
+ isReadOnly: getIsCertified(state)
};
}
diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/composition/CompositionView.js b/workflow-designer-ui/src/main/frontend/src/features/version/composition/CompositionView.js
index eac3083..3ec0cb2 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/version/composition/CompositionView.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/version/composition/CompositionView.js
@@ -28,9 +28,37 @@
import {
PROCESS_DEFAULT_ID,
COMPOSITION_ERROR_COLOR,
- COMPOSITION_VALID_COLOR
+ COMPOSITION_VALID_COLOR,
+ CAMUNDA_PANEL_INPUTS_NAMES
} from './compositionConstants';
+import readOnly from './readOnly';
+function setStatusToElement(type, status, parent) {
+ let elements = parent.getElementsByTagName(type);
+ for (let item of elements) {
+ if (item.name !== 'selectedExtensionElement') {
+ item.readOnly = status;
+ item.disabled = status;
+ }
+ }
+}
+
+function disablePanelInputs(status) {
+ let panel = document.getElementById('js-properties-panel');
+
+ if (panel) {
+ setStatusToElement('input', status, panel);
+ setStatusToElement('button', status, panel);
+ setStatusToElement('select', status, panel);
+
+ CAMUNDA_PANEL_INPUTS_NAMES.map(name => {
+ const div = document.getElementById(name);
+ if (div) {
+ div.setAttribute('contenteditable', !status);
+ }
+ });
+ }
+}
class CompositionView extends Component {
static propTypes = {
compositionUpdate: PropTypes.func,
@@ -41,7 +69,8 @@
inputOutput: PropTypes.object,
activities: PropTypes.array,
validationUpdate: PropTypes.func,
- errors: PropTypes.array
+ errors: PropTypes.array,
+ isReadOnly: PropTypes.bool
};
constructor() {
@@ -53,9 +82,10 @@
this.state = {
diagram: false
};
+ this.versionChanged = false;
}
componentDidUpdate(prevProps) {
- const { errors } = this.props;
+ const { errors, isReadOnly, versionName, composition } = this.props;
if (!isEqual(prevProps.errors, errors)) {
errors.map(item => {
this.modeling.setColor([item.element], {
@@ -65,22 +95,43 @@
});
});
}
+ if (prevProps.isReadOnly !== isReadOnly) {
+ this.modeler.get('readOnly').readOnly(isReadOnly);
+ disablePanelInputs(isReadOnly);
+ }
+
+ if (prevProps.versionName !== versionName) {
+ this.versionChanged = true;
+ }
+ if (
+ !isEqual(prevProps.composition, composition) &&
+ this.versionChanged
+ ) {
+ this.setDiagramToBPMN(composition);
+ this.versionChanged = false;
+ }
}
componentDidMount() {
const {
composition,
activities,
inputOutput,
- validationUpdate
+ validationUpdate,
+ isReadOnly
} = this.props;
+ const readOnlyModule = {
+ __init__: ['readOnly'],
+ readOnly: ['type', readOnly]
+ };
this.modeler = new CustomModeler({
propertiesPanel: {
parent: '#js-properties-panel'
},
additionalModules: [
propertiesPanelModule,
- propertiesProviderModule
+ propertiesProviderModule,
+ readOnlyModule
],
moddleExtensions: {
camunda: camundaModuleDescriptor
@@ -96,10 +147,14 @@
this.modeler.attachTo('#' + this.generatedId);
this.setDiagramToBPMN(composition ? composition : newDiagramXML);
this.modeler.on('element.out', () => this.exportDiagramToStore());
+ this.modeler.on('element.click', this.handleCompositionStatus);
this.bpmnContainer.current.click();
this.modeling = this.modeler.get('modeling');
+ this.modeler.get('readOnly').readOnly(isReadOnly);
}
-
+ handleCompositionStatus = () => {
+ disablePanelInputs(this.props.isReadOnly);
+ };
getActivityInputsOutputs = selectedValue => {
const selectedActivity = this.props.activities.find(
el => el.name === selectedValue
@@ -132,6 +187,7 @@
this.props.inputOutput,
this.modeler.get('moddle')
);
+ disablePanelInputs(this.props.isReadOnly);
});
};
setDefaultIdAndName = businessObject => {
@@ -213,6 +269,7 @@
id="js-properties-panel"
/>
<CompositionButtons
+ isReadOnly={this.props.isReadOnly}
onClean={this.loadNewDiagram}
onDownload={this.exportDiagram}
onUpload={this.uploadDiagram}
diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButton.js b/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButton.js
index 2fc6618..433e055 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButton.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButton.js
@@ -17,8 +17,10 @@
import PropTypes from 'prop-types';
import SVGIcon from 'sdc-ui/lib/react/SVGIcon';
-const CompositionButton = ({ onClick, name, title }) => (
- <div onClick={onClick} className="diagram-btn">
+const CompositionButton = ({ onClick, name, title, disabled }) => (
+ <div
+ onClick={disabled ? () => {} : onClick}
+ className={`diagram-btn ${disabled ? 'disabled' : ''}`}>
<SVGIcon title={title} name={name} />
</div>
);
@@ -27,7 +29,8 @@
onClick: PropTypes.func,
className: PropTypes.string,
name: PropTypes.string,
- title: PropTypes.string
+ title: PropTypes.string,
+ disabled: PropTypes.bool
};
export default CompositionButton;
diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButtonsPanel.js b/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButtonsPanel.js
index add6490..0292fd4 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButtonsPanel.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/version/composition/components/CompositionButtonsPanel.js
@@ -19,14 +19,16 @@
const Divider = () => <div className="divider" />;
-const CompositionButtons = ({ onClean, onUpload, onDownload }) => (
+const CompositionButtons = ({ onClean, onUpload, onDownload, isReadOnly }) => (
<div className="composition-buttons">
<CompositionButton
+ disabled={isReadOnly}
data-test-id="composition-clear-btn"
onClick={onClean}
name="trashO"
title="clear"
/>
+
<Divider />
<CompositionButton
data-test-id="composition-download-btn"
@@ -36,6 +38,7 @@
/>
<Divider />
<CompositionButton
+ disabled={isReadOnly}
data-test-id="composition-download-upload"
onClick={onUpload}
name="upload"
@@ -47,6 +50,7 @@
CompositionButtons.propTypes = {
onClean: PropTypes.func,
onUpload: PropTypes.func,
- onDownload: PropTypes.func
+ onDownload: PropTypes.func,
+ isReadOnly: PropTypes.bool
};
export default CompositionButtons;
diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/composition/compositionConstants.js b/workflow-designer-ui/src/main/frontend/src/features/version/composition/compositionConstants.js
index 79c7e8e..7aaa656 100644
--- a/workflow-designer-ui/src/main/frontend/src/features/version/composition/compositionConstants.js
+++ b/workflow-designer-ui/src/main/frontend/src/features/version/composition/compositionConstants.js
@@ -27,3 +27,9 @@
export const COMPOSITION_ERROR_COLOR = '#f0c2c2';
export const COMPOSITION_VALID_COLOR = 'white';
+
+export const CAMUNDA_PANEL_INPUTS_NAMES = [
+ 'camunda-parameterType-text',
+ 'camunda-documentation',
+ 'camunda-name'
+];
diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/composition/readOnly.js b/workflow-designer-ui/src/main/frontend/src/features/version/composition/readOnly.js
new file mode 100644
index 0000000..828244b
--- /dev/null
+++ b/workflow-designer-ui/src/main/frontend/src/features/version/composition/readOnly.js
@@ -0,0 +1,138 @@
+import forEach from 'lodash.foreach';
+
+const HIGH_PRIORITY = 10001;
+
+function ReadOnly(
+ eventBus,
+ contextPad,
+ dragging,
+ directEditing,
+ editorActions,
+ modeling,
+ palette,
+ paletteProvider
+) {
+ this._readOnly = false;
+ this._eventBus = eventBus;
+
+ let self = this;
+ eventBus.on('readOnly.changed', HIGH_PRIORITY, function(e) {
+ self._readOnly = e.readOnly;
+
+ if (e.readOnly) {
+ directEditing.cancel();
+ contextPad.close();
+ dragging.cancel();
+ }
+
+ palette._update();
+ });
+
+ function intercept(obj, fnName, cb) {
+ var fn = obj[fnName];
+ obj[fnName] = function() {
+ return cb.call(this, fn, arguments);
+ };
+ }
+
+ function ignoreWhenReadOnly(obj, fnName) {
+ intercept(obj, fnName, function(fn, args) {
+ if (self._readOnly) {
+ return;
+ }
+
+ return fn.apply(this, args);
+ });
+ }
+
+ function throwIfReadOnly(obj, fnName) {
+ intercept(obj, fnName, function(fn, args) {
+ if (self._readOnly) {
+ throw new Error('model is read-only');
+ }
+
+ return fn.apply(this, args);
+ });
+ }
+
+ ignoreWhenReadOnly(contextPad, 'open');
+
+ ignoreWhenReadOnly(dragging, 'init');
+
+ ignoreWhenReadOnly(directEditing, 'activate');
+
+ ignoreWhenReadOnly(editorActions._actions, 'undo');
+ ignoreWhenReadOnly(editorActions._actions, 'redo');
+ ignoreWhenReadOnly(editorActions._actions, 'copy');
+ ignoreWhenReadOnly(editorActions._actions, 'paste');
+ ignoreWhenReadOnly(editorActions._actions, 'removeSelection');
+ // BpmnEditorActions
+ ignoreWhenReadOnly(editorActions._actions, 'spaceTool');
+ ignoreWhenReadOnly(editorActions._actions, 'lassoTool');
+ ignoreWhenReadOnly(editorActions._actions, 'globalConnectTool');
+ ignoreWhenReadOnly(editorActions._actions, 'distributeElements');
+ ignoreWhenReadOnly(editorActions._actions, 'alignElements');
+ ignoreWhenReadOnly(editorActions._actions, 'directEditing');
+
+ throwIfReadOnly(modeling, 'moveShape');
+ throwIfReadOnly(modeling, 'updateAttachment');
+ throwIfReadOnly(modeling, 'moveElements');
+ throwIfReadOnly(modeling, 'moveConnection');
+ throwIfReadOnly(modeling, 'layoutConnection');
+ throwIfReadOnly(modeling, 'createConnection');
+ throwIfReadOnly(modeling, 'createShape');
+ throwIfReadOnly(modeling, 'createLabel');
+ throwIfReadOnly(modeling, 'appendShape');
+ throwIfReadOnly(modeling, 'removeElements');
+ throwIfReadOnly(modeling, 'distributeElements');
+ throwIfReadOnly(modeling, 'removeShape');
+ throwIfReadOnly(modeling, 'removeConnection');
+ throwIfReadOnly(modeling, 'replaceShape');
+ throwIfReadOnly(modeling, 'pasteElements');
+ throwIfReadOnly(modeling, 'alignElements');
+ throwIfReadOnly(modeling, 'resizeShape');
+ throwIfReadOnly(modeling, 'createSpace');
+ throwIfReadOnly(modeling, 'updateWaypoints');
+ throwIfReadOnly(modeling, 'reconnectStart');
+ throwIfReadOnly(modeling, 'reconnectEnd');
+
+ intercept(paletteProvider, 'getPaletteEntries', function(fn, args) {
+ var entries = fn.apply(this, args);
+ if (self._readOnly) {
+ let allowedEntries = ['hand-tool'];
+
+ forEach(entries, function(value, key) {
+ if (allowedEntries.indexOf(key) === -1) {
+ delete entries[key];
+ }
+ });
+ }
+ return entries;
+ });
+}
+
+ReadOnly.$inject = [
+ 'eventBus',
+ 'contextPad',
+ 'dragging',
+ 'directEditing',
+ 'editorActions',
+ 'modeling',
+ 'palette',
+ 'paletteProvider'
+];
+
+module.exports = ReadOnly;
+
+ReadOnly.prototype.readOnly = function(readOnly) {
+ var newValue = !!readOnly,
+ oldValue = !!this._readOnly;
+
+ if (readOnly === undefined || newValue === oldValue) {
+ return oldValue;
+ }
+
+ this._readOnly = newValue;
+ this._eventBus.fire('readOnly.changed', { readOnly: newValue });
+ return newValue;
+};
diff --git a/workflow-designer-ui/src/main/frontend/yarn.lock b/workflow-designer-ui/src/main/frontend/yarn.lock
index 4235c3d..c428758 100644
--- a/workflow-designer-ui/src/main/frontend/yarn.lock
+++ b/workflow-designer-ui/src/main/frontend/yarn.lock
@@ -7020,6 +7020,10 @@
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
+lodash.foreach@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53"
+
lodash.isarguments@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"