From be48d9f7161d0664fa175e09975473c720611a83 Mon Sep 17 00:00:00 2001 From: Beatriz Mendes Date: Thu, 13 Oct 2022 21:25:15 +0200 Subject: [PATCH] feat(examples): add element templates example Closes #166 --- element-templates/.gitignore | 3 + element-templates/README.md | 57 +++++++++ element-templates/package.json | 54 ++++++++ element-templates/src/app.js | 178 ++++++++++++++++++++++++++ element-templates/src/app.less | 127 ++++++++++++++++++ element-templates/src/index.html | 57 +++++++++ element-templates/src/newDiagram.bpmn | 27 ++++ element-templates/webpack.config.js | 36 ++++++ properties-panel/src/index.html | 2 +- properties-panel/webpack.config.js | 2 +- 10 files changed, 541 insertions(+), 2 deletions(-) create mode 100644 element-templates/.gitignore create mode 100644 element-templates/README.md create mode 100644 element-templates/package.json create mode 100644 element-templates/src/app.js create mode 100644 element-templates/src/app.less create mode 100644 element-templates/src/index.html create mode 100644 element-templates/src/newDiagram.bpmn create mode 100644 element-templates/webpack.config.js diff --git a/element-templates/.gitignore b/element-templates/.gitignore new file mode 100644 index 00000000..f3766233 --- /dev/null +++ b/element-templates/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +public/ +tmp/ \ No newline at end of file diff --git a/element-templates/README.md b/element-templates/README.md new file mode 100644 index 00000000..1e6052b7 --- /dev/null +++ b/element-templates/README.md @@ -0,0 +1,57 @@ +# bpmn-js Modeler + element templates Example + + +## About + + + +```javascript +import { + BpmnPropertiesPanelModule, + BpmnPropertiesProviderModule, + ElementTemplatesPropertiesProviderModule +} from 'bpmn-js-properties-panel' + + +var bpmnModeler = new BpmnModeler({ + container: canvas, + propertiesPanel: { + parent: '#js-properties-panel' + }, + additionalModules: [ + BpmnPropertiesPanelModule, + BpmnPropertiesProviderModule, + ElementTemplatesPropertiesProviderModule, + ] +}) + +bpmnModeler.get('elementTemplatesLoader').setTemplates(templates) + +``` + +## Building the Example + +You need a [NodeJS](http://nodejs.org) development stack with [npm](https://npmjs.org) and installed to build the project. + +To install all project dependencies execute + +``` +npm install +``` + +Build the example using [webpack](https://webpack.js.org/) via + +``` +npm run all +``` + +Both tasks generate the distribution ready client-side modeler application into the `public` folder. + +Serve the application locally or via a web server (nginx, apache, embedded). diff --git a/element-templates/package.json b/element-templates/package.json new file mode 100644 index 00000000..609a8782 --- /dev/null +++ b/element-templates/package.json @@ -0,0 +1,54 @@ +{ + "name": "bpmn-js-example-element-templates", + "version": "0.0.0", + "description": "A bpmn-js modeler + element templates example", + "main": "app/index.js", + "scripts": { + "all": "run-s bundle", + "dev": "run-s bundle:less watch:js", + "start": "run-s bundle serve", + "serve": "sirv public --port=5002 --watch --dev", + "bundle": "run-s bundle:*", + "bundle:less": "lessc src/app.less public/app.css", + "bundle:js": "webpack -c webpack.config.js", + "watch:js": "run-s \"bundle:js -- --watch\"" + }, + "repository": { + "type": "git", + "url": "https://github.com/bpmn-io/bpmn-js-examples", + "directory": "element-templates" + }, + "author": { + "name": "Beatriz Mendes", + "url": "https://github.com/smbea" + }, + "keywords": [ + "bpmnjs-example", + "element-templates" + ], + "contributors": [ + { + "name": "bpmn.io contributors", + "url": "https://github.com/bpmn-io" + } + ], + "license": "MIT", + "dependencies": { + "@bpmn-io/element-template-chooser": "^0.1.0", + "@bpmn-io/properties-panel": "^0.11.0", + "bpmn-js": "^9.0.3", + "bpmn-js-properties-panel": "^1.0.0-alpha.5", + "css-loader": "^6.7.1", + "jquery": "^3.5.1", + "min-dash": "^3.7.0" + }, + "devDependencies": { + "copy-webpack-plugin": "^7.0.0", + "less": "^4.1.0", + "npm-run-all": "^4.1.5", + "raw-loader": "^4.0.2", + "sirv-cli": "^1.0.10", + "webpack": "^5.16.0", + "webpack-cli": "^4.4.0" + } +} diff --git a/element-templates/src/app.js b/element-templates/src/app.js new file mode 100644 index 00000000..62c62dc3 --- /dev/null +++ b/element-templates/src/app.js @@ -0,0 +1,178 @@ +import $ from 'jquery' +import BpmnModeler from 'bpmn-js/lib/Modeler' + +import { debounce } from 'min-dash' + +import { + BpmnPropertiesPanelModule, + BpmnPropertiesProviderModule, + ElementTemplatesPropertiesProviderModule +} from 'bpmn-js-properties-panel' + +import diagramXML from './newDiagram.bpmn' +import ElementTemplateChooserModule from '@bpmn-io/element-template-chooser' + +var container = $('#js-drop-zone') + +var canvas = $('#js-canvas') + +var templates = [ + { + id: 'template1', + name: 'Template 1', + appliesTo: ['bpmn:Task'], + properties: [ + { + binding: { + name: 'name', + type: 'property' + }, + label: 'Template Name', + type: 'Hidden', + value: 'template-name' + } + ] + } +] + +var bpmnModeler = new BpmnModeler({ + container: canvas, + propertiesPanel: { + parent: '#js-properties-panel' + }, + additionalModules: [ + BpmnPropertiesPanelModule, + BpmnPropertiesProviderModule, + ElementTemplatesPropertiesProviderModule, + ElementTemplateChooserModule // example of a template chooser, can be replaced by custom implementation + ] +}) +container.removeClass('with-diagram') + +function createNewDiagram () { + openDiagram(diagramXML) +} + +async function openDiagram (xml) { + try { + await bpmnModeler.importXML(xml) + + container.removeClass('with-error').addClass('with-diagram') + + bpmnModeler.on('elementTemplates.errors', event => { + const { errors } = event + + showTemplateErrors(errors) + }) + + bpmnModeler.get('elementTemplatesLoader').setTemplates(templates) + + } catch (err) { + container.removeClass('with-diagram').addClass('with-error') + + container.find('.error pre').text(err.message) + + console.error(err) + } +} + +function registerFileDrop (container, callback) { + function handleFileSelect (e) { + e.stopPropagation() + e.preventDefault() + + var files = e.dataTransfer.files + + var file = files[0] + + var reader = new FileReader() + + reader.onload = function (e) { + var xml = e.target.result + + callback(xml) + } + + reader.readAsText(file) + } + + function handleDragOver (e) { + e.stopPropagation() + e.preventDefault() + + e.dataTransfer.dropEffect = 'copy' // Explicitly show this is a copy. + } + + container.get(0).addEventListener('dragover', handleDragOver, false) + container.get(0).addEventListener('drop', handleFileSelect, false) +} + +////// file drag / drop /////////////////////// + +// check file api availability +if (!window.FileList || !window.FileReader) { + window.alert( + 'Looks like you use an older browser that does not support drag and drop. ' + + 'Try using Chrome, Firefox or the Internet Explorer > 10.' + ) +} else { + registerFileDrop(container, openDiagram) +} + +// bootstrap diagram functions + +$(function () { + $('#js-create-diagram').click(function (e) { + e.stopPropagation() + e.preventDefault() + + createNewDiagram() + }) + + var downloadLink = $('#js-download-diagram') + var downloadSvgLink = $('#js-download-svg') + + $('.buttons a').click(function (e) { + if (!$(this).is('.active')) { + e.preventDefault() + e.stopPropagation() + } + }) + + function setEncoded (link, name, data) { + var encodedData = encodeURIComponent(data) + + if (data) { + link.addClass('active').attr({ + href: 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData, + download: name + }) + } else { + link.removeClass('active') + } + } + + var exportArtifacts = debounce(async function () { + try { + const { svg } = await bpmnModeler.saveSVG() + + setEncoded(downloadSvgLink, 'diagram.svg', svg) + } catch (err) { + console.error('Error happened saving SVG: ', err) + + setEncoded(downloadSvgLink, 'diagram.svg', null) + } + + try { + const { xml } = await bpmnModeler.saveXML({ format: true }) + + setEncoded(downloadLink, 'diagram.bpmn', xml) + } catch (err) { + console.log('Error happened saving XML: ', err) + + setEncoded(downloadLink, 'diagram.bpmn', null) + } + }, 500) + + bpmnModeler.on('commandStack.changed', exportArtifacts) +}) diff --git a/element-templates/src/app.less b/element-templates/src/app.less new file mode 100644 index 00000000..51f48719 --- /dev/null +++ b/element-templates/src/app.less @@ -0,0 +1,127 @@ +* { + box-sizing: border-box; +} + +body, +html { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + + font-size: 12px; + + height: 100%; + max-height: 100%; + padding: 0; + margin: 0; +} + +#js-properties-panel { + width: 400px; +} + +a:link { + text-decoration: none; +} + +.content { + position: relative; + width: 100%; + height: 100%; + display: flex; + + > .message { + width: 100%; + height: 100%; + text-align: center; + display: table; + + font-size: 16px; + color: #111; + + .note { + vertical-align: middle; + text-align: center; + display: table-cell; + } + + &.error { + .details { + max-width: 500px; + font-size: 12px; + margin: 20px auto; + text-align: left; + color: #BD2828; + } + + pre { + border: solid 1px #BD2828; + background: #fefafa; + padding: 10px; + color: #BD2828; + } + } + } + &:not(.with-error) .error, + &.with-error .intro, + &.with-diagram .intro { + display: none; + } + + .canvas { + width: 100%; + } + + .canvas, + .properties-panel-parent { + display: none; + } + + &.with-diagram { + .canvas, + .properties-panel-parent { + display: block; + } + } +} + + +.buttons { + position: fixed; + bottom: 20px; + left: 20px; + + padding: 0; + margin: 0; + list-style: none; + + > li { + display: inline-block; + margin-right: 10px; + + > a { + background: #DDD; + border: solid 1px #666; + display: inline-block; + padding: 5px; + } + } + + a { + opacity: 0.3; + } + + a.active { + opacity: 1.0; + } +} + +.properties-panel-parent { + border-left: 1px solid #ccc; + overflow: auto; + &:empty { + display: none; + } + > .djs-properties-panel { + padding-bottom: 70px; + min-height:100%; + } +} diff --git a/element-templates/src/index.html b/element-templates/src/index.html new file mode 100644 index 00000000..2638946f --- /dev/null +++ b/element-templates/src/index.html @@ -0,0 +1,57 @@ + + + + + bpmn-js properties panel demo + + + + + + + + + + + +
+ +
+
+ Drop BPMN diagram from your desktop or create a new diagram to get started. +
+
+ +
+
+

Ooops, we could not display the BPMN 2.0 diagram.

+ +
+ Import Error Details +

+        
+
+
+ +
+
+
+ + + + + diff --git a/element-templates/src/newDiagram.bpmn b/element-templates/src/newDiagram.bpmn new file mode 100644 index 00000000..4e15f449 --- /dev/null +++ b/element-templates/src/newDiagram.bpmn @@ -0,0 +1,27 @@ + + + + + + Flow_140gw4k + + + + Flow_140gw4k + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/element-templates/webpack.config.js b/element-templates/webpack.config.js new file mode 100644 index 00000000..23787df9 --- /dev/null +++ b/element-templates/webpack.config.js @@ -0,0 +1,36 @@ +var CopyPlugin = require('copy-webpack-plugin'); + +var path = require('path'); + +module.exports = { + mode: 'development', + entry: './src/app.js', + output: { + path: path.resolve(__dirname, 'public'), + filename: 'app.js' + }, + module: { + rules: [ + { + test: /\.bpmn$/, + use: { + loader: 'raw-loader' + } + }, + { + test: /\.css$/, + use: ["css-loader"] + } + ] + }, + plugins: [ + new CopyPlugin({ + patterns: [ + { from: 'src/index.html', to: '.' }, + { from: 'node_modules/bpmn-js/dist/assets', to: 'vendor/bpmn-js/assets' }, + { from: 'node_modules/bpmn-js-properties-panel/dist/assets', to: 'vendor/bpmn-js-properties-panel/assets' }, + { from: 'node_modules/@bpmn-io/element-template-chooser/dist', to: 'vendor/@bpmn-io/element-template-chooser/assets' } + ] + }) + ] +}; \ No newline at end of file diff --git a/properties-panel/src/index.html b/properties-panel/src/index.html index 5f3ce110..680b9bb4 100644 --- a/properties-panel/src/index.html +++ b/properties-panel/src/index.html @@ -8,7 +8,7 @@ - + diff --git a/properties-panel/webpack.config.js b/properties-panel/webpack.config.js index bd71ef39..4bd8e769 100644 --- a/properties-panel/webpack.config.js +++ b/properties-panel/webpack.config.js @@ -24,7 +24,7 @@ module.exports = { patterns: [ { from: 'src/index.html', to: '.' }, { from: 'node_modules/bpmn-js/dist/assets', to: 'vendor/bpmn-js/assets' }, - { from: 'node_modules/bpmn-js-properties-panel/dist/assets', to: 'vendor/bpmn-js-properties-panel/assets' }, + { from: 'node_modules/bpmn-js-properties-panel/dist/assets', to: 'vendor/bpmn-js-properties-panel/assets' } ] }) ]