Skip to content

Commit

Permalink
feat(examples): add element templates example
Browse files Browse the repository at this point in the history
Closes #166
  • Loading branch information
smbea committed Oct 14, 2022
1 parent 2718340 commit be48d9f
Show file tree
Hide file tree
Showing 10 changed files with 541 additions and 2 deletions.
3 changes: 3 additions & 0 deletions element-templates/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
public/
tmp/
57 changes: 57 additions & 0 deletions element-templates/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# bpmn-js Modeler + element templates Example


## About
<!-- Points:
* Explain: currently no custom element templates provider, need to use C7/C8 providers
* Explain:
- ElementTemplatesLoader handles loading of templates.
- There is no template chooser UI built in the properties panel. This needs to be added on top: see example [@bpmn-io/element-template-chooser](https://github.com/bpmn-io/element-template-chooser)
* Compare to custom elements, when to use what
* Link to element template documentation
-->


```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).
54 changes: 54 additions & 0 deletions element-templates/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
178 changes: 178 additions & 0 deletions element-templates/src/app.js
Original file line number Diff line number Diff line change
@@ -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)
})
Loading

0 comments on commit be48d9f

Please sign in to comment.