Merge branch 'main' of github.com:sartography/spiff-arena
This commit is contained in:
commit
1702521ccb
|
@ -1,23 +1,16 @@
|
|||
version: "3.8"
|
||||
services:
|
||||
spiffworkflow-db:
|
||||
container_name: spiffworkflow-db
|
||||
image: mysql:8.0.29
|
||||
platform: linux/amd64
|
||||
cap_add:
|
||||
- SYS_NICE
|
||||
restart: "no"
|
||||
spiffworkflow-frontend:
|
||||
container_name: spiffworkflow-frontend
|
||||
image: ghcr.io/sartography/spiffworkflow-frontend:latest
|
||||
depends_on:
|
||||
spiffworkflow-backend:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- MYSQL_DATABASE=spiffworkflow_backend_development
|
||||
- MYSQL_ROOT_PASSWORD=my-secret-pw
|
||||
- MYSQL_TCP_PORT=8003
|
||||
APPLICATION_ROOT: "/"
|
||||
PORT0: "${SPIFF_FRONTEND_PORT:-8001}"
|
||||
ports:
|
||||
- "8003"
|
||||
healthcheck:
|
||||
test: mysql --user=root --password=my-secret-pw -e 'select 1' spiffworkflow_backend_development
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
- "${SPIFF_FRONTEND_PORT:-8001}:${SPIFF_FRONTEND_PORT:-8001}/tcp"
|
||||
|
||||
spiffworkflow-backend:
|
||||
container_name: spiffworkflow-backend
|
||||
|
@ -26,58 +19,69 @@ services:
|
|||
spiffworkflow-db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- APPLICATION_ROOT=/
|
||||
- SPIFFWORKFLOW_BACKEND_ENV=development
|
||||
- FLASK_DEBUG=0
|
||||
- FLASK_SESSION_SECRET_KEY=super_secret_key
|
||||
- OPEN_ID_SERVER_URL=http://localhost:8000/openid
|
||||
- SPIFFWORKFLOW_FRONTEND_URL=http://localhost:8001
|
||||
- SPIFFWORKFLOW_BACKEND_URL=http://localhost:8000
|
||||
- SPIFFWORKFLOW_BACKEND_PORT=8000
|
||||
- SPIFFWORKFLOW_BACKEND_UPGRADE_DB=true
|
||||
- SPIFFWORKFLOW_BACKEND_DATABASE_URI=mysql+mysqlconnector://root:my-secret-pw@spiffworkflow-db:8003/spiffworkflow_backend_development
|
||||
- BPMN_SPEC_ABSOLUTE_DIR=/app/process_models
|
||||
- SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA=false
|
||||
- SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME=example.yml
|
||||
- RUN_BACKGROUND_SCHEDULER=true
|
||||
- OPEN_ID_CLIENT_ID=spiffworkflow-backend
|
||||
- OPEN_ID_CLIENT_SECRET_KEY=my_open_id_secret_key
|
||||
APPLICATION_ROOT: "/"
|
||||
SPIFFWORKFLOW_BACKEND_ENV: "development"
|
||||
FLASK_DEBUG: "0"
|
||||
FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}"
|
||||
OPEN_ID_SERVER_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}/openid"
|
||||
SPIFFWORKFLOW_FRONTEND_URL: "http://localhost:${SPIFF_FRONTEND_PORT:-8001}"
|
||||
# WARNING: Frontend is a static site which assumes frontend port - 1 on localhost.
|
||||
SPIFFWORKFLOW_BACKEND_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}"
|
||||
SPIFFWORKFLOW_BACKEND_PORT: "${SPIFF_BACKEND_PORT:-8000}"
|
||||
SPIFFWORKFLOW_BACKEND_UPGRADE_DB: "true"
|
||||
SPIFFWORKFLOW_BACKEND_DATABASE_URI: "mysql+mysqlconnector://root:${SPIFF_MYSQL_PASS:-my-secret-pw}@spiffworkflow-db:${SPIFF_MYSQL_PORT:-8003}/spiffworkflow_backend_development"
|
||||
BPMN_SPEC_ABSOLUTE_DIR: "/app/process_models"
|
||||
SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA: "false"
|
||||
SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME: "example.yml"
|
||||
RUN_BACKGROUND_SCHEDULER: "true"
|
||||
OPEN_ID_CLIENT_ID: "spiffworkflow-backend"
|
||||
OPEN_ID_CLIENT_SECRET_KEY: "my_open_id_secret_key"
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "${SPIFF_BACKEND_PORT:-8000}:${SPIFF_BACKEND_PORT:-8000}/tcp"
|
||||
volumes:
|
||||
- ./process_models:/app/process_models
|
||||
- ./log:/app/log
|
||||
healthcheck:
|
||||
test: curl localhost:8000/v1.0/status --fail
|
||||
test: "curl localhost:${SPIFF_BACKEND_PORT:-8000}/v1.0/status --fail"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
|
||||
spiffworkflow-frontend:
|
||||
container_name: spiffworkflow-frontend
|
||||
image: ghcr.io/sartography/spiffworkflow-frontend
|
||||
environment:
|
||||
- APPLICATION_ROOT=/
|
||||
- PORT0=8001
|
||||
ports:
|
||||
- "8001:8001"
|
||||
|
||||
spiffworkflow-connector:
|
||||
container_name: spiffworkflow-connector
|
||||
image: ghcr.io/sartography/connector-proxy-demo
|
||||
image: ghcr.io/sartography/connector-proxy-demo:latest
|
||||
environment:
|
||||
- FLASK_ENV=${FLASK_ENV:-development}
|
||||
- FLASK_DEBUG=0
|
||||
- FLASK_SESSION_SECRET_KEY=${FLASK_SESSION_SECRET_KEY:-super_secret_key}
|
||||
- CONNECTOR_PROXY_PORT=8004
|
||||
FLASK_ENV: "${FLASK_ENV:-development}"
|
||||
FLASK_DEBUG: "0"
|
||||
FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}"
|
||||
CONNECTOR_PROXY_PORT: "${SPIFF_CONNECTOR_PORT:-8004}"
|
||||
ports:
|
||||
- "8004:8004"
|
||||
- "${SPIFF_CONNECTOR_PORT:-8004}:${SPIFF_CONNECTOR_PORT:-8004}/tcp"
|
||||
healthcheck:
|
||||
test: curl localhost:8004/liveness --fail
|
||||
test: "curl localhost:${SPIFF_CONNECTOR_PORT:-8004}/liveness --fail"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
|
||||
spiffworkflow-db:
|
||||
container_name: spiffworkflow-db
|
||||
image: mysql:8.0.29
|
||||
platform: linux/amd64
|
||||
cap_add:
|
||||
- SYS_NICE
|
||||
restart: "no"
|
||||
environment:
|
||||
MYSQL_DATABASE: "spiffworkflow_backend_development"
|
||||
MYSQL_ROOT_PASSWORD: "${SPIFF_MYSQL_PASS:-my-secret-pw}"
|
||||
MYSQL_TCP_PORT: "${SPIFF_MYSQL_PORT:-8003}"
|
||||
ports:
|
||||
- "${SPIFF_MYSQL_PORT:-8003}:${SPIFF_MYSQL_PORT:-8003}/tcp"
|
||||
healthcheck:
|
||||
test: "mysql --user=root --password=${SPIFF_MYSQL_PASS:-my-secret-pw} -e 'select 1' spiffworkflow_backend_development"
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
|
||||
volumes:
|
||||
spiffworkflow_backend:
|
||||
|
|
|
@ -19,7 +19,6 @@ from spiffworkflow_backend.exceptions.api_error import api_error_blueprint
|
|||
from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX
|
||||
from spiffworkflow_backend.models.db import db
|
||||
from spiffworkflow_backend.models.db import migrate
|
||||
from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint
|
||||
from spiffworkflow_backend.routes.openid_blueprint.openid_blueprint import (
|
||||
openid_blueprint,
|
||||
)
|
||||
|
@ -106,7 +105,6 @@ def create_app() -> flask.app.Flask:
|
|||
|
||||
app.register_blueprint(user_blueprint)
|
||||
app.register_blueprint(api_error_blueprint)
|
||||
app.register_blueprint(admin_blueprint, url_prefix="/admin")
|
||||
app.register_blueprint(openid_blueprint, url_prefix="/openid")
|
||||
|
||||
# preflight options requests will be allowed if they meet the requirements of the url regex.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
"""__init__."""
|
|
@ -1,187 +0,0 @@
|
|||
"""APIs for dealing with process groups, process models, and process instances."""
|
||||
from typing import Union
|
||||
|
||||
from flask import Blueprint
|
||||
from flask import flash
|
||||
from flask import redirect
|
||||
from flask import render_template
|
||||
from flask import request
|
||||
from flask import url_for
|
||||
from werkzeug.wrappers import Response
|
||||
|
||||
from spiffworkflow_backend.services.process_instance_processor import (
|
||||
ProcessInstanceProcessor,
|
||||
)
|
||||
from spiffworkflow_backend.services.process_instance_service import (
|
||||
ProcessInstanceService,
|
||||
)
|
||||
from spiffworkflow_backend.services.process_model_service import ProcessModelService
|
||||
from spiffworkflow_backend.services.spec_file_service import SpecFileService
|
||||
from spiffworkflow_backend.services.user_service import UserService
|
||||
|
||||
admin_blueprint = Blueprint(
|
||||
"admin", __name__, template_folder="templates", static_folder="static"
|
||||
)
|
||||
|
||||
ALLOWED_BPMN_EXTENSIONS = {"bpmn", "dmn"}
|
||||
|
||||
|
||||
@admin_blueprint.route("/process-groups", methods=["GET"])
|
||||
def process_group_list() -> str:
|
||||
"""Process_group_list."""
|
||||
process_groups = ProcessModelService.get_process_groups()
|
||||
return render_template("process_group_list.html", process_groups=process_groups)
|
||||
|
||||
|
||||
@admin_blueprint.route("/process-groups/<process_group_id>", methods=["GET"])
|
||||
def process_group_show(process_group_id: str) -> str:
|
||||
"""Show_process_group."""
|
||||
process_group = ProcessModelService.get_process_group(process_group_id)
|
||||
return render_template("process_group_show.html", process_group=process_group)
|
||||
|
||||
|
||||
@admin_blueprint.route("/process-models/<process_model_id>", methods=["GET"])
|
||||
def process_model_show(process_model_id: str) -> Union[str, Response]:
|
||||
"""Show_process_model."""
|
||||
process_model = ProcessModelService.get_process_model(process_model_id)
|
||||
files = SpecFileService.get_files(process_model, extension_filter="bpmn")
|
||||
current_file_name = process_model.primary_file_name
|
||||
if current_file_name is None:
|
||||
flash("No primary_file_name", "error")
|
||||
return redirect(url_for("admin.process_group_list"))
|
||||
bpmn_xml = SpecFileService.get_data(process_model, current_file_name)
|
||||
return render_template(
|
||||
"process_model_show.html",
|
||||
process_model=process_model,
|
||||
bpmn_xml=bpmn_xml,
|
||||
files=files,
|
||||
current_file_name=current_file_name,
|
||||
)
|
||||
|
||||
|
||||
@admin_blueprint.route(
|
||||
"/process-models/<process_model_id>/<file_name>", methods=["GET"]
|
||||
)
|
||||
def process_model_show_file(process_model_id: str, file_name: str) -> str:
|
||||
"""Process_model_show_file."""
|
||||
process_model = ProcessModelService.get_process_model(process_model_id)
|
||||
bpmn_xml = SpecFileService.get_data(process_model, file_name)
|
||||
files = SpecFileService.get_files(process_model, extension_filter="bpmn")
|
||||
return render_template(
|
||||
"process_model_show.html",
|
||||
process_model=process_model,
|
||||
bpmn_xml=bpmn_xml,
|
||||
files=files,
|
||||
current_file_name=file_name,
|
||||
)
|
||||
|
||||
|
||||
@admin_blueprint.route(
|
||||
"/process-models/<process_model_id>/upload-file", methods=["POST"]
|
||||
)
|
||||
def process_model_upload_file(process_model_id: str) -> Response:
|
||||
"""Process_model_upload_file."""
|
||||
process_model = ProcessModelService.get_process_model(process_model_id)
|
||||
|
||||
if "file" not in request.files:
|
||||
flash("No file part", "error")
|
||||
request_file = request.files["file"]
|
||||
# If the user does not select a file, the browser submits an
|
||||
# empty file without a filename.
|
||||
if request_file.filename == "" or request_file.filename is None:
|
||||
flash("No selected file", "error")
|
||||
else:
|
||||
if request_file and _allowed_file(request_file.filename):
|
||||
if request_file.filename is not None:
|
||||
SpecFileService.add_file(
|
||||
process_model, request_file.filename, request_file.stream.read()
|
||||
)
|
||||
ProcessModelService.save_process_model(process_model)
|
||||
|
||||
return redirect(
|
||||
url_for("admin.process_model_show", process_model_id=process_model.id)
|
||||
)
|
||||
|
||||
|
||||
@admin_blueprint.route(
|
||||
"/process_models/<process_model_id>/edit/<file_name>", methods=["GET"]
|
||||
)
|
||||
def process_model_edit(process_model_id: str, file_name: str) -> str:
|
||||
"""Edit_bpmn."""
|
||||
process_model = ProcessModelService.get_process_model(process_model_id)
|
||||
bpmn_xml = SpecFileService.get_data(process_model, file_name)
|
||||
|
||||
return render_template(
|
||||
"process_model_edit.html",
|
||||
bpmn_xml=bpmn_xml.decode("utf-8"),
|
||||
process_model=process_model,
|
||||
file_name=file_name,
|
||||
)
|
||||
|
||||
|
||||
@admin_blueprint.route(
|
||||
"/process-models/<process_model_id>/save/<file_name>", methods=["POST"]
|
||||
)
|
||||
def process_model_save(process_model_id: str, file_name: str) -> Union[str, Response]:
|
||||
"""Process_model_save."""
|
||||
process_model = ProcessModelService.get_process_model(process_model_id)
|
||||
SpecFileService.update_file(process_model, file_name, request.get_data())
|
||||
if process_model.primary_file_name is None:
|
||||
flash("No primary_file_name", "error")
|
||||
return redirect(url_for("admin.process_group_list"))
|
||||
bpmn_xml = SpecFileService.get_data(process_model, process_model.primary_file_name)
|
||||
return render_template(
|
||||
"process_model_edit.html",
|
||||
bpmn_xml=bpmn_xml.decode("utf-8"),
|
||||
process_model=process_model,
|
||||
file_name=file_name,
|
||||
)
|
||||
|
||||
|
||||
@admin_blueprint.route("/process-models/<process_model_id>/run", methods=["GET"])
|
||||
def process_model_run(process_model_id: str) -> Union[str, Response]:
|
||||
"""Process_model_run."""
|
||||
user = UserService.create_user("Mr. Test", "internal", "Mr. Test")
|
||||
process_instance = (
|
||||
ProcessInstanceService.create_process_instance_from_process_model_identifier(
|
||||
process_model_id, user
|
||||
)
|
||||
)
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
processor.do_engine_steps()
|
||||
result = processor.get_data()
|
||||
|
||||
process_model = ProcessModelService.get_process_model(process_model_id)
|
||||
files = SpecFileService.get_files(process_model, extension_filter="bpmn")
|
||||
current_file_name = process_model.primary_file_name
|
||||
if current_file_name is None:
|
||||
flash("No primary_file_name", "error")
|
||||
return redirect(url_for("admin.process_group_list"))
|
||||
bpmn_xml = SpecFileService.get_data(process_model, current_file_name)
|
||||
|
||||
return render_template(
|
||||
"process_model_show.html",
|
||||
process_model=process_model,
|
||||
bpmn_xml=bpmn_xml,
|
||||
result=result,
|
||||
files=files,
|
||||
current_file_name=current_file_name,
|
||||
)
|
||||
|
||||
|
||||
# def _find_or_create_user(username: str = "test_user1") -> Any:
|
||||
# """Find_or_create_user."""
|
||||
# user = UserModel.query.filter_by(username=username).first()
|
||||
# if user is None:
|
||||
# user = UserModel(username=username)
|
||||
# db.session.add(user)
|
||||
# db.session.commit()
|
||||
# return user
|
||||
|
||||
|
||||
def _allowed_file(filename: str) -> bool:
|
||||
"""_allowed_file."""
|
||||
return (
|
||||
"." in filename
|
||||
and filename.rsplit(".", 1)[1].lower() in ALLOWED_BPMN_EXTENSIONS
|
||||
)
|
|
@ -1,26 +0,0 @@
|
|||
import BpmnViewer from "bpmn-js";
|
||||
|
||||
var viewer = new BpmnViewer({
|
||||
container: "#canvas",
|
||||
});
|
||||
|
||||
viewer
|
||||
.importXML(pizzaDiagram)
|
||||
.then(function (result) {
|
||||
const { warnings } = result;
|
||||
|
||||
console.log("success !", warnings);
|
||||
|
||||
viewer.get("canvas").zoom("fit-viewport");
|
||||
})
|
||||
.catch(function (err) {
|
||||
const { warnings, message } = err;
|
||||
|
||||
console.log("something went wrong:", warnings, message);
|
||||
});
|
||||
|
||||
export function sayHello() {
|
||||
console.log("hello");
|
||||
}
|
||||
|
||||
window.foo = "bar";
|
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"name": "spiffworkflow-backend",
|
||||
"version": "0.0.0",
|
||||
"description": "Serve up Spiff Workflows to the World!",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bpmn-js": "^9.1.0",
|
||||
"bpmn-js-properties-panel": "^1.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"webpack-cli": "^4.9.2"
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
.example {
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
{% block head %}
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ url_for('admin.static', filename='style.css') }}"
|
||||
/>
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{ self.title() }}</h1>
|
||||
{% with messages = get_flashed_messages(with_categories=true) %} {% if
|
||||
messages %}
|
||||
<ul class="flashes">
|
||||
{% for category, message in messages %}
|
||||
<li class="{{ category }}">{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %} {% endwith %} {% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
|
@ -1,18 +0,0 @@
|
|||
{% extends "layout.html" %} {% block title %}Process Groups{% endblock %} {%
|
||||
block content %}
|
||||
<table>
|
||||
<tbody>
|
||||
{# here we iterate over every item in our list#} {% for process_group in
|
||||
process_groups %}
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
href="{{ url_for('admin.process_group_show', process_group_id=process_group.id) }}"
|
||||
>{{ process_group.display_name }}</a
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
|
@ -1,25 +0,0 @@
|
|||
{% extends "layout.html" %}
|
||||
{% block title %}Process Group: {{ process_group.id }}{% endblock %}
|
||||
{% block content %}
|
||||
<button
|
||||
type="button"
|
||||
onclick="window.location.href='{{ url_for( 'admin.process_group_list') }}';"
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<table>
|
||||
<tbody>
|
||||
{# here we iterate over every item in our list#}
|
||||
{% for process_model in process_group.process_models %}
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
href="{{ url_for('admin.process_model_show', process_model_id=process_model.id) }}"
|
||||
>{{ process_model.display_name }}</a
|
||||
>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
|
@ -1,167 +0,0 @@
|
|||
{% extends "layout.html" %} {% block title %}
|
||||
Process Model Edit: {{ process_model.id }}
|
||||
{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
<!-- example styles -->
|
||||
<!-- required modeler styles -->
|
||||
<link rel="stylesheet" href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/bpmn-js.css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/diagram-js.css" />
|
||||
<link rel="stylesheet" href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/bpmn-font/css/bpmn.css" />
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/bpmn-js-properties-panel/dist/assets/properties-panel.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/bpmn-js-properties-panel/dist/assets/element-templates.css">
|
||||
|
||||
<!-- modeler distro -->
|
||||
<script src="https://unpkg.com/bpmn-js@9.1.0/dist/bpmn-modeler.development.js"></script>
|
||||
|
||||
<!-- needed for this example only -->
|
||||
<script src="https://unpkg.com/jquery@3.3.1/dist/jquery.js"></script>
|
||||
|
||||
<!-- example styles -->
|
||||
<style>
|
||||
html, body, #canvas {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.diagram-note {
|
||||
background-color: rgba(66, 180, 21, 0.7);
|
||||
color: White;
|
||||
border-radius: 5px;
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
padding: 5px;
|
||||
min-height: 16px;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.needs-discussion:not(.djs-connection) .djs-visual > :nth-child(1) {
|
||||
stroke: rgba(66, 180, 21, 0.7) !important; /* color elements as red */
|
||||
}
|
||||
|
||||
#save-button {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 20px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="result">{{ result }}</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick="window.location.href='{{ url_for( 'admin.process_model_show_file', process_model_id=process_model.id, file_name=file_name ) }}';"
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button type="button" onclick="exportDiagram()">Save</button>
|
||||
<!-- <div class="modeler"> -->
|
||||
<div id="canvas"></div>
|
||||
<div id="properties"></div>
|
||||
<!-- </div> -->
|
||||
|
||||
<meta id="bpmn_xml" data-name="{{bpmn_xml}}" />
|
||||
<script>
|
||||
// import BpmnModeler from '/admin/static/node_modules/bpmn-js/lib/Modeler.js';
|
||||
// import {
|
||||
// BpmnPropertiesPanelModule,
|
||||
// BpmnPropertiesProviderModule,
|
||||
// } from '/admin/static/node_modules/bpmn-js-properties-panel/dist/index.js';
|
||||
//
|
||||
// const bpmnModeler = new BpmnModeler({
|
||||
// container: '#canvas',
|
||||
// propertiesPanel: {
|
||||
// parent: '#properties'
|
||||
// },
|
||||
// additionalModules: [
|
||||
// BpmnPropertiesPanelModule,
|
||||
// BpmnPropertiesProviderModule
|
||||
// ]
|
||||
// });
|
||||
|
||||
// modeler instance
|
||||
var bpmnModeler = new BpmnJS({
|
||||
container: "#canvas",
|
||||
keyboard: {
|
||||
bindTo: window,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Save diagram contents and print them to the console.
|
||||
*/
|
||||
async function exportDiagram() {
|
||||
try {
|
||||
var data = await bpmnModeler.saveXML({ format: true });
|
||||
//POST request with body equal on data in JSON format
|
||||
fetch("/admin/process-models/{{ process_model.id }}/save/{{ file_name }}", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "text/xml",
|
||||
},
|
||||
body: data.xml,
|
||||
})
|
||||
.then((response) => response.json())
|
||||
//Then with the data from the response in JSON...
|
||||
.then((data) => {
|
||||
console.log("Success:", data);
|
||||
})
|
||||
//Then with the error genereted...
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
});
|
||||
|
||||
alert("Diagram exported. Check the developer tools!");
|
||||
} catch (err) {
|
||||
console.error("could not save BPMN 2.0 diagram", err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open diagram in our modeler instance.
|
||||
*
|
||||
* @param {String} bpmnXML diagram to display
|
||||
*/
|
||||
async function openDiagram(bpmnXML) {
|
||||
// import diagram
|
||||
try {
|
||||
await bpmnModeler.importXML(bpmnXML);
|
||||
|
||||
// access modeler components
|
||||
var canvas = bpmnModeler.get("canvas");
|
||||
var overlays = bpmnModeler.get("overlays");
|
||||
|
||||
// zoom to fit full viewport
|
||||
canvas.zoom("fit-viewport");
|
||||
|
||||
// attach an overlay to a node
|
||||
overlays.add("SCAN_OK", "note", {
|
||||
position: {
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
},
|
||||
html: '<div class="diagram-note">Mixed up the labels?</div>',
|
||||
});
|
||||
|
||||
// add marker
|
||||
canvas.addMarker("SCAN_OK", "needs-discussion");
|
||||
} catch (err) {
|
||||
console.error("could not import BPMN 2.0 diagram", err);
|
||||
}
|
||||
}
|
||||
|
||||
// trying to use the python variable bpmn_xml directly causes the xml to have escape sequences
|
||||
// and using the meta tag seems to help with that
|
||||
var bpmn_xml = $("#bpmn_xml").data();
|
||||
openDiagram(bpmn_xml.name);
|
||||
|
||||
// wire save button
|
||||
$("#save-button").click(exportDiagram);
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -1,159 +0,0 @@
|
|||
{% extends "layout.html" %} {% block title %}Process Model: {{ process_model.id
|
||||
}}{% endblock %} {% block head %} {{ super() }}
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
<script src="{{ url_for('admin.static', filename='node_modules/bpmn-js/dist/bpmn-viewer.development.js') }}"></script>
|
||||
|
||||
<!-- viewer distro (without pan and zoom) -->
|
||||
<!--
|
||||
<script src="https://unpkg.com/bpmn-js@9.1.0/dist/bpmn-viewer.development.js"></script>
|
||||
-->
|
||||
|
||||
<!-- required viewer styles -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/bpmn-js.css"
|
||||
/>
|
||||
|
||||
<!-- viewer distro (with pan and zoom) -->
|
||||
<script src="https://unpkg.com/bpmn-js@9.1.0/dist/bpmn-navigated-viewer.development.js"></script>
|
||||
|
||||
<!-- needed for this example only -->
|
||||
<script src="https://unpkg.com/jquery@3.3.1/dist/jquery.js"></script>
|
||||
|
||||
<!-- example styles -->
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#canvas {
|
||||
height: 90%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.diagram-note {
|
||||
background-color: rgba(66, 180, 21, 0.7);
|
||||
color: White;
|
||||
border-radius: 5px;
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
padding: 5px;
|
||||
min-height: 16px;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.needs-discussion:not(.djs-connection) .djs-visual > :nth-child(1) {
|
||||
stroke: rgba(66, 180, 21, 0.7) !important; /* color elements as red */
|
||||
}
|
||||
</style>
|
||||
{% endblock %} {% block content %}
|
||||
<div id="result">{{ result }}</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick="window.location.href='{{ url_for( 'admin.process_group_show', process_group_id=process_model.process_group_id ) }}';"
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onclick="window.location.href='{{ url_for( 'admin.process_model_run' , process_model_id=process_model.id ) }}';"
|
||||
>
|
||||
Run
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onclick="window.location.href='{{ url_for( 'admin.process_model_edit' , process_model_id=process_model.id, file_name=current_file_name ) }}';"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
|
||||
{% if files %}
|
||||
<h3>BPMN Files</h3>
|
||||
<ul>
|
||||
{% for file in files %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ url_for('admin.process_model_show_file', process_model_id=process_model.id, file_name=file.name) }}"
|
||||
>{{ file.name }}</a
|
||||
>
|
||||
{% if file.name == current_file_name %} (current) {% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<form
|
||||
method="post"
|
||||
action="/admin/process-models/{{process_model.id}}/upload-file"
|
||||
enctype="multipart/form-data"
|
||||
>
|
||||
<input type="file" name="file" />
|
||||
<input type="submit" value="Upload" />
|
||||
</form>
|
||||
|
||||
<div id="canvas"></div>
|
||||
|
||||
<meta id="bpmn_xml" data-name="{{bpmn_xml}}" />
|
||||
<script>
|
||||
var diagramUrl =
|
||||
"https://cdn.staticaly.com/gh/bpmn-io/bpmn-js-examples/dfceecba/starter/diagram.bpmn";
|
||||
|
||||
// viewer instance
|
||||
var bpmnViewer = new BpmnJS({
|
||||
container: "#canvas",
|
||||
});
|
||||
|
||||
/**
|
||||
* Open diagram in our viewer instance.
|
||||
*
|
||||
* @param {String} bpmnXML diagram to display
|
||||
*/
|
||||
async function openDiagram(bpmnXML) {
|
||||
// import diagram
|
||||
try {
|
||||
await bpmnViewer.importXML(bpmnXML);
|
||||
|
||||
// access viewer components
|
||||
var canvas = bpmnViewer.get("canvas");
|
||||
var overlays = bpmnViewer.get("overlays");
|
||||
|
||||
// zoom to fit full viewport
|
||||
canvas.zoom("fit-viewport");
|
||||
|
||||
// attach an overlay to a node
|
||||
overlays.add("SCAN_OK", "note", {
|
||||
position: {
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
},
|
||||
html: '<div class="diagram-note">Mixed up the labels?</div>',
|
||||
});
|
||||
|
||||
// add marker
|
||||
canvas.addMarker("SCAN_OK", "needs-discussion");
|
||||
} catch (err) {
|
||||
console.error("could not import BPMN 2.0 diagram", err);
|
||||
}
|
||||
}
|
||||
var bpmn_xml = $("#bpmn_xml").data();
|
||||
openDiagram(bpmn_xml.name);
|
||||
|
||||
// load external diagram file via AJAX and open it
|
||||
//$.get(diagramUrl, openDiagram, 'text');
|
||||
</script>
|
||||
<!--
|
||||
Thanks for trying out our BPMN toolkit!
|
||||
If you'd like to learn more about what our library,
|
||||
continue with some more basic examples:
|
||||
* https://github.com/bpmn-io/bpmn-js-examples/overlays
|
||||
* https://github.com/bpmn-io/bpmn-js-examples/interaction
|
||||
* https://github.com/bpmn-io/bpmn-js-examples/colors
|
||||
* https://github.com/bpmn-io/bpmn-js-examples/commenting
|
||||
To get a bit broader overview over how bpmn-js works,
|
||||
follow our walkthrough:
|
||||
* https://bpmn.io/toolkit/bpmn-js/walkthrough/
|
||||
Related starters:
|
||||
* https://raw.githubusercontent.com/bpmn-io/bpmn-js-examples/starter/modeler.html
|
||||
-->
|
||||
{% endblock %}
|
Loading…
Reference in New Issue