parent
0f6ad79c8c
commit
f69a1049c5
@ -0,0 +1,38 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询modeler列表
|
||||
export function listDefinition(query) {
|
||||
return request({
|
||||
url: '/workflow/processDefinition/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询请假详细
|
||||
export function getDefinitionsByInstanceId(instanceId) {
|
||||
return request({
|
||||
url: '/workflow/processDefinition/getDefinitions/' + instanceId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 挂起激活转换
|
||||
export function suspendOrActiveApply(data) {
|
||||
return request({
|
||||
url: '/workflow/processDefinition/suspendOrActiveApply',
|
||||
method: 'post',
|
||||
data:data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 删除Modeler
|
||||
export function delDefinition(id) {
|
||||
return request({
|
||||
url: '/workflow/processDefinition/remove/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,8 @@
|
||||
import request from '@/utils/request'
|
||||
// 查询请假详细
|
||||
export function historyFromData(instanceId) {
|
||||
return request({
|
||||
url: '/workflow/historyFromData/ByInstanceId/' + instanceId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询task列表
|
||||
export function listTask(query) {
|
||||
return request({
|
||||
url: '/workflow/task/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询表单
|
||||
export function formDataShow(taskID) {
|
||||
return request({
|
||||
url: '/workflow/task/formDataShow/'+taskID,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
// 查询表单
|
||||
export function formDataSave(taskID,data) {
|
||||
return request({
|
||||
url: '/workflow/task/formDataSave/'+taskID,
|
||||
method: 'post',
|
||||
data:data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询请假列表
|
||||
export function listLeave(query) {
|
||||
return request({
|
||||
url: '/workflow/workflow/leave/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
// 查询请假列表
|
||||
export function listLeaveAll(query) {
|
||||
return request({
|
||||
url: '/workflow/workflow/leave/listAll',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询请假详细
|
||||
export function getLeave(id) {
|
||||
return request({
|
||||
url: '/workflow/workflow/leave/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// 新增请假
|
||||
export function addLeave(data) {
|
||||
return request({
|
||||
url: '/workflow/workflow/leave',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改请假
|
||||
export function updateLeave(data) {
|
||||
return request({
|
||||
url: '/workflow/workflow/leave',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除请假
|
||||
export function delLeave(id) {
|
||||
return request({
|
||||
url: '/workflow/workflow/leave/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 导出请假
|
||||
export function exportLeave(query) {
|
||||
return request({
|
||||
url: '/workflow/workflow/leave/export',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
|
||||
|
||||
<el-table v-loading="loading" :data="tastList">
|
||||
<!-- <el-table-column label="流程ID" align="center" prop="id"/>-->
|
||||
<el-table-column label="流程名称" align="center" prop="instanceName"/>
|
||||
<el-table-column label="任务节点名称" align="center" prop="name"/>
|
||||
<el-table-column label="任务状态" align="center" prop="status"/>
|
||||
<el-table-column label="办理人" align="center" prop="assignee"/>
|
||||
<el-table-column label="创建时间" align="center" prop="createdDate"/>
|
||||
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="examineAndApprove (scope.row)"
|
||||
v-hasPermi="['workflow:leave:edit']"
|
||||
>审批
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 审批对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" v-if="open" width="500px" append-to-body>
|
||||
<leaveHistoryForm :businessKey="businessKey" v-if="'leave'==definitionKey"/>
|
||||
|
||||
<el-form :model="form" ref="form" label-width="100px" class="demo-dynamic">
|
||||
<el-form-item
|
||||
v-for="(domain, index) in form.formData"
|
||||
:label="domain.controlLable"
|
||||
:key="index"
|
||||
>
|
||||
<el-radio-group v-model="domain.controlValue" v-if="'radio'==domain.controlType">
|
||||
<el-radio v-for="(defaults,indexd) in domain.controlDefault.split('--__--')"
|
||||
:label=indexd
|
||||
:key="indexd"
|
||||
>{{defaults}}
|
||||
|
||||
</el-radio>
|
||||
|
||||
</el-radio-group>
|
||||
<el-input type="textarea" v-model="domain.controlValue" v-if="'textarea'==domain.controlType"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import leaveHistoryForm from "@/views/business/workflow/workflow/leave/leaveHistoryForm";
|
||||
import {formDataSave, formDataShow, listTask} from "@/api/business/workflow/activiti/task";
|
||||
|
||||
export default {
|
||||
name: "Leave",
|
||||
components: {leaveHistoryForm},
|
||||
data() {
|
||||
return {
|
||||
id:'',
|
||||
definitionKey: '',
|
||||
businessKey: '',
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 请假表格数据
|
||||
tastList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
formData:[]
|
||||
},
|
||||
// 表单校验
|
||||
rules: {}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询请假列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listTask(this.queryParams).then(response => {
|
||||
this.tastList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.definitionKey = '',
|
||||
this.businessKey = '',
|
||||
this.form = {
|
||||
formData:[],
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
|
||||
/** 审批按钮操作 */
|
||||
examineAndApprove(row) {
|
||||
console.log(row)
|
||||
this.reset();
|
||||
this.definitionKey = row.definitionKey;
|
||||
this.businessKey = row.businessKey;
|
||||
this.id=row.id;
|
||||
formDataShow(row.id).then(response => {
|
||||
// FormProperty_3qipis2--__!!radio--__!!审批意见--__!!i--__!!同意--__--不同意
|
||||
// FormProperty_0lffpcm--__!!textarea--__!!批注--__!!f--__!!null
|
||||
let datas = response.data;
|
||||
let formData = []
|
||||
for (let i = 0; i < datas.length; i++) {
|
||||
let strings = datas[i].split('--__!!')
|
||||
let controlValue = null
|
||||
let controlDefault = null
|
||||
switch (strings[1]) {
|
||||
case 'radio':
|
||||
controlValue = 0;
|
||||
controlDefault = strings[4]
|
||||
break;
|
||||
// default:
|
||||
}
|
||||
formData.push({
|
||||
controlId: strings[0],
|
||||
controlType: strings[1],
|
||||
controlLable: strings[2],
|
||||
controlIsParam: strings[3],
|
||||
controlValue: controlValue,
|
||||
controlDefault: controlDefault
|
||||
})
|
||||
}
|
||||
this.form.formData = formData;
|
||||
this.open = true;
|
||||
this.title = "审批";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
formDataSave(this.id,this.form.formData).then(response => {
|
||||
this.msgSuccess("审批成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,459 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="请假类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择请假类型" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in typeOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入标题"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态" prop="state">
|
||||
<el-select v-model="queryParams.state" placeholder="请选择状态" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in stateOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="创建者" prop="createBy">-->
|
||||
<!-- <el-select v-model="queryParams.createBy" placeholder="请选择创建者" clearable size="small">-->
|
||||
<!-- <el-option label="请选择字典生成" value="" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item>
|
||||
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['workflow:leave:add']"
|
||||
>新增
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['workflow:leave:export']"
|
||||
>导出
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="leaveList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center"/>
|
||||
<!-- <el-table-column label="主键ID" align="center" prop="id" />-->
|
||||
<el-table-column label="请假类型" align="center" prop="type" :formatter="typeFormat"/>
|
||||
<el-table-column label="标题" align="center" prop="title"/>
|
||||
<el-table-column label="原因" align="center" prop="reason"/>
|
||||
<el-table-column label="开始时间" align="center" prop="leaveStartTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.leaveStartTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间" align="center" prop="leaveEndTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.leaveEndTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
||||
<!-- <el-table-column label="状态" align="center" prop="state" :formatter="stateFormat">-->
|
||||
<el-table-column label="状态" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.state!==0">
|
||||
{{ stateFormat(scope.row) }}
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ scope.row.taskName }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="创建者" align="center" prop="createName" />-->
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="2===scope.row.state"
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['workflow:leave:edit']"
|
||||
>修改
|
||||
</el-button>
|
||||
<!-- <el-button v-if="1==scope.row.state"-->
|
||||
<!-- size="mini"-->
|
||||
<!-- type="text"-->
|
||||
<!-- icon="el-icon-edit"-->
|
||||
<!-- @click="terminateLeave(scope.row)"-->
|
||||
<!-- v-hasPermi="['workflow:leave:edit']"-->
|
||||
<!-- >销假-->
|
||||
<!-- </el-button>-->
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="historyFory(scope.row)"
|
||||
v-hasPermi="['workflow:leave:edit']"
|
||||
>审批详情
|
||||
</el-button>
|
||||
|
||||
<el-button v-if="0===scope.row.state"
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="checkTheSchedule(scope.row)"
|
||||
v-hasPermi="['workflow:leave:edit']"
|
||||
>查看进度
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<el-dialog
|
||||
:visible.sync="modelVisible"
|
||||
title="进度查询"
|
||||
width="1680px"
|
||||
append-to-body
|
||||
>
|
||||
<div style="position:relative;height: 100%;">
|
||||
<iframe
|
||||
id="iframe"
|
||||
:src="modelerUrl"
|
||||
frameborder="0"
|
||||
width="100%"
|
||||
height="720px"
|
||||
scrolling="auto"
|
||||
></iframe>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 查看详细信息话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open2" width="500px" append-to-body>
|
||||
<leaveHistoryForm :businessKey="businessKey" v-if="open2"/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="open2=!open2">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form-item label="请假类型" prop="type">
|
||||
<el-select v-model="form.type" placeholder="请选择请假类型" @change="chooseMedicine">
|
||||
<el-option
|
||||
v-for="dict in typeOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input v-model="form.title"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="原因" prop="reason">
|
||||
<el-input v-model="form.reason" type="textarea" placeholder="请输入内容"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间" prop="leaveStartTime">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
v-model="form.leaveStartTime"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择开始时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间" prop="leaveEndTime">
|
||||
<el-date-picker clearable size="small" style="width: 200px"
|
||||
v-model="form.leaveEndTime"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
placeholder="选择结束时间">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
import leaveHistoryForm from "./leaveHistoryForm";
|
||||
import {
|
||||
addLeave,
|
||||
delLeave,
|
||||
exportLeave,
|
||||
getLeave,
|
||||
listLeave,
|
||||
updateLeave
|
||||
} from "@/api/business/workflow/workflow/leave";
|
||||
import {getDefinitionsByInstanceId} from "@/api/business/workflow/activiti/definition";
|
||||
|
||||
export default {
|
||||
name: 'Leave',
|
||||
components: {leaveHistoryForm},
|
||||
data() {
|
||||
return {
|
||||
modelVisible: false,
|
||||
modelerUrl: '',
|
||||
userName: '',
|
||||
createName: '',
|
||||
businessKey: '',
|
||||
//用户信息
|
||||
user: {},
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 请假表格数据
|
||||
leaveList: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
open2: false,
|
||||
// 请假类型字典
|
||||
typeOptions: [],
|
||||
// 状态字典
|
||||
stateOptions: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
type: null,
|
||||
title: null,
|
||||
reason: null,
|
||||
leaveStartTime: null,
|
||||
leaveEndTime: null,
|
||||
instanceId: null,
|
||||
state: null,
|
||||
createBy: null
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
type: [
|
||||
{required: true, message: '请假类型不能为空', trigger: 'change'}
|
||||
],
|
||||
title: [
|
||||
{required: true, message: '标题不能为空', trigger: 'blur'}
|
||||
],
|
||||
reason: [
|
||||
{required: true, message: '原因不能为空', trigger: 'blur'}
|
||||
],
|
||||
leaveStartTime: [
|
||||
{required: true, message: '开始时间不能为空', trigger: 'blur'}
|
||||
],
|
||||
leaveEndTime: [
|
||||
{required: true, message: '结束时间不能为空', trigger: 'blur'}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDicts('activiti_leave_type').then(response => {
|
||||
this.typeOptions = response.data
|
||||
})
|
||||
this.getDicts('activiti_flow_type').then(response => {
|
||||
this.stateOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
/** 查询请假列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listLeave(this.queryParams).then(response => {
|
||||
this.leaveList = response.rows
|
||||
this.total = response.total
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 请假类型字典翻译
|
||||
typeFormat(row, column) {
|
||||
return this.selectDictLabel(this.typeOptions, row.type)
|
||||
},
|
||||
// 状态字典翻译
|
||||
stateFormat(row, column) {
|
||||
return this.selectDictLabel(this.stateOptions, row.state)
|
||||
},
|
||||
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false
|
||||
this.reset()
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: null,
|
||||
type: null,
|
||||
title: null,
|
||||
reason: null,
|
||||
leaveStartTime: null,
|
||||
leaveEndTime: null,
|
||||
instanceId: null,
|
||||
state: null,
|
||||
createBy: null,
|
||||
createTime: null,
|
||||
updateTime: null
|
||||
}
|
||||
this.resetForm('form')
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.createName = this.$store.getters.nickName
|
||||
if (this.$store.getters.name !== "admin") {
|
||||
this.reset()
|
||||
this.open = true
|
||||
this.title = '添加请假'
|
||||
} else {
|
||||
this.$alert('管理员不能创建流程', '管理员不能创建流程', {
|
||||
confirmButtonText: '确定',
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.reset()
|
||||
getLeave(row.id).then(response => {
|
||||
this.form = response.data
|
||||
this.open = true
|
||||
this.title = '修改请假'
|
||||
})
|
||||
},
|
||||
/** 审批详情 */
|
||||
historyFory(row) {
|
||||
this.businessKey = row.id
|
||||
this.open2 = true
|
||||
this.title = '审批详情'
|
||||
|
||||
},
|
||||
/** 进度查看 */
|
||||
checkTheSchedule(row) {
|
||||
getDefinitionsByInstanceId(row.instanceId).then(response => {
|
||||
let data = response.data
|
||||
// this.url = '/bpmnjs/index.html?type=lookBpmn&deploymentFileUUID='+data.deploymentID+'&deploymentName='+ encodeURI(data.resourceName);
|
||||
this.modelerUrl = '/bpmnjs/index.html?type=lookBpmn&instanceId=' + row.instanceId + '&deploymentFileUUID=' + data.deploymentID + '&deploymentName=' + encodeURI(data.resourceName);
|
||||
this.modelVisible = true
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.id != null) {
|
||||
updateLeave(this.form).then(response => {
|
||||
this.msgSuccess('修改成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
} else {
|
||||
addLeave(this.form).then(response => {
|
||||
this.msgSuccess('新增成功')
|
||||
this.open = false
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const ids = row.id || this.ids
|
||||
this.$confirm('是否确认删除请假编号为"' + ids + '"的数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function () {
|
||||
return delLeave(ids)
|
||||
}).then(() => {
|
||||
this.getList()
|
||||
this.msgSuccess('删除成功')
|
||||
})
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有请假数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function () {
|
||||
return exportLeave(queryParams)
|
||||
}).then(response => {
|
||||
this.download(response.msg)
|
||||
})
|
||||
},
|
||||
chooseMedicine() {
|
||||
this.form.title = this.createName + "的" + this.form.type + "申请";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="请假类型" prop="type">
|
||||
<el-select v-model="queryParams.type" placeholder="请选择请假类型" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in typeOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="标题" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入标题"
|
||||
clearable
|
||||
size="small"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态" prop="state">
|
||||
<el-select v-model="queryParams.state" placeholder="请选择状态" clearable size="small">
|
||||
<el-option
|
||||
v-for="dict in stateOptions"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="创建者" prop="createBy">-->
|
||||
<!-- <el-select v-model="queryParams.createBy" placeholder="请选择创建者" clearable size="small">-->
|
||||
<!-- <el-option label="请选择字典生成" value="" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item>
|
||||
<el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['workflow:leave:export']"
|
||||
>导出
|
||||
</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="leaveList">
|
||||
<el-table-column type="selection" width="55" align="center"/>
|
||||
<!-- <el-table-column label="主键ID" align="center" prop="id" />-->
|
||||
<el-table-column label="请假类型" align="center" prop="type" :formatter="typeFormat"/>
|
||||
<el-table-column label="标题" align="center" prop="title"/>
|
||||
<el-table-column label="原因" align="center" prop="reason"/>
|
||||
<el-table-column label="开始时间" align="center" prop="leaveStartTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.leaveStartTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间" align="center" prop="leaveEndTime" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.leaveEndTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建人" align="center" prop="createName"/>
|
||||
<el-table-column label="状态" align="center" prop="state" :formatter="stateFormat"/>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="historyFory(scope.row)"
|
||||
v-hasPermi="['workflow:leave:edit']"
|
||||
>审批详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
|
||||
<!-- 查看详细信息话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open2" width="500px" append-to-body>
|
||||
<leaveHistoryForm :businessKey="businessKey" v-if="open2"/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="open2=!open2">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import leaveHistoryForm from "./leaveHistoryForm";
|
||||
import {exportLeave, listLeaveAll} from "@/api/business/workflow/workflow/leave";
|
||||
|
||||
export default {
|
||||
name: 'Leave',
|
||||
components: {leaveHistoryForm},
|
||||
data() {
|
||||
return {
|
||||
businessKey: '',
|
||||
//用户信息
|
||||
user: {},
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 请假表格数据
|
||||
leaveList: [],
|
||||
// 弹出层标题
|
||||
title: '',
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
open2: false,
|
||||
// 请假类型字典
|
||||
typeOptions: [],
|
||||
// 状态字典
|
||||
stateOptions: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
type: null,
|
||||
title: null,
|
||||
reason: null,
|
||||
leaveStartTime: null,
|
||||
leaveEndTime: null,
|
||||
instanceId: null,
|
||||
state: null,
|
||||
createBy: null
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getDicts('activiti_leave_type').then(response => {
|
||||
this.typeOptions = response.data
|
||||
})
|
||||
this.getDicts('activiti_flow_type').then(response => {
|
||||
this.stateOptions = response.data
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
|
||||
/** 查询请假列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
listLeaveAll(this.queryParams).then(response => {
|
||||
this.leaveList = response.rows
|
||||
this.total = response.total
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 请假类型字典翻译
|
||||
typeFormat(row, column) {
|
||||
return this.selectDictLabel(this.typeOptions, row.type)
|
||||
},
|
||||
// 状态字典翻译
|
||||
stateFormat(row, column) {
|
||||
return this.selectDictLabel(this.stateOptions, row.state)
|
||||
},
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm('queryForm')
|
||||
this.handleQuery()
|
||||
},
|
||||
|
||||
/** 审批详情 */
|
||||
historyFory(row) {
|
||||
|
||||
this.businessKey = row.id
|
||||
this.open2 = true
|
||||
this.title = '审批详情'
|
||||
|
||||
},
|
||||
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
const queryParams = this.queryParams
|
||||
this.$confirm('是否确认导出所有请假数据项?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(function () {
|
||||
return exportLeave(queryParams)
|
||||
}).then(response => {
|
||||
this.download(response.msg)
|
||||
})
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
tmp/
|
||||
dist/
|
@ -0,0 +1 @@
|
||||
package-lock=false
|
@ -0,0 +1,140 @@
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
require('load-grunt-tasks')(grunt);
|
||||
|
||||
/**
|
||||
* Resolve external project resource as file path
|
||||
*/
|
||||
function resolvePath(project, file) {
|
||||
return path.join(path.dirname(require.resolve(project)), file);
|
||||
}
|
||||
|
||||
|
||||
grunt.initConfig({
|
||||
browserify: {
|
||||
options: {
|
||||
browserifyOptions: {
|
||||
debug: true
|
||||
},
|
||||
transform: [
|
||||
[ 'stringify', {
|
||||
extensions: [ '.bpmn' ]
|
||||
} ]
|
||||
],
|
||||
plugin: [
|
||||
'esmify'
|
||||
]
|
||||
},
|
||||
watch: {
|
||||
options: {
|
||||
watch: true
|
||||
},
|
||||
files: {
|
||||
'dist/index.js': [ 'app/**/*.js' ]
|
||||
}
|
||||
},
|
||||
app: {
|
||||
files: {
|
||||
'dist/index.js': [ 'app/**/*.js' ]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
copy: {
|
||||
diagram_js: {
|
||||
files: [
|
||||
{
|
||||
src: resolvePath('diagram-js', 'assets/diagram-js.css'),
|
||||
dest: 'dist/css/diagram-js.css'
|
||||
}
|
||||
]
|
||||
},
|
||||
bpmn_js: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
cwd: resolvePath('bpmn-js', 'dist/assets'),
|
||||
src: ['**/*.*', '!**/*.js'],
|
||||
dest: 'dist/vendor'
|
||||
}
|
||||
]
|
||||
},
|
||||
app: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'app/',
|
||||
src: ['**/*.*', '!**/*.js'],
|
||||
dest: 'dist'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
less: {
|
||||
options: {
|
||||
dumpLineNumbers: 'comments',
|
||||
paths: [
|
||||
'node_modules'
|
||||
]
|
||||
},
|
||||
|
||||
styles: {
|
||||
files: {
|
||||
'dist/css/app.css': 'styles/app.less'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
options: {
|
||||
livereload: true
|
||||
},
|
||||
|
||||
samples: {
|
||||
files: [ 'app/**/*.*' ],
|
||||
tasks: [ 'copy:app' ]
|
||||
},
|
||||
|
||||
less: {
|
||||
files: [
|
||||
'styles/**/*.less',
|
||||
'node_modules/bpmn-js-properties-panel/styles/**/*.less'
|
||||
],
|
||||
tasks: [
|
||||
'less'
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
connect: {
|
||||
livereload: {
|
||||
options: {
|
||||
port: 9013,
|
||||
livereload: true,
|
||||
hostname: 'localhost',
|
||||
open: true,
|
||||
base: [
|
||||
'dist'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// tasks
|
||||
|
||||
grunt.registerTask('build', [ 'copy', 'less', 'browserify:app' ]);
|
||||
|
||||
grunt.registerTask('auto-build', [
|
||||
'copy',
|
||||
'less',
|
||||
'browserify:watch',
|
||||
'connect:livereload',
|
||||
'watch'
|
||||
]);
|
||||
|
||||
grunt.registerTask('default', [ 'build' ]);
|
||||
};
|
After Width: | Height: | Size: 5.5 KiB |
@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<html >
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>在线绘制流程</title>
|
||||
<link rel="icon" href="favicon.ico">
|
||||
<link rel="stylesheet" href="css/diagram-js.css" />
|
||||
<link rel="stylesheet" href="vendor/bpmn-font/css/bpmn-embedded.css" />
|
||||
<link rel="stylesheet" href="css/app.css" />
|
||||
|
||||
<style>
|
||||
.item{
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.bjs-powered-by {
|
||||
display: none;
|
||||
}
|
||||
.buttons > li {
|
||||
/* display: inline-block; */
|
||||
margin-right: 10px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
float: left;
|
||||
}
|
||||
.buttons > li > a.btn {
|
||||
background: #00BCD4;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0px 10px;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
opacity: 1;
|
||||
height: 26px;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
}
|
||||
.label {
|
||||
background: #00BCD4;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0px 10px;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
height: 26px;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
}
|
||||
.sy-mask{width:100%;
|
||||
height:100%;
|
||||
position:fixed;
|
||||
background:rgba(0,0,0,0.8);
|
||||
left:0;top:0;z-index:1000;
|
||||
display: none;
|
||||
}
|
||||
.sy-alert{
|
||||
position:fixed;display:none;background:#fff;border-radius:5px;overflow:hidden;width:300px;max-width:90%;max-height:80%;left:0;right:0;margin:0 auto;z-index:9999}.sy-alert.animated{-webkit-animation-duration:.3s;animation-duration:.3s}.sy-alert .sy-title{height:45px;color:#333;line-height:45px;font-size:15px;border-bottom:1px solid #eee;padding:0 12px}.sy-alert .sy-content{padding:20px;text-align:center;font-size:14px;line-height:24px;color:#666;overflow-y:auto}.sy-alert .sy-btn{height:50%;border-top:1px solid #eee;overflow:hidden}.sy-alert .sy-btn button{float:left;border:0;color:#333;cursor:pointer;background:#fff;width:50%;line-height:45px;font-size:15px;text-align:center}.sy-alert .sy-btn button:nth-child(1){color:#888;border-right:1px solid #eee}.sy-alert.sy-alert-alert .sy-btn button{float:none;width:100%}.sy-alert.sy-alert-tips{text-align:center;width:150px;background:rgba(0,0,0,0.7)}.sy-alert.sy-alert-tips .sy-content{padding:8px;color:#fff;font-size:14px}.sy-alert.sy-alert-model .sy-content{text-align:left}.sy-alert.sy-alert-model .sy-content .form .input-item{margin-bottom:12px;position:relative}.sy-alert.sy-alert-model .sy-content .form .input-item input{display:block;position:relative;width:100%;border:1px solid #eee;padding:10px}.sy-alert.sy-alert-model .sy-content .form .input-item .getcode{border:0;top:0;right:0;position:absolute;background:0;line-height:37px;color:#f60;width:100px;text-align:center}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="content with-diagram" id="js-drop-zone">
|
||||
<div class="message error">
|
||||
<div class="note">
|
||||
<p>无法显示bpms2.0</p>
|
||||
<div class="details">
|
||||
<span>错误详细信息</span>
|
||||
<pre></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="canvas" id="js-canvas"></div>
|
||||
<div class="properties-panel-parent" id="js-properties-panel"></div>
|
||||
</div>
|
||||
<ul class="buttons">
|
||||
<li class="item upload">
|
||||
<form id="form1" name="myForm" onsubmit="return false" method="post" enctype="multipart/form-data" title="上传文件">
|
||||
<input type="file" name="uploadFile" id="uploadFile" accept=".bpmn" style="display: none">
|
||||
<label class="label" for="uploadFile" >导入</label>
|
||||
</form>
|
||||
</li>
|
||||
<li class="item download">
|
||||
<a class="btn" href id="downloadBpmn">导出</a>
|
||||
</li>
|
||||
<li class="item submit">
|
||||
<a class="btn" id="js-download-diagram">
|
||||
部署
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="sy-alert sy-alert-model animated" sy-enter="zoomIn" sy-leave="zoomOut" sy-type="confirm" sy-mask="true" id="alert" >
|
||||
<div class="sy-title">部署流程</div>
|
||||
<div class="sy-content">
|
||||
确认是否部署该流程
|
||||
<!-- <div class="form">-->
|
||||
<!-- <p class="input-item"><input id="deploymentName" type="text" placeholder="请输入流程名称"></p>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<div class="sy-btn">
|
||||
<button id="sure">确定</button>
|
||||
<button class="cancel" >取消</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sy-mask cancel"></div>
|
||||
<script src="index.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,146 @@
|
||||
|
||||
import $ from 'jquery';
|
||||
import BpmnModeler from 'bpmn-js/lib/Modeler';
|
||||
//import propertiesPanelModule from '../resources/properties-panel';
|
||||
import propertiesPanelModule from 'bpmn-js-properties-panel';
|
||||
import propertiesProviderModule from '../resources/properties-panel/provider/activiti';
|
||||
import activitiModdleDescriptor from '../resources/activiti.json';
|
||||
import customTranslate from '../resources/customTranslate/customTranslate';
|
||||
import customControlsModule from '../resources/customControls';
|
||||
import tools from '../resources/tools'
|
||||
import diagramXML from '../resources/newDiagram.bpmn';
|
||||
const proHost = window.location.protocol + "//" + window.location.host;
|
||||
const href = window.location.href.split("bpmnjs")[0];
|
||||
const key = href.split(window.location.host)[1];
|
||||
const publicurl = proHost + key;
|
||||
|
||||
// 添加翻译组件
|
||||
var customTranslateModule = {
|
||||
translate: ['value', customTranslate]
|
||||
};
|
||||
var container = $('#js-drop-zone');
|
||||
var canvas = $('#js-canvas');
|
||||
var bpmnModeler = new BpmnModeler({
|
||||
container: canvas,
|
||||
propertiesPanel: {
|
||||
parent: '#js-properties-panel'
|
||||
},
|
||||
additionalModules: [
|
||||
propertiesPanelModule,
|
||||
propertiesProviderModule,
|
||||
customControlsModule,
|
||||
customTranslateModule
|
||||
],
|
||||
moddleExtensions: {
|
||||
activiti:activitiModdleDescriptor
|
||||
}
|
||||
});
|
||||
container.removeClass('with-diagram');
|
||||
// 判断浏览器支持程度
|
||||
if (!window.FileList || !window.FileReader) {
|
||||
window.alert('请使用谷歌、火狐、IE10+浏览器');
|
||||
} else {
|
||||
tools.registerFileDrop(container, tools.createDiagram(diagramXML, bpmnModeler, container));
|
||||
}
|
||||
|
||||
|
||||
$(function () {
|
||||
// 创建bpmn
|
||||
var param = tools.getUrlParam(window.location.href)
|
||||
$('.item').show()
|
||||
if (param.type === 'addBpmn') {
|
||||
tools.createDiagram(diagramXML, bpmnModeler, container);
|
||||
} else if (param.type === 'lookBpmn') { //编辑bpmn
|
||||
$('.item').hide()
|
||||
$('.download').show()
|
||||
const Id = param.deploymentFileUUID || '6d4af2dc-bab0-11ea-b584-3cf011eaafca'
|
||||
const Name=param.deploymentName || 'String.bpmn'
|
||||
const instanceId=param.instanceId
|
||||
var param={
|
||||
"deploymentId":Id,
|
||||
"resourceName":decodeURI(Name)
|
||||
}
|
||||
if(instanceId){
|
||||
var param1={
|
||||
instanceId
|
||||
}
|
||||
$.ajax({
|
||||
url: localStorage.getItem("VUE_APP_BASE_API")+'/activitiHistory/gethighLine',
|
||||
// url: 'http://localhost:8080/activitiHistory/gethighLine',
|
||||
type: 'GET',
|
||||
data: param1,
|
||||
dataType:'json',
|
||||
success: function (result) {
|
||||
console.log(result)
|
||||
var ColorJson=tools.getByColor(result.data)
|
||||
$.ajax({
|
||||
url: localStorage.getItem("VUE_APP_BASE_API")+'/processDefinition/getDefinitionXML',
|
||||
// url: 'http://localhost:8080/processDefinition/getDefinitionXML',
|
||||
type: 'GET',
|
||||
data: param,
|
||||
dataType:'text',
|
||||
success: function (result) {
|
||||
var newXmlData = result
|
||||
tools.createDiagram(newXmlData, bpmnModeler, container);
|
||||
setTimeout(function () {
|
||||
for (var i in ColorJson) {
|
||||
tools.setColor(ColorJson[i],bpmnModeler)
|
||||
}
|
||||
}, 200)
|
||||
},
|
||||
error: function (err) {
|
||||
console.log(err)
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function (err) {
|
||||
console.log(err)
|
||||
}
|
||||
});
|
||||
}else{
|
||||
//加载后台方法获取xml
|
||||
$.ajax({
|
||||
url: localStorage.getItem("VUE_APP_BASE_API")+'/processDefinition/getDefinitionXML',
|
||||
// url: 'http://localhost:8080/processDefinition/getDefinitionXML',
|
||||
type: 'GET',
|
||||
data: param,
|
||||
dataType:'text',
|
||||
success: function (result) {
|
||||
var newXmlData = result
|
||||
tools.createDiagram(newXmlData, bpmnModeler, container);
|
||||
},
|
||||
error: function (err) {
|
||||
console.log(err)
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if(param.type === "historyBpmn") { // bpmn历史
|
||||
$('.item').hide()
|
||||
$('.download').show()
|
||||
}
|
||||
// 点击新增
|
||||
$('#js-download-diagram').on("click", function () {
|
||||
tools.syopen('alert')
|
||||
})
|
||||
|
||||
// 点击取消
|
||||
$('.cancel').on("click",function () {
|
||||
tools.syhide('alert')
|
||||
})
|
||||
// 点击确定
|
||||
$('#sure').on('click',function(){
|
||||
// const text=$("#deploymentName").val()
|
||||
tools.saveBpmn(bpmnModeler)
|
||||
})
|
||||
|
||||
|
||||
|
||||
// 点击下载
|
||||
$("#downloadBpmn").on("click", function () {
|
||||
tools.downLoad(bpmnModeler)
|
||||
})
|
||||
// 点击上传
|
||||
$("#uploadFile").on("change", function () {
|
||||
tools.upload(bpmnModeler,container)
|
||||
})
|
||||
});
|
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "bpmn-js-example-properties-panel",
|
||||
"version": "0.0.0",
|
||||
"description": "A bpmn-js modeler + properties panel example",
|
||||
"main": "app/index.js",
|
||||
"scripts": {
|
||||
"all": "grunt",
|
||||
"dev": "grunt auto-build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bpmn-io/bpmn-js-examples"
|
||||
},
|
||||
"keywords": [
|
||||
"bpmnjs-example"
|
||||
],
|
||||
"author": {
|
||||
"name": "Nico Rehwaldt",
|
||||
"url": "https://github.com/nikku"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "bpmn.io contributors",
|
||||
"url": "https://github.com/bpmn-io"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"esmify": "^2.1.1",
|
||||
"grunt": "^1.0.4",
|
||||
"grunt-browserify": "^5.3.0",
|
||||
"grunt-contrib-connect": "^2.0.0",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-less": "^2.0.0",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"load-grunt-tasks": "^5.0.0",
|
||||
"stringify": "^5.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bpmn-js": "^7.0.0",
|
||||
"bpmn-js-properties-panel": "^0.32.0",
|
||||
"camunda-bpmn-moddle": "^4.0.1",
|
||||
"diagram-js": "^5.0.0",
|
||||
"jquery": "^3.4.1",
|
||||
"min-dash": "^3.5.0",
|
||||
"x2js": "^3.4.0"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,76 @@
|
||||
export default class CustomContextPad {
|
||||
constructor(config, contextPad, create, elementFactory, injector, translate) {
|
||||
this.create = create;
|
||||
this.elementFactory = elementFactory;
|
||||
this.translate = translate;
|
||||
//自动摆放位置
|
||||
if (config.autoPlace !== false) {
|
||||
this.autoPlace = injector.get('autoPlace', false);
|
||||
}
|
||||
//注册工具
|
||||
contextPad.registerProvider(this);
|
||||
}
|
||||
getContextPadEntries(element) {
|
||||
const {
|
||||
autoPlace,
|
||||
create,
|
||||
elementFactory,
|
||||
translate
|
||||
} = this;
|
||||
|
||||
function appendUserTask(event, element) {
|
||||
if (autoPlace) {
|
||||
const shape = elementFactory.createShape({ type: 'bpmn:UserTask' });
|
||||
autoPlace.append(element, shape);
|
||||
} else {
|
||||
appendUserTaskStart(event, element);
|
||||
}
|
||||
}
|
||||
|
||||
function appendUserTaskStart(event) {
|
||||
const shape = elementFactory.createShape({ type: 'bpmn:UserTask' });
|
||||
create.start(event, shape, element);
|
||||
}
|
||||
function appendCallActivityStart(event) {
|
||||
const shape = elementFactory.createShape({ type: 'bpmn:CallActivity' });
|
||||
create.start(event, shape, element);
|
||||
}
|
||||
|
||||
function appendCallActivity(event, element) {
|
||||
if (autoPlace) {
|
||||
const shape = elementFactory.createShape({ type: 'bpmn:CallActivity' });
|
||||
autoPlace.append(element, shape);
|
||||
} else {
|
||||
appendCallActivityStart(event, element);
|
||||
}
|
||||
}
|
||||
return {
|
||||
'append.user-task': {
|
||||
group: 'model',
|
||||
className: 'bpmn-icon-user-task',
|
||||
title: translate('Append ServiceTask'),
|
||||
action: {
|
||||
click: appendUserTask,
|
||||
dragstart: appendUserTaskStart
|
||||
}
|
||||
},
|
||||
'append.call-activity':{
|
||||
group: 'model',
|
||||
className: 'bpmn-icon-call-activity',
|
||||
title: translate('Append CallActivity'),
|
||||
action: {
|
||||
click: appendCallActivity,
|
||||
dragstart: appendCallActivityStart
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
CustomContextPad.$inject = [
|
||||
'config',
|
||||
'contextPad',
|
||||
'create',
|
||||
'elementFactory',
|
||||
'injector',
|
||||
'translate'
|
||||
];
|
@ -0,0 +1,54 @@
|
||||
export default class CustomPalette {
|
||||
constructor(create, elementFactory, palette, translate) {
|
||||
this.create = create;
|
||||
this.elementFactory = elementFactory;
|
||||
this.translate = translate;
|
||||
palette.registerProvider(this);
|
||||
}
|
||||
|
||||
getPaletteEntries(element) {
|
||||
const {
|
||||
create,
|
||||
elementFactory,
|
||||
translate
|
||||
} = this;
|
||||
|
||||
function createServiceTask(event) {
|
||||
const shape = elementFactory.createShape({ type: 'bpmn:UserTask' });
|
||||
create.start(event, shape);
|
||||
}
|
||||
function createCallActivity(event) {
|
||||
const shape = elementFactory.createShape({ type: 'bpmn:CallActivity' });
|
||||
create.start(event, shape);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
'create.user-task': {
|
||||
group: 'activity',
|
||||
className: 'bpmn-icon-user-task',
|
||||
title: translate('Create UserTask'),
|
||||
action: {
|
||||
dragstart: createServiceTask,
|
||||
click: createServiceTask
|
||||
}
|
||||
},
|
||||
'create.call-activity': {
|
||||
group: 'activity',
|
||||
className: 'bpmn-icon-call-activity',
|
||||
title: translate('Create CallActivity'),
|
||||
action: {
|
||||
dragstart: createCallActivity,
|
||||
click: createCallActivity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomPalette.$inject = [
|
||||
'create',
|
||||
'elementFactory',
|
||||
'palette',
|
||||
'translate'
|
||||
];
|
@ -0,0 +1,8 @@
|
||||
import CustomContextPad from './CustomContextPad';
|
||||
import CustomPalette from './CustomPalette';
|
||||
|
||||
export default {
|
||||
__init__: [ 'customContextPad', 'customPalette' ],
|
||||
customContextPad: [ 'type', CustomContextPad ],
|
||||
customPalette: [ 'type', CustomPalette ]
|
||||
};
|
@ -0,0 +1,12 @@
|
||||
import translations from './translationsGerman';
|
||||
export default function customTranslate(template, replacements) {
|
||||
replacements = replacements || {};
|
||||
template = translations[template] || template;
|
||||
return template.replace(/{([^}]+)}/g, function(_, key) {
|
||||
var str = replacements[key];
|
||||
if(translations[replacements[key]] != null && translations [replacements[key]] != 'undefined'){
|
||||
str = translations[replacements[key]];
|
||||
}
|
||||
return str || '{' + key + '}';
|
||||
});
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://activiti.org/bpmn">
|
||||
<bpmn2:process id="Process_1" isExecutable="true">
|
||||
<bpmn2:startEvent id="StartEvent_1"/>
|
||||
</bpmn2:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds height="36.0" width="36.0" x="412.0" y="240.0"/>
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
@ -0,0 +1,67 @@
|
||||
'use strict';
|
||||
|
||||
var DEFAULT_PRIORITY = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* A component that decides upon the visibility / editable
|
||||
* state of properties in the properties panel.
|
||||
*
|
||||
* Implementors must subclass this component and override
|
||||
* {@link PropertiesActivator#isEntryVisible} and
|
||||
* {@link PropertiesActivator#isPropertyEditable} to provide
|
||||
* custom behavior.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
*
|
||||
* @param {EventBus} eventBus
|
||||
* @param {Number} [priority] at which priority to hook into the activation
|
||||
*/
|
||||
function PropertiesActivator(eventBus, priority) {
|
||||
var self = this;
|
||||
|
||||
priority = priority || DEFAULT_PRIORITY;
|
||||
|
||||
eventBus.on('propertiesPanel.isEntryVisible', priority, function(e) {
|
||||
return self.isEntryVisible(e.entry, e.element);
|
||||
});
|
||||
|
||||
eventBus.on('propertiesPanel.isPropertyEditable', priority, function(e) {
|
||||
return self.isPropertyEditable(e.entry, e.propertyName, e.element);
|
||||
});
|
||||
}
|
||||
|
||||
PropertiesActivator.$inject = [ 'eventBus' ];
|
||||
|
||||
module.exports = PropertiesActivator;
|
||||
|
||||
|
||||
/**
|
||||
* Should the given entry be visible for the specified element.
|
||||
*
|
||||
* @method PropertiesActivator#isEntryVisible
|
||||
*
|
||||
* @param {EntryDescriptor} entry
|
||||
* @param {ModdleElement} element
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
PropertiesActivator.prototype.isEntryVisible = function(entry, element) {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Should the given property be editable for the specified element
|
||||
*
|
||||
* @method PropertiesActivator#isPropertyEditable
|
||||
*
|
||||
* @param {EntryDescriptor} entry
|
||||
* @param {String} propertyName
|
||||
* @param {ModdleElement} element
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
PropertiesActivator.prototype.isPropertyEditable = function(entry, propertyName, element) {
|
||||
return true;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,252 @@
|
||||
'use strict';
|
||||
|
||||
var domQuery = require('min-dom').query,
|
||||
domClear = require('min-dom').clear,
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
forEach = require('lodash/forEach'),
|
||||
domify = require('min-dom').domify,
|
||||
Ids = require('ids').default;
|
||||
|
||||
var SPACE_REGEX = /\s/;
|
||||
|
||||
// for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar
|
||||
var QNAME_REGEX = /^([a-z][\w-.]*:)?[a-z_][\w-.]*$/i;
|
||||
|
||||
// for ID validation as per BPMN Schema (QName - Namespace)
|
||||
var ID_REGEX = /^[a-z_][\w-.]*$/i;
|
||||
|
||||
var PLACEHOLDER_REGEX = /\$\{([^}]*)\}/g;
|
||||
|
||||
var HTML_ESCAPE_MAP = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': '''
|
||||
};
|
||||
|
||||
function selectedOption(selectBox) {
|
||||
if (selectBox.selectedIndex >= 0) {
|
||||
return selectBox.options[selectBox.selectedIndex].value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.selectedOption = selectedOption;
|
||||
|
||||
|
||||
function selectedType(elementSyntax, inputNode) {
|
||||
var typeSelect = domQuery(elementSyntax, inputNode);
|
||||
return selectedOption(typeSelect);
|
||||
}
|
||||
|
||||
module.exports.selectedType = selectedType;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the root element the document this
|
||||
* business object is contained in.
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function getRoot(businessObject) {
|
||||
var parent = businessObject;
|
||||
while (parent.$parent) {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
module.exports.getRoot = getRoot;
|
||||
|
||||
|
||||
/**
|
||||
* filters all elements in the list which have a given type.
|
||||
* removes a new list
|
||||
*/
|
||||
function filterElementsByType(objectList, type) {
|
||||
var list = objectList || [];
|
||||
var result = [];
|
||||
forEach(list, function(obj) {
|
||||
if (is(obj, type)) {
|
||||
result.push(obj);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports.filterElementsByType = filterElementsByType;
|
||||
|
||||
|
||||
function findRootElementsByType(businessObject, referencedType) {
|
||||
var root = getRoot(businessObject);
|
||||
|
||||
return filterElementsByType(root.rootElements, referencedType);
|
||||
}
|
||||
|
||||
module.exports.findRootElementsByType = findRootElementsByType;
|
||||
|
||||
|
||||
function removeAllChildren(domElement) {
|
||||
while (domElement.firstChild) {
|
||||
domElement.removeChild(domElement.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.removeAllChildren = removeAllChildren;
|
||||
|
||||
|
||||
/**
|
||||
* adds an empty option to the list
|
||||
*/
|
||||
function addEmptyParameter(list) {
|
||||
return list.push({ 'label': '', 'value': '', 'name': '' });
|
||||
}
|
||||
|
||||
module.exports.addEmptyParameter = addEmptyParameter;
|
||||
|
||||
|
||||
/**
|
||||
* returns a list with all root elements for the given parameter 'referencedType'
|
||||
*/
|
||||
function refreshOptionsModel(businessObject, referencedType) {
|
||||
var model = [];
|
||||
var referableObjects = findRootElementsByType(businessObject, referencedType);
|
||||
forEach(referableObjects, function(obj) {
|
||||
model.push({
|
||||
label: (obj.name || '') + ' (id='+obj.id+')',
|
||||
value: obj.id,
|
||||
name: obj.name
|
||||
});
|
||||
});
|
||||
return model;
|
||||
}
|
||||
|
||||
module.exports.refreshOptionsModel = refreshOptionsModel;
|
||||
|
||||
|
||||
/**
|
||||
* fills the drop down with options
|
||||
*/
|
||||
function updateOptionsDropDown(domSelector, businessObject, referencedType, entryNode) {
|
||||
var options = refreshOptionsModel(businessObject, referencedType);
|
||||
addEmptyParameter(options);
|
||||
var selectBox = domQuery(domSelector, entryNode);
|
||||
domClear(selectBox);
|
||||
|
||||
forEach(options, function(option) {
|
||||
var optionEntry = domify('<option value="' + escapeHTML(option.value) + '">' + escapeHTML(option.label) + '</option>');
|
||||
selectBox.appendChild(optionEntry);
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
module.exports.updateOptionsDropDown = updateOptionsDropDown;
|
||||
|
||||
|
||||
/**
|
||||
* checks whether the id value is valid
|
||||
*
|
||||
* @param {ModdleElement} bo
|
||||
* @param {String} idValue
|
||||
* @param {Function} translate
|
||||
*
|
||||
* @return {String} error message
|
||||
*/
|
||||
function isIdValid(bo, idValue, translate) {
|
||||
var assigned = bo.$model.ids.assigned(idValue);
|
||||
|
||||
var idExists = assigned && assigned !== bo;
|
||||
|
||||
if (!idValue || idExists) {
|
||||
return translate('Element must have an unique id.');
|
||||
}
|
||||
|
||||
return validateId(idValue, translate);
|
||||
}
|
||||
|
||||
module.exports.isIdValid = isIdValid;
|
||||
|
||||
|
||||
function validateId(idValue, translate) {
|
||||
|
||||
idValue = stripPlaceholders(idValue);
|
||||
|
||||
if (containsSpace(idValue)) {
|
||||
return translate('Id must not contain spaces.');
|
||||
}
|
||||
|
||||
if (!ID_REGEX.test(idValue)) {
|
||||
|
||||
if (QNAME_REGEX.test(idValue)) {
|
||||
return translate('Id must not contain prefix.');
|
||||
}
|
||||
|
||||
return translate('Id must be a valid QName.');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.validateId = validateId;
|
||||
|
||||
|
||||
function containsSpace(value) {
|
||||
return SPACE_REGEX.test(value);
|
||||
}
|
||||
|
||||
module.exports.containsSpace = containsSpace;
|
||||
|
||||
|
||||
function stripPlaceholders(idValue) {
|
||||
|
||||
// replace expression e.g. ${VERSION_TAG}
|
||||
// use only the content between ${}
|
||||
// for the REGEX check
|
||||
return idValue.replace(PLACEHOLDER_REGEX, '$1');
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a semantic id with given prefix
|
||||
*/
|
||||
function nextId(prefix) {
|
||||
var ids = new Ids([32,32,1]);
|
||||
|
||||
return ids.nextPrefixed(prefix);
|
||||
}
|
||||
|
||||
module.exports.nextId = nextId;
|
||||
|
||||
|
||||
function triggerClickEvent(element) {
|
||||
var evt;
|
||||
var eventType = 'click';
|
||||
|
||||
if (document.createEvent) {
|
||||
try {
|
||||
// Chrome, Safari, Firefox
|
||||
evt = new MouseEvent((eventType), { view: window, bubbles: true, cancelable: true });
|
||||
} catch (e) {
|
||||
// IE 11, PhantomJS (wat!)
|
||||
evt = document.createEvent('MouseEvent');
|
||||
|
||||
evt.initEvent((eventType), true, true);
|
||||
}
|
||||
return element.dispatchEvent(evt);
|
||||
} else {
|
||||
// Welcome IE
|
||||
evt = document.createEventObject();
|
||||
|
||||
return element.fireEvent('on' + eventType, evt);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.triggerClickEvent = triggerClickEvent;
|
||||
|
||||
|
||||
function escapeHTML(str) {
|
||||
str = '' + str;
|
||||
|
||||
return str && str.replace(/[&<>"']/g, function(match) {
|
||||
return HTML_ESCAPE_MAP[match];
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.escapeHTML = escapeHTML;
|
@ -0,0 +1,101 @@
|
||||
'use strict';
|
||||
|
||||
var elementHelper = require('../helper/ElementHelper');
|
||||
|
||||
/**
|
||||
* A handler capable of creating a new element under a provided parent
|
||||
* and updating / creating a reference to it in one atomic action.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
*/
|
||||
function CreateAndReferenceElementHandler(elementRegistry, bpmnFactory) {
|
||||
this._elementRegistry = elementRegistry;
|
||||
this._bpmnFactory = bpmnFactory;
|
||||
}
|
||||
|
||||
CreateAndReferenceElementHandler.$inject = [ 'elementRegistry', 'bpmnFactory' ];
|
||||
|
||||
module.exports = CreateAndReferenceElementHandler;
|
||||
|
||||
|
||||
// api ////////////////////
|
||||
|
||||
/**
|
||||
* Creates a new element under a provided parent and updates / creates a reference to it in
|
||||
* one atomic action.
|
||||
*
|
||||
* @method CreateAndReferenceElementHandler#execute
|
||||
*
|
||||
* @param {Object} context
|
||||
* @param {djs.model.Base} context.element which is the context for the reference
|
||||
* @param {moddle.referencingObject} context.referencingObject the object which creates the reference
|
||||
* @param {String} context.referenceProperty the property of the referencingObject which makes the reference
|
||||
* @param {moddle.newObject} context.newObject the new object to add
|
||||
* @param {moddle.newObjectContainer} context.newObjectContainer the container for the new object
|
||||
*
|
||||
* @returns {Array<djs.mode.Base>} the updated element
|
||||
*/
|
||||
CreateAndReferenceElementHandler.prototype.execute = function(context) {
|
||||
|
||||
var referencingObject = ensureNotNull(context.referencingObject, 'referencingObject'),
|
||||
referenceProperty = ensureNotNull(context.referenceProperty, 'referenceProperty'),
|
||||
newObject = ensureNotNull(context.newObject, 'newObject'),
|
||||
newObjectContainer = ensureNotNull(context.newObjectContainer, 'newObjectContainer'),
|
||||
newObjectParent = ensureNotNull(context.newObjectParent, 'newObjectParent'),
|
||||
changed = [ context.element ]; // this will not change any diagram-js elements
|
||||
|
||||
// create new object
|
||||
var referencedObject = elementHelper
|
||||
.createElement(newObject.type, newObject.properties, newObjectParent, this._bpmnFactory);
|
||||
context.referencedObject = referencedObject;
|
||||
|
||||
// add to containing list
|
||||
newObjectContainer.push(referencedObject);
|
||||
|
||||
// adjust reference attribute
|
||||
context.previousReference = referencingObject[referenceProperty];
|
||||
referencingObject[referenceProperty] = referencedObject;
|
||||
|
||||
context.changed = changed;
|
||||
|
||||
// indicate changed on objects affected by the update
|
||||
return changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts the update
|
||||
*
|
||||
* @method CreateAndReferenceElementHandler#revert
|
||||
*
|
||||
* @param {Object} context
|
||||
*
|
||||
* @returns {djs.mode.Base} the updated element
|
||||
*/
|
||||
CreateAndReferenceElementHandler.prototype.revert = function(context) {
|
||||
|
||||
var referencingObject = context.referencingObject,
|
||||
referenceProperty = context.referenceProperty,
|
||||
previousReference = context.previousReference,
|
||||
referencedObject = context.referencedObject,
|
||||
newObjectContainer = context.newObjectContainer;
|
||||
|
||||
// reset reference
|
||||
referencingObject.set(referenceProperty, previousReference);
|
||||
|
||||
// remove new element
|
||||
newObjectContainer.splice(newObjectContainer.indexOf(referencedObject), 1);
|
||||
|
||||
return context.changed;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// helpers //////////////
|
||||
|
||||
function ensureNotNull(prop, name) {
|
||||
if (!prop) {
|
||||
throw new Error(name + ' required');
|
||||
}
|
||||
return prop;
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
'use strict';
|
||||
|
||||
var forEach = require('lodash/forEach');
|
||||
|
||||
var elementHelper = require('../helper/ElementHelper');
|
||||
|
||||
/**
|
||||
* A handler that implements a BPMN 2.0 property update
|
||||
* for business objects which are not represented in the
|
||||
* diagram.
|
||||
*
|
||||
* This is useful in the context of the properties panel in
|
||||
* order to update child elements of elements visible in
|
||||
* the diagram.
|
||||
*
|
||||
* Example: perform an update of a specific event definition
|
||||
* of an intermediate event.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
*/
|
||||
function CreateBusinessObjectListHandler(elementRegistry, bpmnFactory) {
|
||||
this._elementRegistry = elementRegistry;
|
||||
this._bpmnFactory = bpmnFactory;
|
||||
}
|
||||
|
||||
CreateBusinessObjectListHandler.$inject = [ 'elementRegistry', 'bpmnFactory' ];
|
||||
|
||||
module.exports = CreateBusinessObjectListHandler;
|
||||
|
||||
function ensureNotNull(prop, name) {
|
||||
if (!prop) {
|
||||
throw new Error(name + ' required');
|
||||
}
|
||||
return prop;
|
||||
|
||||
}
|
||||
function ensureList(prop, name) {
|
||||
if (!prop || Object.prototype.toString.call(prop) !== '[object Array]') {
|
||||
throw new Error(name + ' needs to be a list');
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
// api /////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a new element under a provided parent and updates / creates a reference to it in
|
||||
* one atomic action.
|
||||
*
|
||||
* @method CreateBusinessObjectListHandler#execute
|
||||
*
|
||||
* @param {Object} context
|
||||
* @param {djs.model.Base} context.element which is the context for the reference
|
||||
* @param {moddle.referencingObject} context.referencingObject the object which creates the reference
|
||||
* @param {String} context.referenceProperty the property of the referencingObject which makes the reference
|
||||
* @param {moddle.newObject} context.newObject the new object to add
|
||||
* @param {moddle.newObjectContainer} context.newObjectContainer the container for the new object
|
||||
*
|
||||
* @return {Array<djs.mode.Base>} the updated element
|
||||
*/
|
||||
CreateBusinessObjectListHandler.prototype.execute = function(context) {
|
||||
|
||||
var currentObject = ensureNotNull(context.currentObject, 'currentObject'),
|
||||
propertyName = ensureNotNull(context.propertyName, 'propertyName'),
|
||||
newObjects = ensureList(context.newObjects, 'newObjects'),
|
||||
changed = [ context.element ]; // this will not change any diagram-js elements
|
||||
|
||||
|
||||
var childObjects = [];
|
||||
var self = this;
|
||||
|
||||
// create new array of business objects
|
||||
forEach(newObjects, function(obj) {
|
||||
var element = elementHelper.createElement(obj.type, obj.properties, currentObject, self._bpmnFactory);
|
||||
|
||||
childObjects.push(element);
|
||||
});
|
||||
context.childObject = childObjects;
|
||||
|
||||
// adjust array reference in the parent business object
|
||||
context.previousChilds = currentObject[propertyName];
|
||||
currentObject[propertyName] = childObjects;
|
||||
|
||||
context.changed = changed;
|
||||
|
||||
// indicate changed on objects affected by the update
|
||||
return changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts the update
|
||||
*
|
||||
* @method CreateBusinessObjectListHandler#revert
|
||||
*
|
||||
* @param {Object} context
|
||||
*
|
||||
* @return {djs.mode.Base} the updated element
|
||||
*/
|
||||
CreateBusinessObjectListHandler.prototype.revert = function(context) {
|
||||
|
||||
var currentObject = context.currentObject,
|
||||
propertyName = context.propertyName,
|
||||
previousChilds = context.previousChilds;
|
||||
|
||||
// remove new element
|
||||
currentObject.set(propertyName, previousChilds);
|
||||
|
||||
return context.changed;
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
var forEach = require('lodash/forEach');
|
||||
|
||||
/**
|
||||
* A handler that combines and executes multiple commands.
|
||||
*
|
||||
* All updates are bundled on the command stack and executed in one step.
|
||||
* This also makes it possible to revert the changes in one step.
|
||||
*
|
||||
* Example use case: remove the camunda:formKey attribute and in addition
|
||||
* add all form fields needed for the camunda:formData property.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
*/
|
||||
function MultiCommandHandler(commandStack) {
|
||||
this._commandStack = commandStack;
|
||||
}
|
||||
|
||||
MultiCommandHandler.$inject = [ 'commandStack' ];
|
||||
|
||||
module.exports = MultiCommandHandler;
|
||||
|
||||
MultiCommandHandler.prototype.preExecute = function(context) {
|
||||
|
||||
var commandStack = this._commandStack;
|
||||
|
||||
forEach(context, function(command) {
|
||||
commandStack.execute(command.cmd, command.context);
|
||||
});
|
||||
};
|
@ -0,0 +1,131 @@
|
||||
'use strict';
|
||||
|
||||
var reduce = require('lodash/transform'),
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
keys = require('lodash/keys'),
|
||||
forEach = require('lodash/forEach');
|
||||
|
||||
/**
|
||||
* A handler that implements a BPMN 2.0 property update
|
||||
* for business objects which are not represented in the
|
||||
* diagram.
|
||||
*
|
||||
* This is useful in the context of the properties panel in
|
||||
* order to update child elements of elements visible in
|
||||
* the diagram.
|
||||
*
|
||||
* Example: perform an update of a specific event definition
|
||||
* of an intermediate event.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
*/
|
||||
function UpdateBusinessObjectHandler(elementRegistry) {
|
||||
this._elementRegistry = elementRegistry;
|
||||
}
|
||||
|
||||
UpdateBusinessObjectHandler.$inject = [ 'elementRegistry' ];
|
||||
|
||||
module.exports = UpdateBusinessObjectHandler;
|
||||
|
||||
/**
|
||||
* returns the root element
|
||||
*/
|
||||
function getRoot(businessObject) {
|
||||
var parent = businessObject;
|
||||
while (parent.$parent) {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
function getProperties(businessObject, propertyNames) {
|
||||
return reduce(propertyNames, function(result, key) {
|
||||
result[key] = businessObject.get(key);
|
||||
return result;
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
function setProperties(businessObject, properties) {
|
||||
forEach(properties, function(value, key) {
|
||||
businessObject.set(key, value);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// api /////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Updates a business object with a list of new properties
|
||||
*
|
||||
* @method UpdateBusinessObjectHandler#execute
|
||||
*
|
||||
* @param {Object} context
|
||||
* @param {djs.model.Base} context.element the element which has a child business object updated
|
||||
* @param {moddle.businessObject} context.businessObject the businessObject to update
|
||||
* @param {Object} context.properties a list of properties to set on the businessObject
|
||||
*
|
||||
* @return {Array<djs.mode.Base>} the updated element
|
||||
*/
|
||||
UpdateBusinessObjectHandler.prototype.execute = function(context) {
|
||||
|
||||
var element = context.element,
|
||||
businessObject = context.businessObject,
|
||||
rootElements = getRoot(businessObject).rootElements,
|
||||
referenceType = context.referenceType,
|
||||
referenceProperty = context.referenceProperty,
|
||||
changed = [ element ]; // this will not change any diagram-js elements
|
||||
|
||||
if (!element) {
|
||||
throw new Error('element required');
|
||||
}
|
||||
|
||||
if (!businessObject) {
|
||||
throw new Error('businessObject required');
|
||||
}
|
||||
|
||||
var properties = context.properties,
|
||||
oldProperties = context.oldProperties || getProperties(businessObject, keys(properties));
|
||||
|
||||
// check if there the update needs an external element for reference
|
||||
if (typeof referenceType !== 'undefined' && typeof referenceProperty !== 'undefined') {
|
||||
forEach(rootElements, function(rootElement) {
|
||||
if (is(rootElement, referenceType)) {
|
||||
if (rootElement.id === properties[referenceProperty]) {
|
||||
properties[referenceProperty] = rootElement;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// update properties
|
||||
setProperties(businessObject, properties);
|
||||
|
||||
// store old values
|
||||
context.oldProperties = oldProperties;
|
||||
context.changed = changed;
|
||||
|
||||
// indicate changed on objects affected by the update
|
||||
return changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts the update
|
||||
*
|
||||
* @method UpdateBusinessObjectHandler#revert
|
||||
*
|
||||
* @param {Object} context
|
||||
*
|
||||
* @return {djs.mode.Base} the updated element
|
||||
*/
|
||||
UpdateBusinessObjectHandler.prototype.revert = function(context) {
|
||||
|
||||
var oldProperties = context.oldProperties,
|
||||
businessObject = context.businessObject;
|
||||
|
||||
// update properties
|
||||
setProperties(businessObject, oldProperties);
|
||||
|
||||
return context.changed;
|
||||
};
|
@ -0,0 +1,115 @@
|
||||
'use strict';
|
||||
|
||||
var forEach = require('lodash/forEach');
|
||||
|
||||
/**
|
||||
* A handler that implements a BPMN 2.0 property update
|
||||
* for business object lists which are not represented in the
|
||||
* diagram.
|
||||
*
|
||||
* This is useful in the context of the properties panel in
|
||||
* order to update child elements of elements visible in
|
||||
* the diagram.
|
||||
*
|
||||
* Example: perform an update of a specific event definition
|
||||
* of an intermediate event.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
*/
|
||||
function UpdateBusinessObjectListHandler(elementRegistry, bpmnFactory) {
|
||||
this._elementRegistry = elementRegistry;
|
||||
this._bpmnFactory = bpmnFactory;
|
||||
}
|
||||
|
||||
UpdateBusinessObjectListHandler.$inject = [ 'elementRegistry', 'bpmnFactory' ];
|
||||
|
||||
module.exports = UpdateBusinessObjectListHandler;
|
||||
|
||||
function ensureNotNull(prop, name) {
|
||||
if (!prop) {
|
||||
throw new Error(name + 'required');
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
// api /////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Updates a element under a provided parent.
|
||||
*/
|
||||
UpdateBusinessObjectListHandler.prototype.execute = function(context) {
|
||||
|
||||
var currentObject = ensureNotNull(context.currentObject, 'currentObject'),
|
||||
propertyName = ensureNotNull(context.propertyName, 'propertyName'),
|
||||
updatedObjectList = context.updatedObjectList,
|
||||
objectsToRemove = context.objectsToRemove || [],
|
||||
objectsToAdd = context.objectsToAdd || [],
|
||||
changed = [ context.element], // this will not change any diagram-js elements
|
||||
referencePropertyName;
|
||||
|
||||
if (context.referencePropertyName) {
|
||||
referencePropertyName = context.referencePropertyName;
|
||||
}
|
||||
|
||||
var objectList = currentObject[propertyName];
|
||||
// adjust array reference in the parent business object
|
||||
context.previousList = currentObject[propertyName];
|
||||
|
||||
if (updatedObjectList) {
|
||||
currentObject[propertyName] = updatedObjectList;
|
||||
} else {
|
||||
var listCopy = [];
|
||||
// remove all objects which should be removed
|
||||
forEach(objectList, function(object) {
|
||||
if (objectsToRemove.indexOf(object) == -1) {
|
||||
listCopy.push(object);
|
||||
}
|
||||
});
|
||||
// add all objects which should be added
|
||||
listCopy = listCopy.concat(objectsToAdd);
|
||||
|
||||
// set property to new list
|
||||
if (listCopy.length > 0 || !referencePropertyName) {
|
||||
|
||||
// as long as there are elements in the list update the list
|
||||
currentObject[propertyName] = listCopy;
|
||||
} else if (referencePropertyName) {
|
||||
|
||||
// remove the list when it is empty
|
||||
var parentObject = currentObject.$parent;
|
||||
parentObject.set(referencePropertyName, undefined);
|
||||
}
|
||||
}
|
||||
|
||||
context.changed = changed;
|
||||
|
||||
// indicate changed on objects affected by the update
|
||||
return changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts the update
|
||||
*
|
||||
* @method CreateBusinessObjectListHandler#revert
|
||||
*
|
||||
* @param {Object} context
|
||||
*
|
||||
* @return {djs.mode.Base} the updated element
|
||||
*/
|
||||
UpdateBusinessObjectListHandler.prototype.revert = function(context) {
|
||||
|
||||
var currentObject = context.currentObject,
|
||||
propertyName = context.propertyName,
|
||||
previousList = context.previousList,
|
||||
parentObject = currentObject.$parent;
|
||||
|
||||
if (context.referencePropertyName) {
|
||||
parentObject.set(context.referencePropertyName, currentObject);
|
||||
}
|
||||
|
||||
// remove new element
|
||||
currentObject.set(propertyName, previousList);
|
||||
|
||||
return context.changed;
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
var forEach = require('lodash/forEach');
|
||||
|
||||
var HANDLERS = {
|
||||
'properties-panel.update-businessobject': require('./UpdateBusinessObjectHandler'),
|
||||
'properties-panel.create-and-reference': require('./CreateAndReferenceHandler'),
|
||||
'properties-panel.create-businessobject-list': require('./CreateBusinessObjectListHandler'),
|
||||
'properties-panel.update-businessobject-list': require('./UpdateBusinessObjectListHandler'),
|
||||
'properties-panel.multi-command-executor': require('./MultiCommandHandler')
|
||||
};
|
||||
|
||||
|
||||
function CommandInitializer(eventBus, commandStack) {
|
||||
|
||||
eventBus.on('diagram.init', function() {
|
||||
forEach(HANDLERS, function(handler, id) {
|
||||
commandStack.registerHandler(id, handler);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
CommandInitializer.$inject = [ 'eventBus', 'commandStack' ];
|
||||
|
||||
module.exports = {
|
||||
__init__: [ CommandInitializer ]
|
||||
};
|
@ -0,0 +1,77 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
cmdHelper = require('../helper/CmdHelper'),
|
||||
escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
var entryFieldDescription = require('./EntryFieldDescription');
|
||||
|
||||
|
||||
var checkbox = function(options, defaultParameters) {
|
||||
var resource = defaultParameters,
|
||||
id = resource.id,
|
||||
label = options.label || id,
|
||||
canBeDisabled = !!options.disabled && typeof options.disabled === 'function',
|
||||
canBeHidden = !!options.hidden && typeof options.hidden === 'function',
|
||||
description = options.description;
|
||||
|
||||
resource.html =
|
||||
'<input id="activiti-' + escapeHTML(id) + '" ' +
|
||||
'type="checkbox" ' +
|
||||
'name="' + escapeHTML(options.modelProperty) + '" ' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled"' : '') +
|
||||
(canBeHidden ? 'data-show="isHidden"' : '') +
|
||||
' />' +
|
||||
'<label for="activiti-' + escapeHTML(id) + '" ' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled"' : '') +
|
||||
(canBeHidden ? 'data-show="isHidden"' : '') +
|
||||
'>' + escapeHTML(label) + '</label>';
|
||||
|
||||
// add description below checkbox entry field
|
||||
if (description) {
|
||||
resource.html += entryFieldDescription(description);
|
||||
}
|
||||
|
||||
resource.get = function(element) {
|
||||
var bo = getBusinessObject(element),
|
||||
res = {};
|
||||
|
||||
res[options.modelProperty] = bo.get(options.modelProperty);
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
resource.set = function(element, values) {
|
||||
var res = {};
|
||||
|
||||
res[options.modelProperty] = !!values[options.modelProperty];
|
||||
|
||||
return cmdHelper.updateProperties(element, res);
|
||||
};
|
||||
|
||||
if (typeof options.set === 'function') {
|
||||
resource.set = options.set;
|
||||
}
|
||||
|
||||
if (typeof options.get === 'function') {
|
||||
resource.get = options.get;
|
||||
}
|
||||
|
||||
if (canBeDisabled) {
|
||||
resource.isDisabled = function() {
|
||||
return options.disabled.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
if (canBeHidden) {
|
||||
resource.isHidden = function() {
|
||||
return !options.hidden.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
resource.cssClasses = ['bpp-checkbox'];
|
||||
|
||||
return resource;
|
||||
};
|
||||
|
||||
module.exports = checkbox;
|
@ -0,0 +1,118 @@
|
||||
'use strict';
|
||||
|
||||
var assign = require('lodash/assign'),
|
||||
find = require('lodash/find');
|
||||
|
||||
var domQuery = require('min-dom').query;
|
||||
|
||||
var escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
var selectEntryFactory = require('./SelectEntryFactory'),
|
||||
entryFieldDescription = require('./EntryFieldDescription');
|
||||
|
||||
|
||||
/**
|
||||
* The combo box is a special implementation of the select entry and adds the option 'custom' to the
|
||||
* select box. If 'custom' is selected, an additional text input field is shown which allows to define
|
||||
* a custom value.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {string} options.id
|
||||
* @param {string} options.label
|
||||
* @param {Array<Object>} options.selectOptions list of name/value pairs
|
||||
* @param {string} options.modelProperty
|
||||
* @param {function} options.get
|
||||
* @param {function} options.set
|
||||
* @param {string} [options.customValue] custom select option value (default: 'custom')
|
||||
* @param {string} [options.customName] custom select option name visible in the select box (default: 'custom')
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
var comboBox = function(options) {
|
||||
|
||||
var selectOptions = options.selectOptions,
|
||||
modelProperty = options.modelProperty,
|
||||
customValue = options.customValue || 'custom',
|
||||
customName = options.customName || 'custom ' + modelProperty,
|
||||
description = options.description;
|
||||
|
||||
// check if a value is not a built in value
|
||||
var isCustomValue = function(value) {
|
||||
if (typeof value[modelProperty] === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
|
||||
var isCustom = !find(selectOptions, function(option) {
|
||||
return value[modelProperty] === option.value;
|
||||
});
|
||||
|
||||
return isCustom;
|
||||
};
|
||||
|
||||
var comboOptions = assign({}, options);
|
||||
|
||||
// true if the selected value in the select box is customValue
|
||||
comboOptions.showCustomInput = function(element, node) {
|
||||
var selectBox = domQuery('[data-entry="'+ options.id +'"] select', node.parentNode);
|
||||
|
||||
if (selectBox) {
|
||||
return selectBox.value === customValue;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
comboOptions.get = function(element, node) {
|
||||
var value = options.get(element, node);
|
||||
|
||||
var modifiedValues = {};
|
||||
|
||||
if (!isCustomValue(value)) {
|
||||
modifiedValues[modelProperty] = value[modelProperty] || '';
|
||||
|
||||
return modifiedValues;
|
||||
}
|
||||
|
||||
modifiedValues[modelProperty] = customValue;
|
||||
modifiedValues['custom-'+modelProperty] = value[modelProperty];
|
||||
|
||||
return modifiedValues;
|
||||
};
|
||||
|
||||
comboOptions.set = function(element, values, node) {
|
||||
var modifiedValues = {};
|
||||
|
||||
// if the custom select option has been selected
|
||||
// take the value from the text input field
|
||||
if (values[modelProperty] === customValue) {
|
||||
modifiedValues[modelProperty] = values['custom-' + modelProperty] || '';
|
||||
}
|
||||
else if (options.emptyParameter && values[modelProperty] === '') {
|
||||
modifiedValues[modelProperty] = undefined;
|
||||
} else {
|
||||
modifiedValues[modelProperty] = values[modelProperty];
|
||||
}
|
||||
return options.set(element, modifiedValues, node);
|
||||
};
|
||||
|
||||
comboOptions.selectOptions.push({ name: customName, value: customValue });
|
||||
|
||||
var comboBoxEntry = assign({}, selectEntryFactory(comboOptions, comboOptions));
|
||||
|
||||
comboBoxEntry.html += '<div class="bpp-field-wrapper bpp-combo-input" ' +
|
||||
'data-show="showCustomInput"' +
|
||||
'>' +
|
||||
'<input id="activiti-' + escapeHTML(options.id) + '-input" type="text" name="custom-' +
|
||||
escapeHTML(modelProperty) + '" ' +
|
||||
' />' +
|
||||
'</div>';
|
||||
|
||||
// add description below combo box entry field
|
||||
if (description) {
|
||||
comboBoxEntry.html += entryFieldDescription(description);
|
||||
}
|
||||
|
||||
return comboBoxEntry;
|
||||
};
|
||||
|
||||
module.exports = comboBox;
|
@ -0,0 +1,163 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
// input entities
|
||||
var textInputField = require('./TextInputEntryFactory'),
|
||||
checkboxField = require('./CheckboxEntryFactory'),
|
||||
selectBoxField = require('./SelectEntryFactory'),
|
||||
comboBoxField = require('./ComboEntryFactory'),
|
||||
textBoxField = require('./TextBoxEntryFactory'),
|
||||
validationAwareTextInputField = require('./ValidationAwareTextInput'),
|
||||
tableField = require('./TableEntryFactory'),
|
||||
labelEntry = require('./LabelFactory'),
|
||||
link = require('./LinkEntryFactory');
|
||||
|
||||
var cmdHelper = require('../helper/CmdHelper');
|
||||
|
||||
// helpers ////////////////////////////////////////
|
||||
|
||||
function ensureNotNull(prop) {
|
||||
if (!prop) {
|
||||
throw new Error(prop + ' must be set.');
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the default parameters which are needed to create an entry
|
||||
*
|
||||
* @param options
|
||||
* @returns {{id: *, description: (*|string), get: (*|Function), set: (*|Function),
|
||||
* validate: (*|Function), html: string}}
|
||||
*/
|
||||
var setDefaultParameters = function(options) {
|
||||
|
||||
// default method to fetch the current value of the input field
|
||||
var defaultGet = function(element) {
|
||||
var bo = getBusinessObject(element),
|
||||
res = {},
|
||||
prop = ensureNotNull(options.modelProperty);
|
||||
res[prop] = bo.get(prop);
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
// default method to set a new value to the input field
|
||||
var defaultSet = function(element, values) {
|
||||
var res = {},
|
||||
prop = ensureNotNull(options.modelProperty);
|
||||
if (values[prop] !== '') {
|
||||
res[prop] = values[prop];
|
||||
} else {
|
||||
res[prop] = undefined;
|
||||
}
|
||||
|
||||
return cmdHelper.updateProperties(element, res);
|
||||
};
|
||||
|
||||
// default validation method
|
||||
var defaultValidate = function() {
|
||||
return {};
|
||||
};
|
||||
|
||||
return {
|
||||
id : options.id,
|
||||
description : (options.description || ''),
|
||||
get : (options.get || defaultGet),
|
||||
set : (options.set || defaultSet),
|
||||
validate : (options.validate || defaultValidate),
|
||||
html: ''
|
||||
};
|
||||
};
|
||||
|
||||
function EntryFactory() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an text input entry object for a property panel.
|
||||
* options are:
|
||||
* - id: id of the entry - String
|
||||
*
|
||||
* - description: description of the property - String
|
||||
*
|
||||
* - label: label for the input field - String
|
||||
*
|
||||
* - set: setter method - Function
|
||||
*
|
||||
* - get: getter method - Function
|
||||
*
|
||||
* - validate: validation mehtod - Function
|
||||
*
|
||||
* - modelProperty: name of the model property - String
|
||||
*
|
||||
* - buttonAction: Object which contains the following properties: - Object
|
||||
* ---- name: name of the [data-action] callback - String
|
||||
* ---- method: callback function for [data-action] - Function
|
||||
*
|
||||
* - buttonShow: Object which contains the following properties: - Object
|
||||
* ---- name: name of the [data-show] callback - String
|
||||
* ---- method: callback function for [data-show] - Function
|
||||
*
|
||||
* @param options
|
||||
* @returns the propertyPanel entry resource object
|
||||
*/
|
||||
EntryFactory.textField = function(options) {
|
||||
return textInputField(options, setDefaultParameters(options));
|
||||
};
|
||||
|
||||
EntryFactory.validationAwareTextField = function(options) {
|
||||
return validationAwareTextInputField(options, setDefaultParameters(options));
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a checkbox input entry object for a property panel.
|
||||
* options are:
|
||||
* - id: id of the entry - String
|
||||
*
|
||||
* - description: description of the property - String
|
||||
*
|
||||
* - label: label for the input field - String
|
||||
*
|
||||
* - set: setter method - Function
|
||||
*
|
||||
* - get: getter method - Function
|
||||
*
|
||||
* - validate: validation method - Function
|
||||
*
|
||||
* - modelProperty: name of the model property - String
|
||||
*
|
||||
* @param options
|
||||
* @returns the propertyPanel entry resource object
|
||||
*/
|
||||
EntryFactory.checkbox = function(options) {
|
||||
return checkboxField(options, setDefaultParameters(options));
|
||||
};
|
||||
|
||||
EntryFactory.textBox = function(options) {
|
||||
return textBoxField(options, setDefaultParameters(options));
|
||||
};
|
||||
|
||||
EntryFactory.selectBox = function(options) {
|
||||
return selectBoxField(options, setDefaultParameters(options));
|
||||
};
|
||||
|
||||
EntryFactory.comboBox = function(options) {
|
||||
return comboBoxField(options);
|
||||
};
|
||||
|
||||
EntryFactory.table = function(options) {
|
||||
return tableField(options);
|
||||
};
|
||||
|
||||
EntryFactory.label = function(options) {
|
||||
return labelEntry(options);
|
||||
};
|
||||
|
||||
EntryFactory.link = function(options) {
|
||||
return link(options);
|
||||
};
|
||||
|
||||
module.exports = EntryFactory;
|
@ -0,0 +1,49 @@
|
||||
'use strict';
|
||||
|
||||
var escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
/**
|
||||
* Create a linkified and HTML escaped entry field description.
|
||||
*
|
||||
* As a special feature, this description may contain both markdown
|
||||
* and plain <a href> links.
|
||||
*
|
||||
* @param {String} description
|
||||
*/
|
||||
module.exports = function entryFieldDescription(description) {
|
||||
|
||||
// we tokenize the description to extract text, HTML and markdown links
|
||||
// text and links are handled seperately
|
||||
|
||||
var escaped = [];
|
||||
|
||||
// match markdown [{TEXT}]({URL}) and HTML links <a href="{URL}">{TEXT}</a>
|
||||
var pattern = /(?:\[([^\]]+)\]\((https?:\/\/[^"<>\]]+)\))|(?:<a href="(https?:\/\/[^"<>]+)">([^<]*)<\/a>)/gi;
|
||||
|
||||
var index = 0;
|
||||
var match;
|
||||
var link, text;
|
||||
|
||||
while ((match = pattern.exec(description))) {
|
||||
|
||||
// escape + insert text before match
|
||||
if (match.index > index) {
|
||||
escaped.push(escapeHTML(description.substring(index, match.index)));
|
||||
}
|
||||
|
||||
link = match[2] || match[3];
|
||||
text = match[1] || match[4];
|
||||
|
||||
// insert safe link
|
||||
escaped.push('<a href="' + link + '" target="_blank">' + escapeHTML(text) + '</a>');
|
||||
|
||||
index = match.index + match[0].length;
|
||||
}
|
||||
|
||||
// escape and insert text after last match
|
||||
if (index < description.length) {
|
||||
escaped.push(escapeHTML(description.substring(index)));
|
||||
}
|
||||
|
||||
return '<div class="bpp-field-description">' + escaped.join('') + '</div>';
|
||||
};
|
@ -0,0 +1,38 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The label factory provides a label entry. For the label text
|
||||
* it expects either a string provided by the options.labelText
|
||||
* parameter or it could be generated programmatically using a
|
||||
* function passed as the options.get parameter.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {string} options.id
|
||||
* @param {string} [options.labelText]
|
||||
* @param {Function} [options.get]
|
||||
* @param {Function} [options.showLabel]
|
||||
* @param {Boolean} [options.divider] adds a divider at the top of the label if true; default: false
|
||||
*/
|
||||
var label = function(options) {
|
||||
return {
|
||||
id: options.id,
|
||||
html: '<label data-value="label" ' +
|
||||
'data-show="showLabel" ' +
|
||||
'class="entry-label' + (options.divider ? ' divider' : '') + '">' +
|
||||
'</label>',
|
||||
get: function(element, node) {
|
||||
if (typeof options.get === 'function') {
|
||||
return options.get(element, node);
|
||||
}
|
||||
return { label: options.labelText };
|
||||
},
|
||||
showLabel: function(element, node) {
|
||||
if (typeof options.showLabel === 'function') {
|
||||
return options.showLabel(element, node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = label;
|
@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
var escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
var entryFieldDescription = require('./EntryFieldDescription');
|
||||
|
||||
var bind = require('lodash/bind');
|
||||
|
||||
/**
|
||||
* An entry that renders a clickable link.
|
||||
*
|
||||
* A passed {@link options#handleClick} handler is responsible
|
||||
* to process the click.
|
||||
*
|
||||
* The link may be conditionally shown or hidden. This can be
|
||||
* controlled via the {@link options.showLink}.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {String} options.id
|
||||
* @param {String} [options.label]
|
||||
* @param {Function} options.handleClick
|
||||
* @param {Function} [options.showLink] returning false to hide link
|
||||
* @param {String} [options.description]
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* var linkEntry = link({
|
||||
* id: 'foo',
|
||||
* description: 'Some Description',
|
||||
* handleClick: function(element, node, event) { ... },
|
||||
* showLink: function(element, node) { ... }
|
||||
* });
|
||||
*
|
||||
* @return {Entry} the newly created entry
|
||||
*/
|
||||
function link(options) {
|
||||
|
||||
var id = options.id,
|
||||
label = options.label || id,
|
||||
showLink = options.showLink,
|
||||
handleClick = options.handleClick,
|
||||
description = options.description;
|
||||
|
||||
if (showLink && typeof showLink !== 'function') {
|
||||
throw new Error('options.showLink must be a function');
|
||||
}
|
||||
|
||||
if (typeof handleClick !== 'function') {
|
||||
throw new Error('options.handleClick must be a function');
|
||||
}
|
||||
|
||||
var resource = {
|
||||
id: id
|
||||
};
|
||||
|
||||
resource.html =
|
||||
'<a data-action="handleClick" ' +
|
||||
(showLink ? 'data-show="showLink" ' : '') +
|
||||
'class="bpp-entry-link' + (options.cssClasses ? ' ' + escapeHTML(options.cssClasses) : '') +
|
||||
'">' + escapeHTML(label) + '</a>';
|
||||
|
||||
// add description below link entry field
|
||||
if (description) {
|
||||
resource.html += entryFieldDescription(description);
|
||||
}
|
||||
|
||||
resource.handleClick = bind(handleClick, resource);
|
||||
|
||||
if (typeof showLink === 'function') {
|
||||
resource.showLink = function() {
|
||||
return showLink.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
module.exports = link;
|
@ -0,0 +1,137 @@
|
||||
'use strict';
|
||||
|
||||
var escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
var domify = require('min-dom').domify;
|
||||
|
||||
var forEach = require('lodash/forEach');
|
||||
|
||||
var entryFieldDescription = require('./EntryFieldDescription');
|
||||
|
||||
|
||||
var isList = function(list) {
|
||||
return !(!list || Object.prototype.toString.call(list) !== '[object Array]');
|
||||
};
|
||||
|
||||
var addEmptyParameter = function(list) {
|
||||
return list.concat([ { name: '', value: '' } ]);
|
||||
};
|
||||
|
||||
var createOption = function(option) {
|
||||
return '<option value="' + option.value + '">' + option.name + '</option>';
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @param {string} options.id
|
||||
* @param {string} [options.label]
|
||||
* @param {Array<Object>} options.selectOptions
|
||||
* @param {string} options.modelProperty
|
||||
* @param {boolean} options.emptyParameter
|
||||
* @param {function} options.disabled
|
||||
* @param {function} options.hidden
|
||||
* @param {Object} defaultParameters
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
var selectbox = function(options, defaultParameters) {
|
||||
var resource = defaultParameters,
|
||||
label = options.label || resource.id,
|
||||
selectOptions = options.selectOptions || [ { name: '', value: '' } ],
|
||||
modelProperty = options.modelProperty,
|
||||
emptyParameter = options.emptyParameter,
|
||||
canBeDisabled = !!options.disabled && typeof options.disabled === 'function',
|
||||
canBeHidden = !!options.hidden && typeof options.hidden === 'function',
|
||||
description = options.description;
|
||||
|
||||
|
||||
if (emptyParameter) {
|
||||
selectOptions = addEmptyParameter(selectOptions);
|
||||
}
|
||||
|
||||
|
||||
resource.html =
|
||||
'<label for="activiti-' + escapeHTML(resource.id) + '"' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled" ' : '') +
|
||||
(canBeHidden ? 'data-show="isHidden" ' : '') +
|
||||
'>' + escapeHTML(label) + '</label>' +
|
||||
'<select id="activiti-' + escapeHTML(resource.id) + '-select" name="' +
|
||||
escapeHTML(modelProperty) + '"' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled" ' : '') +
|
||||
(canBeHidden ? 'data-show="isHidden" ' : '') +
|
||||
' data-value>';
|
||||
|
||||
if (isList(selectOptions)) {
|
||||
forEach(selectOptions, function(option) {
|
||||
resource.html += '<option value="' + escapeHTML(option.value) + '">' +
|
||||
(option.name ? escapeHTML(option.name) : '') + '</option>';
|
||||
});
|
||||
}
|
||||
|
||||
resource.html += '</select>';
|
||||
|
||||
// add description below select box entry field
|
||||
if (description && typeof options.showCustomInput !== 'function') {
|
||||
resource.html += entryFieldDescription(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the select box options dynamically.
|
||||
*
|
||||
* Calls the defined function #selectOptions in the entry to get the
|
||||
* values for the options and set the value to the inputNode.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {HTMLElement} entryNode
|
||||
* @param {EntryDescriptor} inputNode
|
||||
* @param {Object} inputName
|
||||
* @param {Object} newValue
|
||||
*/
|
||||
resource.setControlValue = function(element, entryNode, inputNode, inputName, newValue) {
|
||||
if (typeof selectOptions === 'function') {
|
||||
|
||||
var options = selectOptions(element, inputNode);
|
||||
|
||||
if (options) {
|
||||
|
||||
// remove existing options
|
||||
while (inputNode.firstChild) {
|
||||
inputNode.removeChild(inputNode.firstChild);
|
||||
}
|
||||
|
||||
// add options
|
||||
forEach(options, function(option) {
|
||||
var template = domify(createOption(option));
|
||||
|
||||
inputNode.appendChild(template);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// set select value
|
||||
if (newValue !== undefined) {
|
||||
inputNode.value = newValue;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (canBeDisabled) {
|
||||
resource.isDisabled = function() {
|
||||
return options.disabled.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
if (canBeHidden) {
|
||||
resource.isHidden = function() {
|
||||
return !options.hidden.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
resource.cssClasses = ['bpp-dropdown'];
|
||||
|
||||
return resource;
|
||||
};
|
||||
|
||||
module.exports = selectbox;
|
@ -0,0 +1,338 @@
|
||||
'use strict';
|
||||
|
||||
var escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
var cmdHelper = require('../helper/CmdHelper');
|
||||
|
||||
var domQuery = require('min-dom').query,
|
||||
domAttr = require('min-dom').attr,
|
||||
domClosest = require('min-dom').closest;
|
||||
|
||||
var filter = require('lodash/filter'),
|
||||
forEach = require('lodash/forEach'),
|
||||
keys = require('lodash/keys');
|
||||
|
||||
var domify = require('min-dom').domify;
|
||||
|
||||
var entryFieldDescription = require('./EntryFieldDescription');
|
||||
|
||||
var updateSelection = require('selection-update');
|
||||
|
||||
var TABLE_ROW_DIV_SNIPPET = '<div class="bpp-field-wrapper bpp-table-row">';
|
||||
var DELETE_ROW_BUTTON_SNIPPET = '<button class="clear" data-action="deleteElement">' +
|
||||
'<span>X</span>' +
|
||||
'</button>';
|
||||
|
||||
function createInputRowTemplate(properties, canRemove) {
|
||||
var template = TABLE_ROW_DIV_SNIPPET;
|
||||
template += createInputTemplate(properties, canRemove);
|
||||
template += canRemove ? DELETE_ROW_BUTTON_SNIPPET : '';
|
||||
template += '</div>';
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
function createInputTemplate(properties, canRemove) {
|
||||
var columns = properties.length;
|
||||
var template = '';
|
||||
forEach(properties, function(prop) {
|
||||
template += '<input class="bpp-table-row-columns-' + columns + ' ' +
|
||||
(canRemove ? 'bpp-table-row-removable' : '') + '" ' +
|
||||
'id="activiti-table-row-cell-input-value" ' +
|
||||
'type="text" ' +
|
||||
'name="' + escapeHTML(prop) + '" />';
|
||||
});
|
||||
return template;
|
||||
}
|
||||
|
||||
function createLabelRowTemplate(labels) {
|
||||
var template = TABLE_ROW_DIV_SNIPPET;
|
||||
template += createLabelTemplate(labels);
|
||||
template += '</div>';
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
function createLabelTemplate(labels) {
|
||||
var columns = labels.length;
|
||||
var template = '';
|
||||
forEach(labels, function(label) {
|
||||
template += '<label class="bpp-table-row-columns-' + columns + '">' + escapeHTML(label) + '</label>';
|
||||
});
|
||||
return template;
|
||||
}
|
||||
|
||||
function pick(elements, properties) {
|
||||
return (elements || []).map(function(elem) {
|
||||
var newElement = {};
|
||||
forEach(properties, function(prop) {
|
||||
newElement[prop] = elem[prop] || '';
|
||||
});
|
||||
return newElement;
|
||||
});
|
||||
}
|
||||
|
||||
function diff(element, node, values, oldValues, editable) {
|
||||
return filter(values, function(value, idx) {
|
||||
return !valueEqual(element, node, value, oldValues[idx], editable, idx);
|
||||
});
|
||||
}
|
||||
|
||||
function valueEqual(element, node, value, oldValue, editable, idx) {
|
||||
if (value && !oldValue) {
|
||||
return false;
|
||||
}
|
||||
var allKeys = keys(value).concat(keys(oldValue));
|
||||
|
||||
return allKeys.every(function(key) {
|
||||
var n = value[key] || undefined;
|
||||
var o = oldValue[key] || undefined;
|
||||
return !editable(element, node, key, idx) || n === o;
|
||||
});
|
||||
}
|
||||
|
||||
function getEntryNode(node) {
|
||||
return domClosest(node, '[data-entry]', true);
|
||||
}
|
||||
|
||||
function getContainer(node) {
|
||||
return domQuery('div[data-list-entry-container]', node);
|
||||
}
|
||||
|
||||
function getSelection(node) {
|
||||
return {
|
||||
start: node.selectionStart,
|
||||
end: node.selectionEnd
|
||||
};
|
||||
}
|
||||
|
||||
function setSelection(node, selection) {
|
||||
node.selectionStart = selection.start;
|
||||
node.selectionEnd = selection.end;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} options
|
||||
* @param {string} options.id
|
||||
* @param {string} options.description
|
||||
* @param {Array<string>} options.modelProperties
|
||||
* @param {Array<string>} options.labels
|
||||
* @param {Function} options.getElements - this callback function must return a list of business object items
|
||||
* @param {Function} options.removeElement
|
||||
* @param {Function} options.addElement
|
||||
* @param {Function} options.updateElement
|
||||
* @param {Function} options.editable
|
||||
* @param {Function} options.setControlValue
|
||||
* @param {Function} options.show
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
module.exports = function(options) {
|
||||
|
||||
var id = options.id,
|
||||
modelProperties = options.modelProperties,
|
||||
labels = options.labels,
|
||||
description = options.description;
|
||||
|
||||
var labelRow = createLabelRowTemplate(labels);
|
||||
|
||||
var getElements = options.getElements;
|
||||
|
||||
var removeElement = options.removeElement,
|
||||
canRemove = typeof removeElement === 'function';
|
||||
|
||||
var addElement = options.addElement,
|
||||
canAdd = typeof addElement === 'function',
|
||||
addLabel = options.addLabel || 'Add Value';
|
||||
|
||||
var updateElement = options.updateElement,
|
||||
canUpdate = typeof updateElement === 'function';
|
||||
|
||||
var editable = options.editable || function() { return true; },
|
||||
setControlValue = options.setControlValue;
|
||||
|
||||
var show = options.show,
|
||||
canBeShown = typeof show === 'function';
|
||||
|
||||
var elements = function(element, node) {
|
||||
return pick(getElements(element, node), modelProperties);
|
||||
};
|
||||
|
||||
var factory = {
|
||||
id: id,
|
||||
html: (canAdd ?
|
||||
'<div class="bpp-table-add-row" ' + (canBeShown ? 'data-show="show"' : '') + '>' +
|
||||
'<label>' + escapeHTML(addLabel) + '</label>' +
|
||||
'<button class="add" data-action="addElement"><span>+</span></button>' +
|
||||
'</div>' : '') +
|
||||
'<div class="bpp-table" data-show="showTable">' +
|
||||
'<div class="bpp-field-wrapper bpp-table-row">' +
|
||||
labelRow +
|
||||
'</div>' +
|
||||
'<div data-list-entry-container>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
// add description below table entry field
|
||||
(description ? entryFieldDescription(description) : ''),
|
||||
|
||||
get: function(element, node) {
|
||||
var boElements = elements(element, node, this.__invalidValues);
|
||||
|
||||
var invalidValues = this.__invalidValues;
|
||||
|
||||
delete this.__invalidValues;
|
||||
|
||||
forEach(invalidValues, function(value, idx) {
|
||||
var element = boElements[idx];
|
||||
|
||||
forEach(modelProperties, function(prop) {
|
||||
element[prop] = value[prop];
|
||||
});
|
||||
});
|
||||
|
||||
return boElements;
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var action = this.__action || {};
|
||||
delete this.__action;
|
||||
|
||||
if (action.id === 'delete-element') {
|
||||
return removeElement(element, node, action.idx);
|
||||
}
|
||||
else if (action.id === 'add-element') {
|
||||
return addElement(element, node);
|
||||
}
|
||||
else if (canUpdate) {
|
||||
var commands = [],
|
||||
valuesToValidate = values;
|
||||
|
||||
if (typeof options.validate !== 'function') {
|
||||
valuesToValidate = diff(element, node, values, elements(element, node), editable);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
forEach(valuesToValidate, function(value) {
|
||||
var validationError,
|
||||
idx = values.indexOf(value);
|
||||
|
||||
if (typeof options.validate === 'function') {
|
||||
validationError = options.validate(element, value, node, idx);
|
||||
}
|
||||
|
||||
if (!validationError) {
|
||||
var cmd = updateElement(element, value, node, idx);
|
||||
|
||||
if (cmd) {
|
||||
commands.push(cmd);
|
||||
}
|
||||
} else {
|
||||
// cache invalid value in an object by index as key
|
||||
self.__invalidValues = self.__invalidValues || {};
|
||||
self.__invalidValues[idx] = value;
|
||||
|
||||
// execute a command, which does not do anything
|
||||
commands.push(cmdHelper.updateProperties(element, {}));
|
||||
}
|
||||
});
|
||||
|
||||
return commands;
|
||||
}
|
||||
},
|
||||
createListEntryTemplate: function(value, index, selectBox) {
|
||||
return createInputRowTemplate(modelProperties, canRemove);
|
||||
},
|
||||
|
||||
addElement: function(element, node, event, scopeNode) {
|
||||
var template = domify(createInputRowTemplate(modelProperties, canRemove));
|
||||
|
||||
var container = getContainer(node);
|
||||
container.appendChild(template);
|
||||
|
||||
this.__action = {
|
||||
id: 'add-element'
|
||||
};
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
deleteElement: function(element, node, event, scopeNode) {
|
||||
var container = getContainer(node);
|
||||
var rowToDelete = event.delegateTarget.parentNode;
|
||||
var idx = parseInt(domAttr(rowToDelete, 'data-index'), 10);
|
||||
|
||||
container.removeChild(rowToDelete);
|
||||
|
||||
this.__action = {
|
||||
id: 'delete-element',
|
||||
idx: idx
|
||||
};
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
editable: function(element, rowNode, input, prop, value, idx) {
|
||||
var entryNode = domClosest(rowNode, '[data-entry]');
|
||||
return editable(element, entryNode, prop, idx);
|
||||
},
|
||||
|
||||
show: function(element, entryNode, node, scopeNode) {
|
||||
entryNode = getEntryNode(entryNode);
|
||||
return show(element, entryNode, node, scopeNode);
|
||||
},
|
||||
|
||||
showTable: function(element, entryNode, node, scopeNode) {
|
||||
entryNode = getEntryNode(entryNode);
|
||||
var elems = elements(element, entryNode);
|
||||
return elems && elems.length && (!canBeShown || show(element, entryNode, node, scopeNode));
|
||||
},
|
||||
|
||||
validateListItem: function(element, value, node, idx) {
|
||||
if (typeof options.validate === 'function') {
|
||||
return options.validate(element, value, node, idx);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Update/set the selection on the correct position.
|
||||
// It's the same code like for an input value in the PropertiesPanel.js.
|
||||
if (setControlValue) {
|
||||
factory.setControlValue = function(element, rowNode, input, prop, value, idx) {
|
||||
var entryNode = getEntryNode(rowNode);
|
||||
|
||||
var isReadOnly = domAttr(input, 'readonly');
|
||||
var oldValue = input.value;
|
||||
|
||||
var selection;
|
||||
|
||||
// prevents input fields from having the value 'undefined'
|
||||
if (value === undefined) {
|
||||
value = '';
|
||||
}
|
||||
|
||||
// when the attribute 'readonly' exists, ignore the comparison
|
||||
// with 'oldValue' and 'value'
|
||||
if (!!isReadOnly && oldValue === value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update selection on undo/redo
|
||||
if (document.activeElement === input) {
|
||||
selection = updateSelection(getSelection(input), oldValue, value);
|
||||
}
|
||||
|
||||
setControlValue(element, entryNode, input, prop, value, idx);
|
||||
|
||||
if (selection) {
|
||||
setSelection(input, selection);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
return factory;
|
||||
|
||||
};
|
@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
var escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
var entryFieldDescription = require('./EntryFieldDescription');
|
||||
|
||||
|
||||
var textBox = function(options, defaultParameters) {
|
||||
|
||||
var resource = defaultParameters,
|
||||
label = options.label || resource.id,
|
||||
canBeShown = !!options.show && typeof options.show === 'function',
|
||||
description = options.description;
|
||||
|
||||
resource.html =
|
||||
'<label for="activiti-' + escapeHTML(resource.id) + '" ' +
|
||||
(canBeShown ? 'data-show="isShown"' : '') +
|
||||
'>' + label + '</label>' +
|
||||
'<div class="bpp-field-wrapper" ' +
|
||||
(canBeShown ? 'data-show="isShown"' : '') +
|
||||
'>' +
|
||||
'<div contenteditable="true" id="activiti-' + escapeHTML(resource.id) + '" ' +
|
||||
'name="' + escapeHTML(options.modelProperty) + '" />' +
|
||||
'</div>';
|
||||
|
||||
// add description below text box entry field
|
||||
if (description) {
|
||||
resource.html += entryFieldDescription(description);
|
||||
}
|
||||
|
||||
if (canBeShown) {
|
||||
resource.isShown = function() {
|
||||
return options.show.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
resource.cssClasses = ['bpp-textbox'];
|
||||
|
||||
return resource;
|
||||
};
|
||||
|
||||
module.exports = textBox;
|
@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
|
||||
var escapeHTML = require('../Utils').escapeHTML;
|
||||
|
||||
var domQuery = require('min-dom').query;
|
||||
|
||||
var entryFieldDescription = require('./EntryFieldDescription');
|
||||
|
||||
|
||||
var textField = function(options, defaultParameters) {
|
||||
|
||||
// Default action for the button next to the input-field
|
||||
var defaultButtonAction = function(element, inputNode) {
|
||||
var input = domQuery('input[name="' + options.modelProperty + '"]', inputNode);
|
||||
input.value = '';
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// default method to determine if the button should be visible
|
||||
var defaultButtonShow = function(element, inputNode) {
|
||||
var input = domQuery('input[name="' + options.modelProperty + '"]', inputNode);
|
||||
|
||||
return input.value !== '';
|
||||
};
|
||||
|
||||
|
||||
var resource = defaultParameters,
|
||||
label = options.label || resource.id,
|
||||
dataValueLabel = options.dataValueLabel,
|
||||
buttonLabel = (options.buttonLabel || 'X'),
|
||||
actionName = (typeof options.buttonAction != 'undefined') ? options.buttonAction.name : 'clear',
|
||||
actionMethod = (typeof options.buttonAction != 'undefined') ? options.buttonAction.method : defaultButtonAction,
|
||||
showName = (typeof options.buttonShow != 'undefined') ? options.buttonShow.name : 'canClear',
|
||||
showMethod = (typeof options.buttonShow != 'undefined') ? options.buttonShow.method : defaultButtonShow,
|
||||
canBeDisabled = !!options.disabled && typeof options.disabled === 'function',
|
||||
canBeHidden = !!options.hidden && typeof options.hidden === 'function',
|
||||
description = options.description;
|
||||
|
||||
resource.html =
|
||||
'<label for="activiti-' + escapeHTML(resource.id) + '" ' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled" ' : '') +
|
||||
(canBeHidden ? 'data-show="isHidden" ' : '') +
|
||||
(dataValueLabel ? 'data-value="' + escapeHTML(dataValueLabel) + '"' : '') + '>'+ escapeHTML(label) +'</label>' +
|
||||
'<div class="bpp-field-wrapper" ' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled"' : '') +
|
||||
(canBeHidden ? 'data-show="isHidden"' : '') +
|
||||
'>' +
|
||||
'<input id="activiti-' + escapeHTML(resource.id) + '" type="text" name="' + escapeHTML(options.modelProperty) + '" ' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled"' : '') +
|
||||
(canBeHidden ? 'data-show="isHidden"' : '') +
|
||||
' />' +
|
||||
'<button class="' + escapeHTML(actionName) + '" data-action="' + escapeHTML(actionName) + '" data-show="' + escapeHTML(showName) + '" ' +
|
||||
(canBeDisabled ? 'data-disable="isDisabled"' : '') +
|
||||
(canBeHidden ? ' data-show="isHidden"' : '') + '>' +
|
||||
'<span>' + escapeHTML(buttonLabel) + '</span>' +
|
||||
'</button>' +
|
||||
'</div>';
|
||||
|
||||
// add description below text input entry field
|
||||
if (description) {
|
||||
resource.html += entryFieldDescription(description);
|
||||
}
|
||||
|
||||
resource[actionName] = actionMethod;
|
||||
resource[showName] = showMethod;
|
||||
|
||||
if (canBeDisabled) {
|
||||
resource.isDisabled = function() {
|
||||
return options.disabled.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
if (canBeHidden) {
|
||||
resource.isHidden = function() {
|
||||
return !options.hidden.apply(resource, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
resource.cssClasses = ['bpp-textfield'];
|
||||
|
||||
return resource;
|
||||
};
|
||||
|
||||
module.exports = textField;
|
@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
|
||||
var textField = require('./TextInputEntryFactory');
|
||||
|
||||
/**
|
||||
* This function is a wrapper around TextInputEntryFactory.
|
||||
* It adds functionality to cache an invalid value entered in the
|
||||
* text input, instead of setting it on the business object.
|
||||
*/
|
||||
var validationAwareTextField = function(options, defaultParameters) {
|
||||
|
||||
var modelProperty = options.modelProperty;
|
||||
|
||||
defaultParameters.get = function(element, node) {
|
||||
var value = this.__lastInvalidValue;
|
||||
|
||||
delete this.__lastInvalidValue;
|
||||
|
||||
var properties = {};
|
||||
|
||||
properties[modelProperty] = value !== undefined ? value : options.getProperty(element, node);
|
||||
|
||||
return properties;
|
||||
};
|
||||
|
||||
defaultParameters.set = function(element, values, node) {
|
||||
var validationErrors = validate.apply(this, [ element, values, node ]),
|
||||
propertyValue = values[modelProperty];
|
||||
|
||||
// make sure we do not update the id
|
||||
if (validationErrors && validationErrors[modelProperty]) {
|
||||
this.__lastInvalidValue = propertyValue;
|
||||
|
||||
return options.setProperty(element, {}, node);
|
||||
} else {
|
||||
var properties = {};
|
||||
|
||||
properties[modelProperty] = propertyValue;
|
||||
|
||||
return options.setProperty(element, properties, node);
|
||||
}
|
||||
};
|
||||
|
||||
var validate = defaultParameters.validate = function(element, values, node) {
|
||||
var value = values[modelProperty] || this.__lastInvalidValue;
|
||||
|
||||
var property = {};
|
||||
property[modelProperty] = value;
|
||||
|
||||
return options.validate(element, property, node);
|
||||
};
|
||||
|
||||
return textField(options, defaultParameters);
|
||||
};
|
||||
|
||||
module.exports = validationAwareTextField;
|
@ -0,0 +1,76 @@
|
||||
'use strict';
|
||||
|
||||
var map = require('lodash/map');
|
||||
|
||||
var extensionElementsHelper = require('./ExtensionElementsHelper');
|
||||
|
||||
/**
|
||||
* Returns true if the attribute 'activiti:asyncBefore' is set
|
||||
* to true.
|
||||
*
|
||||
* @param {ModdleElement} bo
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
function isAsyncBefore(bo) {
|
||||
return !!(bo.get('activiti:asyncBefore') || bo.get('activiti:async'));
|
||||
}
|
||||
|
||||
module.exports.isAsyncBefore = isAsyncBefore;
|
||||
|
||||
/**
|
||||
* Returns true if the attribute 'activiti:asyncAfter' is set
|
||||
* to true.
|
||||
*
|
||||
* @param {ModdleElement} bo
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
function isAsyncAfter(bo) {
|
||||
return !!bo.get('activiti:asyncAfter');
|
||||
}
|
||||
|
||||
module.exports.isAsyncAfter = isAsyncAfter;
|
||||
|
||||
/**
|
||||
* Returns true if the attribute 'activiti:exclusive' is set
|
||||
* to true.
|
||||
*
|
||||
* @param {ModdleElement} bo
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
function isExclusive(bo) {
|
||||
return !!bo.get('activiti:exclusive');
|
||||
}
|
||||
|
||||
module.exports.isExclusive = isExclusive;
|
||||
|
||||
/**
|
||||
* Get first 'activiti:FailedJobRetryTimeCycle' from the business object.
|
||||
*
|
||||
* @param {ModdleElement} bo
|
||||
*
|
||||
* @return {Array<ModdleElement>} a list of 'activiti:FailedJobRetryTimeCycle'
|
||||
*/
|
||||
function getFailedJobRetryTimeCycle(bo) {
|
||||
return (extensionElementsHelper.getExtensionElements(bo, 'activiti:FailedJobRetryTimeCycle') || [])[0];
|
||||
}
|
||||
|
||||
module.exports.getFailedJobRetryTimeCycle = getFailedJobRetryTimeCycle;
|
||||
|
||||
/**
|
||||
* Removes all existing 'activiti:FailedJobRetryTimeCycle' from the business object
|
||||
*
|
||||
* @param {ModdleElement} bo
|
||||
*
|
||||
* @return {Array<ModdleElement>} a list of 'activiti:FailedJobRetryTimeCycle'
|
||||
*/
|
||||
function removeFailedJobRetryTimeCycle(bo, element) {
|
||||
var retryTimeCycles = extensionElementsHelper.getExtensionElements(bo, 'activiti:FailedJobRetryTimeCycle');
|
||||
return map(retryTimeCycles, function(cycle) {
|
||||
return extensionElementsHelper.removeEntry(bo, element, cycle);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.removeFailedJobRetryTimeCycle = removeFailedJobRetryTimeCycle;
|
@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
var collectionAdd = require('diagram-js/lib/util/Collections').add,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
var CategoryHelper = {};
|
||||
|
||||
module.exports = CategoryHelper;
|
||||
|
||||
/**
|
||||
* Creates a new bpmn:CategoryValue inside a new bpmn:Category
|
||||
*
|
||||
* @param {ModdleElement} definitions
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement} categoryValue.
|
||||
*/
|
||||
CategoryHelper.createCategoryValue = function(definitions, bpmnFactory) {
|
||||
var categoryValue = bpmnFactory.create('bpmn:CategoryValue'),
|
||||
category = bpmnFactory.create('bpmn:Category', {
|
||||
categoryValue: [ categoryValue ]
|
||||
});
|
||||
|
||||
// add to correct place
|
||||
collectionAdd(definitions.get('rootElements'), category);
|
||||
getBusinessObject(category).$parent = definitions;
|
||||
getBusinessObject(categoryValue).$parent = category;
|
||||
|
||||
return categoryValue;
|
||||
|
||||
};
|
@ -0,0 +1,77 @@
|
||||
'use strict';
|
||||
|
||||
var CmdHelper = {};
|
||||
module.exports = CmdHelper;
|
||||
|
||||
CmdHelper.updateProperties = function(element, properties) {
|
||||
return {
|
||||
cmd: 'element.updateProperties',
|
||||
context: { element: element, properties: properties }
|
||||
};
|
||||
};
|
||||
|
||||
CmdHelper.updateBusinessObject = function(element, businessObject, newProperties) {
|
||||
return {
|
||||
cmd: 'properties-panel.update-businessobject',
|
||||
context: {
|
||||
element: element,
|
||||
businessObject: businessObject,
|
||||
properties: newProperties
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
CmdHelper.addElementsTolist = function(element, businessObject, listPropertyName, objectsToAdd) {
|
||||
return {
|
||||
cmd: 'properties-panel.update-businessobject-list',
|
||||
context: {
|
||||
element: element,
|
||||
currentObject: businessObject,
|
||||
propertyName: listPropertyName,
|
||||
objectsToAdd: objectsToAdd
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
CmdHelper.removeElementsFromList = function(element, businessObject, listPropertyName, referencePropertyName, objectsToRemove) {
|
||||
|
||||
return {
|
||||
cmd: 'properties-panel.update-businessobject-list',
|
||||
context: {
|
||||
element: element,
|
||||
currentObject: businessObject,
|
||||
propertyName: listPropertyName,
|
||||
referencePropertyName: referencePropertyName,
|
||||
objectsToRemove: objectsToRemove
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
CmdHelper.addAndRemoveElementsFromList = function(element, businessObject, listPropertyName, referencePropertyName, objectsToAdd, objectsToRemove) {
|
||||
|
||||
return {
|
||||
cmd: 'properties-panel.update-businessobject-list',
|
||||
context: {
|
||||
element: element,
|
||||
currentObject: businessObject,
|
||||
propertyName: listPropertyName,
|
||||
referencePropertyName: referencePropertyName,
|
||||
objectsToAdd: objectsToAdd,
|
||||
objectsToRemove: objectsToRemove
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
CmdHelper.setList = function(element, businessObject, listPropertyName, updatedObjectList) {
|
||||
return {
|
||||
cmd: 'properties-panel.update-businessobject-list',
|
||||
context: {
|
||||
element: element,
|
||||
currentObject: businessObject,
|
||||
propertyName: listPropertyName,
|
||||
updatedObjectList: updatedObjectList
|
||||
}
|
||||
};
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
var ElementHelper = {};
|
||||
module.exports = ElementHelper;
|
||||
|
||||
/**
|
||||
* Creates a new element and set the parent to it
|
||||
*
|
||||
* @method ElementHelper#createElement
|
||||
*
|
||||
* @param {String} elementType of the new element
|
||||
* @param {Object} properties of the new element in key-value pairs
|
||||
* @param {moddle.object} parent of the new element
|
||||
* @param {BpmnFactory} factory which creates the new element
|
||||
*
|
||||
* @returns {djs.model.Base} element which is created
|
||||
*/
|
||||
ElementHelper.createElement = function(elementType, properties, parent, factory) {
|
||||
var element = factory.create(elementType, properties);
|
||||
element.$parent = parent;
|
||||
|
||||
return element;
|
||||
};
|
@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
forEach = require('lodash/forEach');
|
||||
|
||||
var EventDefinitionHelper = {};
|
||||
|
||||
module.exports = EventDefinitionHelper;
|
||||
|
||||
EventDefinitionHelper.getEventDefinition = function(element, eventType) {
|
||||
|
||||
var bo = getBusinessObject(element),
|
||||
eventDefinition = null;
|
||||
|
||||
if (bo.eventDefinitions) {
|
||||
forEach(bo.eventDefinitions, function(event) {
|
||||
if (is(event, eventType)) {
|
||||
eventDefinition = event;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return eventDefinition;
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getTimerEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:TimerEventDefinition');
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getMessageEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:MessageEventDefinition');
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getSignalEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:SignalEventDefinition');
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getErrorEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:ErrorEventDefinition');
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getEscalationEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:EscalationEventDefinition');
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getCompensateEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:CompensateEventDefinition');
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getLinkEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:LinkEventDefinition');
|
||||
};
|
||||
|
||||
EventDefinitionHelper.getConditionalEventDefinition = function(element) {
|
||||
return this.getEventDefinition(element, 'bpmn:ConditionalEventDefinition');
|
||||
};
|
@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
var cmdHelper = require('./CmdHelper'),
|
||||
elementHelper = require('./ElementHelper');
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is;
|
||||
|
||||
var ExtensionElementsHelper = {};
|
||||
|
||||
var getExtensionElements = function(bo) {
|
||||
return bo.get('extensionElements');
|
||||
};
|
||||
|
||||
ExtensionElementsHelper.getExtensionElements = function(bo, type) {
|
||||
var extensionElements = getExtensionElements(bo);
|
||||
if (typeof extensionElements !== 'undefined') {
|
||||
var extensionValues = extensionElements.get('values');
|
||||
if (typeof extensionValues !== 'undefined') {
|
||||
var elements = extensionValues.filter(function(value) {
|
||||
return is(value, type);
|
||||
});
|
||||
if (elements.length) {
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ExtensionElementsHelper.addEntry = function(bo, element, entry, bpmnFactory) {
|
||||
var extensionElements = bo.get('extensionElements');
|
||||
|
||||
// if there is no extensionElements list, create one
|
||||
if (!extensionElements) {
|
||||
extensionElements = elementHelper.createElement('bpmn:ExtensionElements', { values: [entry] }, bo, bpmnFactory);
|
||||
return { extensionElements : extensionElements };
|
||||
} else {
|
||||
// add new failedJobRetryExtensionElement to existing extensionElements list
|
||||
return cmdHelper.addElementsTolist(element, extensionElements, 'values', [entry]);
|
||||
}
|
||||
};
|
||||
|
||||
ExtensionElementsHelper.removeEntry = function(bo, element, entry) {
|
||||
var extensionElements = bo.get('extensionElements');
|
||||
|
||||
if (!extensionElements) {
|
||||
|
||||
// return an empty command when there is no extensionElements list
|
||||
return {};
|
||||
}
|
||||
|
||||
return cmdHelper.removeElementsFromList(element, extensionElements, 'values', 'extensionElements', [entry]);
|
||||
};
|
||||
|
||||
module.exports = ExtensionElementsHelper;
|
@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
getExtensionElements = require('./ExtensionElementsHelper').getExtensionElements;
|
||||
|
||||
var FormHelper = {};
|
||||
|
||||
module.exports = FormHelper;
|
||||
|
||||
/**
|
||||
* Return form data from business object or undefined if none exist
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {ModdleElement|undefined} formData
|
||||
*
|
||||
* 此方法废弃
|
||||
*
|
||||
*/
|
||||
FormHelper.getFormData = function(element) {
|
||||
/* var bo = getBusinessObject(element);
|
||||
|
||||
var formFields = getExtensionElements(bo, 'activiti:FormProperty');
|
||||
|
||||
var formData = {}
|
||||
|
||||
if (typeof formData !== 'undefined') {
|
||||
return formData[0];
|
||||
}*/
|
||||
return {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return all form fields existing in the business object, and
|
||||
* an empty array if none exist.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {Array} a list of form field objects
|
||||
*/
|
||||
FormHelper.getFormFields = function(element) {
|
||||
|
||||
/**直接获取 ExtensionElements的 activiti:FormProperty元素*/
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
var formFields = getExtensionElements(bo, 'activiti:FormProperty');
|
||||
|
||||
return formFields || [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get a form field from the business object at given index
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {number} idx
|
||||
*
|
||||
* @return {ModdleElement} the form field
|
||||
*/
|
||||
FormHelper.getFormField = function(element, idx) {
|
||||
|
||||
var formFields = this.getFormFields(element);
|
||||
|
||||
return formFields[idx];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get all constraints for a specific form field from the business object
|
||||
*
|
||||
* @param {ModdleElement} formField
|
||||
*
|
||||
* @return {Array<ModdleElement>} a list of constraint objects
|
||||
*/
|
||||
FormHelper.getConstraints = function(formField) {
|
||||
if (formField && formField.validation && formField.validation.constraints) {
|
||||
return formField.validation.constraints;
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get all activiti:value objects for a specific form field from the business object
|
||||
*
|
||||
* @param {ModdleElement} formField
|
||||
*
|
||||
* @return {Array<ModdleElement>} a list of activiti:value objects
|
||||
*/
|
||||
FormHelper.getEnumValues = function(formField) {
|
||||
if (formField && formField.values) {
|
||||
return formField.values;
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
@ -0,0 +1,192 @@
|
||||
'use strict';
|
||||
|
||||
var ModelUtil = require('bpmn-js/lib/util/ModelUtil'),
|
||||
is = ModelUtil.is,
|
||||
getBusinessObject = ModelUtil.getBusinessObject;
|
||||
|
||||
var eventDefinitionHelper = require('./EventDefinitionHelper');
|
||||
var extensionsElementHelper = require('./ExtensionElementsHelper');
|
||||
|
||||
var ImplementationTypeHelper = {};
|
||||
|
||||
module.exports = ImplementationTypeHelper;
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element is 'activiti:ServiceTaskLike'
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
ImplementationTypeHelper.isServiceTaskLike = function(element) {
|
||||
return is(element, 'activiti:ServiceTaskLike');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element is 'activiti:DmnCapable'
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
ImplementationTypeHelper.isDmnCapable = function(element) {
|
||||
return is(element, 'activiti:DmnCapable');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element is 'activiti:ExternalCapable'
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
ImplementationTypeHelper.isExternalCapable = function(element) {
|
||||
return is(element, 'activiti:ExternalCapable');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element is 'activiti:TaskListener'
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
ImplementationTypeHelper.isTaskListener = function(element) {
|
||||
return is(element, 'activiti:TaskListener');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element is 'activiti:ExecutionListener'
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
ImplementationTypeHelper.isExecutionListener = function(element) {
|
||||
return is(element, 'activiti:ExecutionListener');
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element is 'activiti:ExecutionListener' or
|
||||
* 'activiti:TaskListener'
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
ImplementationTypeHelper.isListener = function(element) {
|
||||
return this.isTaskListener(element) || this.isExecutionListener(element);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element is 'bpmn:SequenceFlow'
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
ImplementationTypeHelper.isSequenceFlow = function(element) {
|
||||
return is(element, 'bpmn:SequenceFlow');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a 'activiti:ServiceTaskLike' business object.
|
||||
*
|
||||
* If the given element is not a 'activiti:ServiceTaskLike', then 'false'
|
||||
* is returned.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {ModdleElement} the 'activiti:ServiceTaskLike' business object
|
||||
*/
|
||||
ImplementationTypeHelper.getServiceTaskLikeBusinessObject = function(element) {
|
||||
|
||||
if (is(element, 'bpmn:IntermediateThrowEvent') || is(element, 'bpmn:EndEvent')) {
|
||||
|
||||
// change business object to 'messageEventDefinition' when
|
||||
// the element is a message intermediate throw event or message end event
|
||||
// because the activiti extensions (e.g. activiti:class) are in the message
|
||||
// event definition tag and not in the intermediate throw event or end event tag
|
||||
var messageEventDefinition = eventDefinitionHelper.getMessageEventDefinition(element);
|
||||
if (messageEventDefinition) {
|
||||
element = messageEventDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
return this.isServiceTaskLike(element) && getBusinessObject(element);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the implementation type of the given element.
|
||||
*
|
||||
* Possible implementation types are:
|
||||
* - dmn
|
||||
* - connector
|
||||
* - external
|
||||
* - class
|
||||
* - expression
|
||||
* - delegateExpression
|
||||
* - script
|
||||
* - or undefined, when no matching implementation type is found
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {String} the implementation type
|
||||
*/
|
||||
ImplementationTypeHelper.getImplementationType = function(element) {
|
||||
|
||||
var bo = this.getServiceTaskLikeBusinessObject(element);
|
||||
|
||||
if (!bo) {
|
||||
if (this.isListener(element)) {
|
||||
bo = element;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isDmnCapable(bo)) {
|
||||
var decisionRef = bo.get('activiti:decisionRef');
|
||||
if (typeof decisionRef !== 'undefined') {
|
||||
return 'dmn';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isServiceTaskLike(bo)) {
|
||||
var connectors = extensionsElementHelper.getExtensionElements(bo, 'activiti:Connector');
|
||||
if (typeof connectors !== 'undefined') {
|
||||
return 'connector';
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isExternalCapable(bo)) {
|
||||
var type = bo.get('activiti:type');
|
||||
if (type === 'external') {
|
||||
return 'external';
|
||||
}
|
||||
}
|
||||
|
||||
var cls = bo.get('activiti:class');
|
||||
if (typeof cls !== 'undefined') {
|
||||
return 'class';
|
||||
}
|
||||
|
||||
var expression = bo.get('activiti:expression');
|
||||
if (typeof expression !== 'undefined') {
|
||||
return 'expression';
|
||||
}
|
||||
|
||||
var delegateExpression = bo.get('activiti:delegateExpression');
|
||||
if (typeof delegateExpression !== 'undefined') {
|
||||
return 'delegateExpression';
|
||||
}
|
||||
|
||||
if (this.isListener(bo)) {
|
||||
var script = bo.get('script');
|
||||
if (typeof script !== 'undefined') {
|
||||
return 'script';
|
||||
}
|
||||
}
|
||||
|
||||
};
|
@ -0,0 +1,144 @@
|
||||
'use strict';
|
||||
|
||||
var ModelUtil = require('bpmn-js/lib/util/ModelUtil'),
|
||||
is = ModelUtil.is,
|
||||
getBusinessObject = ModelUtil.getBusinessObject;
|
||||
|
||||
var extensionElementsHelper = require('./ExtensionElementsHelper'),
|
||||
implementationTypeHelper = require('./ImplementationTypeHelper');
|
||||
|
||||
var InputOutputHelper = {};
|
||||
|
||||
module.exports = InputOutputHelper;
|
||||
|
||||
function getElements(bo, type, prop) {
|
||||
var elems = extensionElementsHelper.getExtensionElements(bo, type) || [];
|
||||
return !prop ? elems : (elems[0] || {})[prop] || [];
|
||||
}
|
||||
|
||||
function getParameters(element, prop, insideConnector) {
|
||||
var inputOutput = InputOutputHelper.getInputOutput(element, insideConnector);
|
||||
return (inputOutput && inputOutput.get(prop)) || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a inputOutput from the business object
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {boolean} insideConnector
|
||||
*
|
||||
* @return {ModdleElement} the inputOutput object
|
||||
*/
|
||||
InputOutputHelper.getInputOutput = function(element, insideConnector) {
|
||||
if (!insideConnector) {
|
||||
var bo = getBusinessObject(element);
|
||||
return (getElements(bo, 'activiti:InputOutput') || [])[0];
|
||||
}
|
||||
var connector = this.getConnector(element);
|
||||
return connector && connector.get('inputOutput');
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a connector from the business object
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {ModdleElement} the connector object
|
||||
*/
|
||||
InputOutputHelper.getConnector = function(element) {
|
||||
var bo = implementationTypeHelper.getServiceTaskLikeBusinessObject(element);
|
||||
return bo && (getElements(bo, 'activiti:Connector') || [])[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Return all input parameters existing in the business object, and
|
||||
* an empty array if none exist.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {boolean} insideConnector
|
||||
*
|
||||
* @return {Array} a list of input parameter objects
|
||||
*/
|
||||
InputOutputHelper.getInputParameters = function(element, insideConnector) {
|
||||
return getParameters.apply(this, [ element, 'inputParameters', insideConnector ]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return all output parameters existing in the business object, and
|
||||
* an empty array if none exist.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {boolean} insideConnector
|
||||
*
|
||||
* @return {Array} a list of output parameter objects
|
||||
*/
|
||||
InputOutputHelper.getOutputParameters = function(element, insideConnector) {
|
||||
return getParameters.apply(this, [ element, 'outputParameters', insideConnector ]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a input parameter from the business object at given index
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {boolean} insideConnector
|
||||
* @param {number} idx
|
||||
*
|
||||
* @return {ModdleElement} input parameter
|
||||
*/
|
||||
InputOutputHelper.getInputParameter = function(element, insideConnector, idx) {
|
||||
return this.getInputParameters(element, insideConnector)[idx];
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a output parameter from the business object at given index
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {boolean} insideConnector
|
||||
* @param {number} idx
|
||||
*
|
||||
* @return {ModdleElement} output parameter
|
||||
*/
|
||||
InputOutputHelper.getOutputParameter = function(element, insideConnector, idx) {
|
||||
return this.getOutputParameters(element, insideConnector)[idx];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element supports inputOutput
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {boolean} insideConnector
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
InputOutputHelper.isInputOutputSupported = function(element, insideConnector) {
|
||||
|
||||
if (insideConnector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
return (
|
||||
is(bo, 'bpmn:FlowNode') && !(
|
||||
is(bo, 'bpmn:StartEvent') ||
|
||||
is(bo, 'bpmn:Gateway') ||
|
||||
is(bo, 'bpmn:BoundaryEvent') ||
|
||||
(
|
||||
is(bo, 'bpmn:SubProcess') && bo.get('triggeredByEvent')
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns 'true' if the given element supports output parameters
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {boolean} insideConnector
|
||||
*
|
||||
* @return {boolean} a boolean value
|
||||
*/
|
||||
InputOutputHelper.areOutputParametersSupported = function(element, insideConnector) {
|
||||
var bo = getBusinessObject(element);
|
||||
return insideConnector || (!is(bo, 'bpmn:EndEvent') && !bo.loopCharacteristics);
|
||||
};
|
@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
cmdHelper = require('./CmdHelper');
|
||||
|
||||
|
||||
var ParticipantHelper = {};
|
||||
|
||||
module.exports = ParticipantHelper;
|
||||
|
||||
ParticipantHelper.modifyProcessBusinessObject = function(element, property, values) {
|
||||
if (!is(element, 'bpmn:Participant')) {
|
||||
return {};
|
||||
}
|
||||
|
||||
var bo = getBusinessObject(element).get('processRef'),
|
||||
properties = {};
|
||||
|
||||
properties[property] = values[property];
|
||||
|
||||
return cmdHelper.updateBusinessObject(element, bo, properties);
|
||||
};
|
||||
|
||||
ParticipantHelper.getProcessBusinessObject = function(element, propertyName) {
|
||||
if (!is(element, 'bpmn:Participant')) {
|
||||
return {};
|
||||
}
|
||||
|
||||
var bo = getBusinessObject(element).get('processRef'),
|
||||
properties = {};
|
||||
|
||||
properties[propertyName] = bo.get(propertyName);
|
||||
|
||||
return properties;
|
||||
};
|
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
__depends__: [
|
||||
require('./index'),
|
||||
require('diagram-js/lib/i18n/translate').default
|
||||
],
|
||||
__init__: [ 'propertiesPanel' ],
|
||||
propertiesPanel: [ 'type', require('./PropertiesPanel') ]
|
||||
};
|
@ -0,0 +1,103 @@
|
||||
'use strict';
|
||||
|
||||
var domQuery = require('min-dom').query,
|
||||
domClasses = require('min-dom').classes,
|
||||
domify = require('min-dom').domify,
|
||||
bind = require('lodash/bind');
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
*/
|
||||
function Popup(options) {
|
||||
options = options || {};
|
||||
this.template = options.template || this.template;
|
||||
var el = this.el = domify(this.template);
|
||||
|
||||
this.header = domQuery('.popup-header', el);
|
||||
this.body = domQuery('.popup-body', el);
|
||||
this.footer = domQuery('.popup-footer', el);
|
||||
|
||||
document.body.appendChild(el);
|
||||
|
||||
this._attachEvents();
|
||||
}
|
||||
|
||||
Popup.prototype.template = '<div class="bpp-properties-panel-popup">' +
|
||||
'<div class="underlay"></div>' +
|
||||
'<div class="popup">' +
|
||||
'<button class="popup-close"><span>Close</span></button>' +
|
||||
'<div class="popup-header"></div>' +
|
||||
'<div class="popup-body"></div>' +
|
||||
'<div class="popup-footer"></div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
|
||||
Popup.prototype._attachEvents = function() {
|
||||
var self = this;
|
||||
var events = this.events;
|
||||
var el = this.el;
|
||||
|
||||
Object.keys(events).forEach(function(instruction) {
|
||||
var cb = bind(self[events[instruction]], self);
|
||||
var parts = instruction.split(' ');
|
||||
var evtName = parts.shift();
|
||||
var target = parts.length ? parts.shift() : false;
|
||||
target = target ? domQuery(target, el) : el;
|
||||
if (!target) { return; }
|
||||
target.addEventListener(evtName, cb);
|
||||
});
|
||||
};
|
||||
|
||||
Popup.prototype._detachEvents = function() {
|
||||
var self = this;
|
||||
var events = this.events;
|
||||
var el = this.el;
|
||||
|
||||
Object.keys(events).forEach(function(instruction) {
|
||||
var cb = bind(self[events[instruction]], self);
|
||||
var parts = instruction.split(' ');
|
||||
var evtName = parts.shift();
|
||||
var target = parts.length ? parts.shift() : false;
|
||||
target = target ? domQuery(target, el) : el;
|
||||
if (!target) { return; }
|
||||
target.removeEventListener(evtName, cb);
|
||||
});
|
||||
};
|
||||
|
||||
Popup.prototype.events = {
|
||||
// 'keydown:esc': '_handleClose',
|
||||
'click .underlay': '_handleClose',
|
||||
'click .popup-close': '_handleClose'
|
||||
};
|
||||
|
||||
|
||||
Popup.prototype._handleClose = function(evt) {
|
||||
this.close();
|
||||
};
|
||||
|
||||
|
||||
Popup.prototype.open = function(content) {
|
||||
domClasses(this.el).add('open');
|
||||
};
|
||||
|
||||
Popup.prototype.close = function() {
|
||||
domClasses(this.el).remove('open');
|
||||
};
|
||||
|
||||
Popup.prototype.remove = function() {
|
||||
this._detachEvents();
|
||||
if (document.body.contains(this.el)) {
|
||||
document.body.removeChild(this.el);
|
||||
}
|
||||
};
|
||||
|
||||
var popup;
|
||||
module.exports = function() {
|
||||
if (!popup) {
|
||||
popup = new Popup();
|
||||
}
|
||||
return popup;
|
||||
};
|
@ -0,0 +1,542 @@
|
||||
'use strict';
|
||||
|
||||
var inherits = require('inherits');
|
||||
|
||||
var PropertiesActivator = require('../../PropertiesActivator');
|
||||
|
||||
var asyncCapableHelper = require('../../helper/AsyncCapableHelper'),
|
||||
ImplementationTypeHelper = require('../../helper/ImplementationTypeHelper');
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is;
|
||||
|
||||
// bpmn properties
|
||||
var processProps = require('../../provider/bpmn/parts/ProcessProps'),
|
||||
eventProps = require('../../provider/bpmn/parts/EventProps'),
|
||||
linkProps = require('../../provider/bpmn/parts/LinkProps'),
|
||||
documentationProps = require('../../provider/bpmn/parts/DocumentationProps'),
|
||||
idProps = require('../../provider/bpmn/parts/IdProps'),
|
||||
nameProps = require('../../provider/bpmn/parts/NameProps'),
|
||||
executableProps = require('../../provider/bpmn/parts/ExecutableProps');
|
||||
|
||||
// activiti properties
|
||||
var serviceTaskDelegateProps = require('./parts/ServiceTaskDelegateProps'),
|
||||
userTaskProps = require('./parts/UserTaskProps'),
|
||||
asynchronousContinuationProps = require('./parts/AsynchronousContinuationProps'),
|
||||
callActivityProps = require('./parts/CallActivityProps'),
|
||||
multiInstanceProps = require('./parts/MultiInstanceLoopProps'),
|
||||
conditionalProps = require('./parts/ConditionalProps'),
|
||||
scriptProps = require('./parts/ScriptTaskProps'),
|
||||
errorProps = require('./parts/ErrorEventProps'),
|
||||
formProps = require('./parts/FormProps'),
|
||||
startEventInitiator = require('./parts/StartEventInitiator'),
|
||||
variableMapping = require('./parts/VariableMappingProps'),
|
||||
versionTag = require('./parts/VersionTagProps');
|
||||
|
||||
var listenerProps = require('./parts/ListenerProps'),
|
||||
listenerDetails = require('./parts/ListenerDetailProps'),
|
||||
listenerFields = require('./parts/ListenerFieldInjectionProps');
|
||||
|
||||
var elementTemplateChooserProps = require('./element-templates/parts/ChooserProps'),
|
||||
elementTemplateCustomProps = require('./element-templates/parts/CustomProps');
|
||||
|
||||
// Input/Output
|
||||
var inputOutput = require('./parts/InputOutputProps'),
|
||||
inputOutputParameter = require('./parts/InputOutputParameterProps');
|
||||
|
||||
// Connector
|
||||
var connectorDetails = require('./parts/ConnectorDetailProps'),
|
||||
connectorInputOutput = require('./parts/ConnectorInputOutputProps'),
|
||||
connectorInputOutputParameter = require('./parts/ConnectorInputOutputParameterProps');
|
||||
|
||||
// properties
|
||||
var properties = require('./parts/PropertiesProps');
|
||||
|
||||
// job configuration
|
||||
var jobConfiguration = require('./parts/JobConfigurationProps');
|
||||
|
||||
// history time to live
|
||||
var historyTimeToLive = require('./parts/HistoryTimeToLiveProps');
|
||||
|
||||
// candidate starter groups/users
|
||||
var candidateStarter = require('./parts/CandidateStarterProps');
|
||||
|
||||
// tasklist
|
||||
var tasklist = require('./parts/TasklistProps');
|
||||
|
||||
// external task configuration
|
||||
var externalTaskConfiguration = require('./parts/ExternalTaskConfigurationProps');
|
||||
|
||||
// field injection
|
||||
var fieldInjections = require('./parts/FieldInjectionProps');
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
eventDefinitionHelper = require('../../helper/EventDefinitionHelper'),
|
||||
implementationTypeHelper = require('../../helper/ImplementationTypeHelper');
|
||||
|
||||
// helpers ////////////////////////////////////////
|
||||
|
||||
var isExternalTaskPriorityEnabled = function(element) {
|
||||
var businessObject = getBusinessObject(element);
|
||||
|
||||
// show only if element is a process, a participant ...
|
||||
if (is(element, 'bpmn:Process') || is(element, 'bpmn:Participant') && businessObject.get('processRef')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var externalBo = ImplementationTypeHelper.getServiceTaskLikeBusinessObject(element),
|
||||
isExternalTask = ImplementationTypeHelper.getImplementationType(externalBo) === 'external';
|
||||
|
||||
// ... or an external task with selected external implementation type
|
||||
return !!ImplementationTypeHelper.isExternalCapable(externalBo) && isExternalTask;
|
||||
};
|
||||
|
||||
var isJobConfigEnabled = function(element) {
|
||||
var businessObject = getBusinessObject(element);
|
||||
|
||||
if (is(element, 'bpmn:Process') || is(element, 'bpmn:Participant') && businessObject.get('processRef')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// async behavior
|
||||
var bo = getBusinessObject(element);
|
||||
if (asyncCapableHelper.isAsyncBefore(bo) || asyncCapableHelper.isAsyncAfter(bo)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// timer definition
|
||||
if (is(element, 'bpmn:Event')) {
|
||||
return !!eventDefinitionHelper.getTimerEventDefinition(element);
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var getInputOutputParameterLabel = function(param, translate) {
|
||||
|
||||
if (is(param, 'activiti:InputParameter')) {
|
||||
return translate('Input Parameter');
|
||||
}
|
||||
|
||||
if (is(param, 'activiti:OutputParameter')) {
|
||||
return translate('Output Parameter');
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
var getListenerLabel = function(param, translate) {
|
||||
|
||||
if (is(param, 'activiti:ExecutionListener')) {
|
||||
return translate('Execution Listener');
|
||||
}
|
||||
|
||||
if (is(param, 'activiti:TaskListener')) {
|
||||
return translate('Task Listener');
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
var PROCESS_KEY_HINT = 'This maps to the process definition key.';
|
||||
var TASK_KEY_HINT = 'This maps to the task definition key.';
|
||||
|
||||
function createGeneralTabGroups(
|
||||
element, canvas, bpmnFactory,
|
||||
elementRegistry, elementTemplates, translate) {
|
||||
|
||||
// refer to target element for external labels
|
||||
element = element.labelTarget || element;
|
||||
|
||||
var generalGroup = {
|
||||
id: 'general',
|
||||
label: translate('General'),
|
||||
entries: []
|
||||
};
|
||||
|
||||
var idOptions;
|
||||
var processOptions;
|
||||
|
||||
if (is(element, 'bpmn:Process')) {
|
||||
idOptions = { description: PROCESS_KEY_HINT };
|
||||
}
|
||||
|
||||
if (is(element, 'bpmn:UserTask')) {
|
||||
idOptions = { description: TASK_KEY_HINT };
|
||||
}
|
||||
|
||||
if (is(element, 'bpmn:Participant')) {
|
||||
processOptions = { processIdDescription: PROCESS_KEY_HINT };
|
||||
}
|
||||
|
||||
idProps(generalGroup, element, translate, idOptions);
|
||||
nameProps(generalGroup, element, bpmnFactory, canvas, translate);
|
||||
processProps(generalGroup, element, translate, processOptions);
|
||||
versionTag(generalGroup, element, translate);
|
||||
executableProps(generalGroup, element, translate);
|
||||
elementTemplateChooserProps(generalGroup, element, elementTemplates, translate);
|
||||
|
||||
var customFieldsGroups = elementTemplateCustomProps(element, elementTemplates, bpmnFactory, translate);
|
||||
|
||||
var detailsGroup = {
|
||||
id: 'details',
|
||||
label: translate('Details'),
|
||||
entries: []
|
||||
};
|
||||
serviceTaskDelegateProps(detailsGroup, element, bpmnFactory, translate);
|
||||
userTaskProps(detailsGroup, element, translate);
|
||||
scriptProps(detailsGroup, element, bpmnFactory, translate);
|
||||
linkProps(detailsGroup, element, translate);
|
||||
callActivityProps(detailsGroup, element, bpmnFactory, translate);
|
||||
eventProps(detailsGroup, element, bpmnFactory, elementRegistry, translate);
|
||||
errorProps(detailsGroup, element, bpmnFactory, translate);
|
||||
conditionalProps(detailsGroup, element, bpmnFactory, translate);
|
||||
startEventInitiator(detailsGroup, element, translate); // this must be the last element of the details group!
|
||||
|
||||
var multiInstanceGroup = {
|
||||
id: 'multiInstance',
|
||||
label: translate('Multi Instance'),
|
||||
entries: []
|
||||
};
|
||||
multiInstanceProps(multiInstanceGroup, element, bpmnFactory, translate);
|
||||
|
||||
var asyncGroup = {
|
||||
id : 'async',
|
||||
label: translate('Asynchronous Continuations'),
|
||||
entries : []
|
||||
};
|
||||
asynchronousContinuationProps(asyncGroup, element, bpmnFactory, translate);
|
||||
|
||||
var jobConfigurationGroup = {
|
||||
id : 'jobConfiguration',
|
||||
label : translate('Job Configuration'),
|
||||
entries : [],
|
||||
enabled: isJobConfigEnabled
|
||||
};
|
||||
jobConfiguration(jobConfigurationGroup, element, bpmnFactory, translate);
|
||||
|
||||
var externalTaskGroup = {
|
||||
id : 'externalTaskConfiguration',
|
||||
label : translate('External Task Configuration'),
|
||||
entries : [],
|
||||
enabled: isExternalTaskPriorityEnabled
|
||||
};
|
||||
externalTaskConfiguration(externalTaskGroup, element, bpmnFactory, translate);
|
||||
|
||||
|
||||
var candidateStarterGroup = {
|
||||
id: 'candidateStarterConfiguration',
|
||||
label: translate('Candidate Starter Configuration'),
|
||||
entries: []
|
||||
};
|
||||
candidateStarter(candidateStarterGroup, element, bpmnFactory, translate);
|
||||
|
||||
var historyTimeToLiveGroup = {
|
||||
id: 'historyConfiguration',
|
||||
label: translate('History Configuration'),
|
||||
entries: []
|
||||
};
|
||||
historyTimeToLive(historyTimeToLiveGroup, element, bpmnFactory, translate);
|
||||
|
||||
var tasklistGroup = {
|
||||
id: 'tasklist',
|
||||
label: translate('Tasklist Configuration'),
|
||||
entries: []
|
||||
};
|
||||
tasklist(tasklistGroup, element, bpmnFactory, translate);
|
||||
|
||||
var documentationGroup = {
|
||||
id: 'documentation',
|
||||
label: translate('Documentation'),
|
||||
entries: []
|
||||
};
|
||||
documentationProps(documentationGroup, element, bpmnFactory, translate);
|
||||
|
||||
var groups = [];
|
||||
groups.push(generalGroup);
|
||||
customFieldsGroups.forEach(function(group) {
|
||||
groups.push(group);
|
||||
});
|
||||
groups.push(detailsGroup);
|
||||
groups.push(externalTaskGroup);
|
||||
groups.push(multiInstanceGroup);
|
||||
groups.push(asyncGroup);
|
||||
groups.push(jobConfigurationGroup);
|
||||
groups.push(candidateStarterGroup);
|
||||
groups.push(historyTimeToLiveGroup);
|
||||
groups.push(tasklistGroup);
|
||||
groups.push(documentationGroup);
|
||||
|
||||
return groups;
|
||||
}
|
||||
|
||||
function createVariablesTabGroups(element, bpmnFactory, elementRegistry, translate) {
|
||||
var variablesGroup = {
|
||||
id : 'variables',
|
||||
label : translate('Variables'),
|
||||
entries: []
|
||||
};
|
||||
variableMapping(variablesGroup, element, bpmnFactory, translate);
|
||||
|
||||
return [
|
||||
variablesGroup
|
||||
];
|
||||
}
|
||||
|
||||
function createFormsTabGroups(element, bpmnFactory, elementRegistry, translate) {
|
||||
var formGroup = {
|
||||
id : 'forms',
|
||||
label : translate('Forms'),
|
||||
entries: []
|
||||
};
|
||||
formProps(formGroup, element, bpmnFactory, translate);
|
||||
|
||||
return [
|
||||
formGroup
|
||||
];
|
||||
}
|
||||
|
||||
function createListenersTabGroups(element, bpmnFactory, elementRegistry, translate) {
|
||||
|
||||
var listenersGroup = {
|
||||
id : 'listeners',
|
||||
label: translate('Listeners'),
|
||||
entries: []
|
||||
};
|
||||
|
||||
var options = listenerProps(listenersGroup, element, bpmnFactory, translate);
|
||||
|
||||
var listenerDetailsGroup = {
|
||||
id: 'listener-details',
|
||||
entries: [],
|
||||
enabled: function(element, node) {
|
||||
return options.getSelectedListener(element, node);
|
||||
},
|
||||
label: function(element, node) {
|
||||
var param = options.getSelectedListener(element, node);
|
||||
return getListenerLabel(param, translate);
|
||||
}
|
||||
};
|
||||
|
||||
listenerDetails(listenerDetailsGroup, element, bpmnFactory, options, translate);
|
||||
|
||||
var listenerFieldsGroup = {
|
||||
id: 'listener-fields',
|
||||
label: translate('Field Injection'),
|
||||
entries: [],
|
||||
enabled: function(element, node) {
|
||||
return options.getSelectedListener(element, node);
|
||||
}
|
||||
};
|
||||
|
||||
listenerFields(listenerFieldsGroup, element, bpmnFactory, options, translate);
|
||||
|
||||
return [
|
||||
listenersGroup,
|
||||
listenerDetailsGroup,
|
||||
listenerFieldsGroup
|
||||
];
|
||||
}
|
||||
|
||||
function createInputOutputTabGroups(element, bpmnFactory, elementRegistry, translate) {
|
||||
|
||||
var inputOutputGroup = {
|
||||
id: 'input-output',
|
||||
label: translate('Parameters'),
|
||||
entries: []
|
||||
};
|
||||
|
||||
var options = inputOutput(inputOutputGroup, element, bpmnFactory, translate);
|
||||
|
||||
var inputOutputParameterGroup = {
|
||||
id: 'input-output-parameter',
|
||||
entries: [],
|
||||
enabled: function(element, node) {
|
||||
return options.getSelectedParameter(element, node);
|
||||
},
|
||||
label: function(element, node) {
|
||||
var param = options.getSelectedParameter(element, node);
|
||||
return getInputOutputParameterLabel(param, translate);
|
||||
}
|
||||
};
|
||||
|
||||
inputOutputParameter(inputOutputParameterGroup, element, bpmnFactory, options, translate);
|
||||
|
||||
return [
|
||||
inputOutputGroup,
|
||||
inputOutputParameterGroup
|
||||
];
|
||||
}
|
||||
|
||||
function createConnectorTabGroups(element, bpmnFactory, elementRegistry, translate) {
|
||||
var connectorDetailsGroup = {
|
||||
id: 'connector-details',
|
||||
label: translate('Details'),
|
||||
entries: []
|
||||
};
|
||||
|
||||
connectorDetails(connectorDetailsGroup, element, bpmnFactory, translate);
|
||||
|
||||
var connectorInputOutputGroup = {
|
||||
id: 'connector-input-output',
|
||||
label: translate('Input/Output'),
|
||||
entries: []
|
||||
};
|
||||
|
||||
var options = connectorInputOutput(connectorInputOutputGroup, element, bpmnFactory, translate);
|
||||
|
||||
var connectorInputOutputParameterGroup = {
|
||||
id: 'connector-input-output-parameter',
|
||||
entries: [],
|
||||
enabled: function(element, node) {
|
||||
return options.getSelectedParameter(element, node);
|
||||
},
|
||||
label: function(element, node) {
|
||||
var param = options.getSelectedParameter(element, node);
|
||||
return getInputOutputParameterLabel(param, translate);
|
||||
}
|
||||
};
|
||||
|
||||
connectorInputOutputParameter(connectorInputOutputParameterGroup, element, bpmnFactory, options, translate);
|
||||
|
||||
return [
|
||||
connectorDetailsGroup,
|
||||
connectorInputOutputGroup,
|
||||
connectorInputOutputParameterGroup
|
||||
];
|
||||
}
|
||||
|
||||
function createFieldInjectionsTabGroups(element, bpmnFactory, elementRegistry, translate) {
|
||||
|
||||
var fieldGroup = {
|
||||
id: 'field-injections-properties',
|
||||
label: translate('Field Injections'),
|
||||
entries: []
|
||||
};
|
||||
|
||||
fieldInjections(fieldGroup, element, bpmnFactory, translate);
|
||||
|
||||
return [
|
||||
fieldGroup
|
||||
];
|
||||
}
|
||||
|
||||
function createExtensionElementsGroups(element, bpmnFactory, elementRegistry, translate) {
|
||||
|
||||
var propertiesGroup = {
|
||||
id : 'extensionElements-properties',
|
||||
label: translate('Properties'),
|
||||
entries: []
|
||||
};
|
||||
properties(propertiesGroup, element, bpmnFactory, translate);
|
||||
|
||||
return [
|
||||
propertiesGroup
|
||||
];
|
||||
}
|
||||
|
||||
// activiti Properties Provider /////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* A properties provider for activiti related properties.
|
||||
*
|
||||
* @param {EventBus} eventBus
|
||||
* @param {Canvas} canvas
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
* @param {ElementRegistry} elementRegistry
|
||||
* @param {ElementTemplates} elementTemplates
|
||||
* @param {Translate} translate
|
||||
*/
|
||||
function ActivitiPropertiesProvider(
|
||||
eventBus, canvas, bpmnFactory,
|
||||
elementRegistry, elementTemplates, translate) {
|
||||
|
||||
PropertiesActivator.call(this, eventBus);
|
||||
|
||||
this.getTabs = function(element) {
|
||||
|
||||
var generalTab = {
|
||||
id: 'general',
|
||||
label: translate('General'),
|
||||
groups: createGeneralTabGroups(
|
||||
element, canvas, bpmnFactory,
|
||||
elementRegistry, elementTemplates, translate)
|
||||
};
|
||||
|
||||
var variablesTab = {
|
||||
id: 'variables',
|
||||
label: translate('Variables'),
|
||||
groups: createVariablesTabGroups(element, bpmnFactory, elementRegistry, translate)
|
||||
};
|
||||
|
||||
var formsTab = {
|
||||
id: 'forms',
|
||||
label: translate('Forms'),
|
||||
groups: createFormsTabGroups(element, bpmnFactory, elementRegistry, translate)
|
||||
};
|
||||
|
||||
var listenersTab = {
|
||||
id: 'listeners',
|
||||
label: translate('Listeners'),
|
||||
groups: createListenersTabGroups(element, bpmnFactory, elementRegistry, translate),
|
||||
enabled: function(element) {
|
||||
return !eventDefinitionHelper.getLinkEventDefinition(element)
|
||||
|| (!is(element, 'bpmn:IntermediateThrowEvent')
|
||||
&& eventDefinitionHelper.getLinkEventDefinition(element));
|
||||
}
|
||||
};
|
||||
|
||||
var inputOutputTab = {
|
||||
id: 'input-output',
|
||||
label: translate('Input/Output'),
|
||||
groups: createInputOutputTabGroups(element, bpmnFactory, elementRegistry, translate)
|
||||
};
|
||||
|
||||
var connectorTab = {
|
||||
id: 'connector',
|
||||
label: translate('Connector'),
|
||||
groups: createConnectorTabGroups(element, bpmnFactory, elementRegistry, translate),
|
||||
enabled: function(element) {
|
||||
var bo = implementationTypeHelper.getServiceTaskLikeBusinessObject(element);
|
||||
return bo && implementationTypeHelper.getImplementationType(bo) === 'connector';
|
||||
}
|
||||
};
|
||||
|
||||
var fieldInjectionsTab = {
|
||||
id: 'field-injections',
|
||||
label: translate('Field Injections'),
|
||||
groups: createFieldInjectionsTabGroups(element, bpmnFactory, elementRegistry, translate)
|
||||
};
|
||||
|
||||
var extensionsTab = {
|
||||
id: 'extensionElements',
|
||||
label: translate('Extensions'),
|
||||
groups: createExtensionElementsGroups(element, bpmnFactory, elementRegistry, translate)
|
||||
};
|
||||
|
||||
return [
|
||||
generalTab,
|
||||
variablesTab,
|
||||
connectorTab,
|
||||
formsTab,
|
||||
listenersTab,
|
||||
inputOutputTab,
|
||||
fieldInjectionsTab,
|
||||
extensionsTab
|
||||
];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
ActivitiPropertiesProvider.$inject = [
|
||||
'eventBus',
|
||||
'canvas',
|
||||
'bpmnFactory',
|
||||
'elementRegistry',
|
||||
'elementTemplates',
|
||||
'translate'
|
||||
];
|
||||
|
||||
inherits(ActivitiPropertiesProvider, PropertiesActivator);
|
||||
|
||||
module.exports = ActivitiPropertiesProvider;
|
@ -0,0 +1,251 @@
|
||||
'use strict';
|
||||
|
||||
var assign = require('lodash/assign');
|
||||
|
||||
/**
|
||||
* Create an input parameter representing the given
|
||||
* binding and value.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createInputParameter(binding, value, bpmnFactory) {
|
||||
var scriptFormat = binding.scriptFormat,
|
||||
parameterValue,
|
||||
parameterDefinition;
|
||||
|
||||
if (scriptFormat) {
|
||||
parameterDefinition = bpmnFactory.create('activiti:Script', {
|
||||
scriptFormat: scriptFormat,
|
||||
value: value
|
||||
});
|
||||
} else {
|
||||
parameterValue = value;
|
||||
}
|
||||
|
||||
return bpmnFactory.create('activiti:InputParameter', {
|
||||
name: binding.name,
|
||||
value: parameterValue,
|
||||
definition: parameterDefinition
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.createInputParameter = createInputParameter;
|
||||
|
||||
|
||||
/**
|
||||
* Create an output parameter representing the given
|
||||
* binding and value.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createOutputParameter(binding, value, bpmnFactory) {
|
||||
var scriptFormat = binding.scriptFormat,
|
||||
parameterValue,
|
||||
parameterDefinition;
|
||||
|
||||
if (scriptFormat) {
|
||||
parameterDefinition = bpmnFactory.create('activiti:Script', {
|
||||
scriptFormat: scriptFormat,
|
||||
value: binding.source
|
||||
});
|
||||
} else {
|
||||
parameterValue = binding.source;
|
||||
}
|
||||
|
||||
return bpmnFactory.create('activiti:OutputParameter', {
|
||||
name: value,
|
||||
value: parameterValue,
|
||||
definition: parameterDefinition
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.createOutputParameter = createOutputParameter;
|
||||
|
||||
|
||||
/**
|
||||
* Create activiti property from the given binding.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createActivitiProperty(binding, value, bpmnFactory) {
|
||||
return bpmnFactory.create('activiti:Property', {
|
||||
name: binding.name,
|
||||
value: value || ''
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.createActivitiProperty = createActivitiProperty;
|
||||
|
||||
|
||||
/**
|
||||
* Create activiti:in element from given binding.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createActivitiIn(binding, value, bpmnFactory) {
|
||||
|
||||
var properties = createActivitiInOutAttrs(binding, value);
|
||||
|
||||
return bpmnFactory.create('activiti:In', properties);
|
||||
}
|
||||
|
||||
module.exports.createActivitiIn = createActivitiIn;
|
||||
|
||||
|
||||
/**
|
||||
* Create activiti:in with businessKey element from given binding.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createActivitiInWithBusinessKey(binding, value, bpmnFactory) {
|
||||
return bpmnFactory.create('activiti:In', {
|
||||
businessKey: value
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.createActivitiInWithBusinessKey = createActivitiInWithBusinessKey;
|
||||
|
||||
|
||||
/**
|
||||
* Create activiti:out element from given binding.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createActivitiOut(binding, value, bpmnFactory) {
|
||||
var properties = createActivitiInOutAttrs(binding, value);
|
||||
|
||||
return bpmnFactory.create('activiti:Out', properties);
|
||||
}
|
||||
|
||||
module.exports.createActivitiOut = createActivitiOut;
|
||||
|
||||
|
||||
/**
|
||||
* Create activiti:executionListener element containing an inline script from given binding.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createActivitiExecutionListenerScript(binding, value, bpmnFactory) {
|
||||
var scriptFormat = binding.scriptFormat,
|
||||
parameterValue,
|
||||
parameterDefinition;
|
||||
|
||||
if (scriptFormat) {
|
||||
parameterDefinition = bpmnFactory.create('activiti:Script', {
|
||||
scriptFormat: scriptFormat,
|
||||
value: value
|
||||
});
|
||||
} else {
|
||||
parameterValue = value;
|
||||
}
|
||||
|
||||
return bpmnFactory.create('activiti:ExecutionListener', {
|
||||
event: binding.event,
|
||||
value: parameterValue,
|
||||
script: parameterDefinition
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.createActivitiExecutionListenerScript = createActivitiExecutionListenerScript;
|
||||
|
||||
/**
|
||||
* Create activiti:field element containing string or expression from given binding.
|
||||
*
|
||||
* @param {PropertyBinding} binding
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {ModdleElement}
|
||||
*/
|
||||
function createActivitiFieldInjection(binding, value, bpmnFactory) {
|
||||
var DEFAULT_PROPS = {
|
||||
'string': undefined,
|
||||
'expression': undefined,
|
||||
'name': undefined
|
||||
};
|
||||
|
||||
var props = assign({}, DEFAULT_PROPS);
|
||||
|
||||
if (!binding.expression) {
|
||||
props.string = value;
|
||||
} else {
|
||||
props.expression = value;
|
||||
}
|
||||
props.name = binding.name;
|
||||
|
||||
return bpmnFactory.create('activiti:Field', props);
|
||||
}
|
||||
module.exports.createActivitiFieldInjection = createActivitiFieldInjection;
|
||||
|
||||
|
||||
// helpers ////////////////////////////
|
||||
|
||||
/**
|
||||
* Create properties for activiti:in and activiti:out types.
|
||||
*/
|
||||
function createActivitiInOutAttrs(binding, value) {
|
||||
|
||||
var properties = {};
|
||||
|
||||
// activiti:in source(Expression) target
|
||||
if (binding.target) {
|
||||
|
||||
properties.target = binding.target;
|
||||
|
||||
if (binding.expression) {
|
||||
properties.sourceExpression = value;
|
||||
} else {
|
||||
properties.source = value;
|
||||
}
|
||||
} else
|
||||
|
||||
// activiti:(in|out) variables local
|
||||
if (binding.variables) {
|
||||
properties.variables = 'all';
|
||||
|
||||
if (binding.variables === 'local') {
|
||||
properties.local = true;
|
||||
}
|
||||
}
|
||||
|
||||
// activiti:out source(Expression) target
|
||||
else {
|
||||
properties.target = value;
|
||||
|
||||
[ 'source', 'sourceExpression' ].forEach(function(k) {
|
||||
if (binding[k]) {
|
||||
properties[k] = binding[k];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
'use strict';
|
||||
|
||||
var inherits = require('inherits');
|
||||
|
||||
var getTemplate = require('./Helper').getTemplate;
|
||||
|
||||
var PropertiesActivator = require('../../../PropertiesActivator');
|
||||
|
||||
var HIGHER_PRIORITY = 1100;
|
||||
|
||||
/**
|
||||
* Applies template visibility settings.
|
||||
*
|
||||
* Controlled using `entriesVisible` on template config object:
|
||||
*
|
||||
* ```json
|
||||
* "entriesVisible": {
|
||||
* "_all": true|false,
|
||||
* "entryName": true|false,
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param {EventBus} eventBus
|
||||
* @param {ElementTemplates} elementTemplates
|
||||
*/
|
||||
function CustomElementsPropertiesActivator(eventBus, elementTemplates) {
|
||||
PropertiesActivator.call(this, eventBus, HIGHER_PRIORITY);
|
||||
|
||||
this.isEntryVisible = function(entry, element) {
|
||||
|
||||
var template = getTemplate(element, elementTemplates);
|
||||
|
||||
if (template && !isEntryVisible(entry, template)) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
this.isPropertyEditable = function(entry, propertyName, element) {
|
||||
|
||||
var template = getTemplate(element, elementTemplates);
|
||||
|
||||
if (template && !isEntryEditable(entry, template)) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
CustomElementsPropertiesActivator.$inject = [ 'eventBus', 'elementTemplates' ];
|
||||
|
||||
inherits(CustomElementsPropertiesActivator, PropertiesActivator);
|
||||
|
||||
module.exports = CustomElementsPropertiesActivator;
|
||||
|
||||
|
||||
|
||||
// helpers ////////////////////////////////////
|
||||
|
||||
|
||||
var CUSTOM_PROPERTIES_PATTERN = /^custom-/;
|
||||
|
||||
var DEFAULT_ENTRIES_VISIBLE = {
|
||||
_all: false,
|
||||
id: true,
|
||||
name: true
|
||||
};
|
||||
|
||||
function isCustomEntry(entry) {
|
||||
return CUSTOM_PROPERTIES_PATTERN.test(entry.id);
|
||||
}
|
||||
|
||||
function isEntryVisible(entry, template) {
|
||||
|
||||
var entryId = entry.id;
|
||||
|
||||
if (entryId === 'elementTemplate-chooser' || isCustomEntry(entry)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var entriesVisible = template.entriesVisible || DEFAULT_ENTRIES_VISIBLE;
|
||||
|
||||
if (typeof entriesVisible === 'boolean') {
|
||||
return entriesVisible;
|
||||
}
|
||||
|
||||
var defaultVisible = entriesVisible._all || false,
|
||||
entryVisible = entriesVisible[entryId];
|
||||
|
||||
// d = true, e = false => false
|
||||
// d = false, e = true => true
|
||||
// d = false, e = false
|
||||
return (
|
||||
(defaultVisible === true && entryVisible !== false) ||
|
||||
(defaultVisible === false && entryVisible === true)
|
||||
);
|
||||
}
|
||||
|
||||
function isEntryEditable(entry, template) {
|
||||
|
||||
var property;
|
||||
|
||||
if (isCustomEntry(entry)) {
|
||||
property = getProperty(template, entry);
|
||||
|
||||
return property && property.editable !== false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function getProperty(template, entry) {
|
||||
|
||||
var index;
|
||||
var idx = entry.id.replace('custom-' + template.id + '-', '');
|
||||
if (idx.indexOf('-') !== -1) {
|
||||
var indexes = idx.split('-');
|
||||
if (indexes.length == 2) {
|
||||
var scopeName = indexes[0].replace(/_/g, ':');
|
||||
index = parseInt(indexes[1], 10);
|
||||
if (scopeName && !isNaN(index)) {
|
||||
return template.scopes[scopeName].properties[index];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
index = parseInt(idx, 10);
|
||||
if (!isNaN(index)) {
|
||||
return template.properties[index];
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('cannot extract property index for entry <' + entry.id + '>');
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
|
||||
var values = require('lodash/values');
|
||||
|
||||
/**
|
||||
* The guy knowing all configured element templates.
|
||||
*
|
||||
* This registry won't validate. Use the {@link Validator}
|
||||
* to verify a template is valid prior to adding it to
|
||||
* this registry.
|
||||
*/
|
||||
function ElementTemplates() {
|
||||
|
||||
this._templates = {};
|
||||
|
||||
/**
|
||||
* Sets the known element templates.
|
||||
*
|
||||
* @param {Array<TemplateDescriptor>} descriptors
|
||||
*
|
||||
* @return {ElementTemplates}
|
||||
*/
|
||||
this.set = function(descriptors) {
|
||||
|
||||
var templates = this._templates = {};
|
||||
|
||||
descriptors.forEach(function(descriptor) {
|
||||
templates[descriptor.id] = descriptor;
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get template descriptor with given id.
|
||||
*
|
||||
* @param {String} id
|
||||
*
|
||||
* @return {TemplateDescriptor}
|
||||
*/
|
||||
this.get = function(id) {
|
||||
return this._templates[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Return all known template descriptors.
|
||||
*
|
||||
* @return {Array<TemplateDescriptor>}
|
||||
*/
|
||||
this.getAll = function() {
|
||||
return values(this._templates);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
module.exports = ElementTemplates;
|
@ -0,0 +1,96 @@
|
||||
'use strict';
|
||||
|
||||
var Validator = require('./Validator');
|
||||
|
||||
/**
|
||||
* The guy responsible for template loading.
|
||||
*
|
||||
* Provide the actual templates via the `config.elementTemplates`.
|
||||
*
|
||||
* That configuration can either be an array of template
|
||||
* descriptors or a node style callback to retrieve
|
||||
* the templates asynchronously.
|
||||
*
|
||||
* @param {Array<TemplateDescriptor>|Function} loadTemplates
|
||||
* @param {EventBus} eventBus
|
||||
* @param {ElementTemplates} elementTemplates
|
||||
*/
|
||||
function ElementTemplatesLoader(loadTemplates, eventBus, elementTemplates) {
|
||||
this._loadTemplates = loadTemplates;
|
||||
this._eventBus = eventBus;
|
||||
this._elementTemplates = elementTemplates;
|
||||
|
||||
var self = this;
|
||||
|
||||
eventBus.on('diagram.init', function() {
|
||||
self.reload();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = ElementTemplatesLoader;
|
||||
|
||||
ElementTemplatesLoader.$inject = [
|
||||
'config.elementTemplates',
|
||||
'eventBus',
|
||||
'elementTemplates'
|
||||
];
|
||||
|
||||
|
||||
ElementTemplatesLoader.prototype.reload = function() {
|
||||
|
||||
var self = this;
|
||||
|
||||
var loadTemplates = this._loadTemplates;
|
||||
|
||||
// no templates specified
|
||||
if (typeof loadTemplates === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
// template loader function specified
|
||||
if (typeof loadTemplates === 'function') {
|
||||
|
||||
return loadTemplates(function(err, templates) {
|
||||
|
||||
if (err) {
|
||||
return self.templateErrors([ err ]);
|
||||
}
|
||||
|
||||
self.setTemplates(templates);
|
||||
});
|
||||
}
|
||||
|
||||
// templates array specified
|
||||
if (loadTemplates.length) {
|
||||
return this.setTemplates(loadTemplates);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ElementTemplatesLoader.prototype.setTemplates = function(templates) {
|
||||
|
||||
var elementTemplates = this._elementTemplates;
|
||||
|
||||
var validator = new Validator().addAll(templates);
|
||||
|
||||
var errors = validator.getErrors(),
|
||||
validTemplates = validator.getValidTemplates();
|
||||
|
||||
elementTemplates.set(validTemplates);
|
||||
|
||||
if (errors.length) {
|
||||
this.templateErrors(errors);
|
||||
}
|
||||
|
||||
this.templatesChanged();
|
||||
};
|
||||
|
||||
ElementTemplatesLoader.prototype.templatesChanged = function() {
|
||||
this._eventBus.fire('elementTemplates.changed');
|
||||
};
|
||||
|
||||
ElementTemplatesLoader.prototype.templateErrors = function(errors) {
|
||||
this._eventBus.fire('elementTemplates.errors', {
|
||||
errors: errors
|
||||
});
|
||||
};
|
@ -0,0 +1,239 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
isAny = require('bpmn-js/lib/features/modeling/util/ModelingUtil').isAny;
|
||||
|
||||
var find = require('lodash/find');
|
||||
|
||||
|
||||
var TEMPLATE_ATTR = 'activiti:modelerTemplate';
|
||||
|
||||
/**
|
||||
* The BPMN 2.0 extension attribute name under
|
||||
* which the element template is stored.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
module.exports.TEMPLATE_ATTR = TEMPLATE_ATTR;
|
||||
|
||||
|
||||
/**
|
||||
* Get template id for a given diagram element.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
*
|
||||
* @return {String}
|
||||
*/
|
||||
function getTemplateId(element) {
|
||||
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (bo) {
|
||||
return bo.get(TEMPLATE_ATTR);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.getTemplateId = getTemplateId;
|
||||
|
||||
|
||||
/**
|
||||
* Get template of a given element.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @param {ElementTemplates} elementTemplates
|
||||
*
|
||||
* @return {TemplateDefinition}
|
||||
*/
|
||||
function getTemplate(element, elementTemplates) {
|
||||
var id = getTemplateId(element);
|
||||
|
||||
return id && elementTemplates.get(id);
|
||||
}
|
||||
|
||||
module.exports.getTemplate = getTemplate;
|
||||
|
||||
/**
|
||||
* Get default template for a given element.
|
||||
*
|
||||
* @param {Element} element
|
||||
* @param {ElementTemplates} elementTemplates
|
||||
*
|
||||
* @return {TemplateDefinition}
|
||||
*/
|
||||
function getDefaultTemplate(element, elementTemplates) {
|
||||
|
||||
// return first default template, if any exists
|
||||
return (
|
||||
elementTemplates.getAll().filter(function(t) {
|
||||
return isAny(element, t.appliesTo) && t.isDefault;
|
||||
})
|
||||
)[0];
|
||||
}
|
||||
|
||||
module.exports.getDefaultTemplate = getDefaultTemplate;
|
||||
|
||||
|
||||
/**
|
||||
* Find extension with given type in
|
||||
* BPMN element, diagram element or ExtensionElement.
|
||||
*
|
||||
* @param {ModdleElement|djs.model.Base} element
|
||||
* @param {String} type
|
||||
*
|
||||
* @return {ModdleElement} the extension
|
||||
*/
|
||||
function findExtension(element, type) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
var extensionElements;
|
||||
|
||||
if (is(bo, 'bpmn:ExtensionElements')) {
|
||||
extensionElements = bo;
|
||||
} else {
|
||||
extensionElements = bo.extensionElements;
|
||||
}
|
||||
|
||||
if (!extensionElements) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return find(extensionElements.get('values'), function(e) {
|
||||
return is(e, type);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.findExtension = findExtension;
|
||||
|
||||
|
||||
function findExtensions(element, types) {
|
||||
var extensionElements = getExtensionElements(element);
|
||||
|
||||
if (!extensionElements) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return extensionElements.get('values').filter(function(e) {
|
||||
return isAny(e, types);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.findExtensions = findExtensions;
|
||||
|
||||
|
||||
function findActivitiInOut(element, binding) {
|
||||
|
||||
var extensionElements = getExtensionElements(element);
|
||||
|
||||
if (!extensionElements) {
|
||||
return;
|
||||
}
|
||||
|
||||
var matcher;
|
||||
|
||||
if (binding.type === 'activiti:in') {
|
||||
matcher = function(e) {
|
||||
return is(e, 'activiti:In') && isInOut(e, binding);
|
||||
};
|
||||
} else
|
||||
if (binding.type === 'activiti:out') {
|
||||
matcher = function(e) {
|
||||
return is(e, 'activiti:Out') && isInOut(e, binding);
|
||||
};
|
||||
} else
|
||||
if (binding.type === 'activiti:in:businessKey') {
|
||||
matcher = function(e) {
|
||||
return is(e, 'activiti:In') && 'businessKey' in e;
|
||||
};
|
||||
}
|
||||
|
||||
return find(extensionElements.get('values'), matcher);
|
||||
}
|
||||
|
||||
module.exports.findActivitiInOut = findActivitiInOut;
|
||||
|
||||
function findActivitiProperty(activitiProperties, binding) {
|
||||
return find(activitiProperties.get('values'), function(p) {
|
||||
return p.name === binding.name;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.findActivitiProperty = findActivitiProperty;
|
||||
|
||||
|
||||
function findInputParameter(inputOutput, binding) {
|
||||
var parameters = inputOutput.get('inputParameters');
|
||||
|
||||
return find(parameters, function(p) {
|
||||
return p.name === binding.name;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.findInputParameter = findInputParameter;
|
||||
|
||||
|
||||
function findOutputParameter(inputOutput, binding) {
|
||||
var parameters = inputOutput.get('outputParameters');
|
||||
|
||||
return find(parameters, function(p) {
|
||||
var value = p.value;
|
||||
|
||||
if (!binding.scriptFormat) {
|
||||
return value === binding.source;
|
||||
}
|
||||
|
||||
var definition = p.definition;
|
||||
|
||||
if (!definition || binding.scriptFormat !== definition.scriptFormat) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return definition.value === binding.source;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.findOutputParameter = findOutputParameter;
|
||||
|
||||
|
||||
|
||||
// helpers /////////////////////////////////
|
||||
|
||||
function getExtensionElements(element) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (is(bo, 'bpmn:ExtensionElements')) {
|
||||
return bo;
|
||||
} else {
|
||||
return bo.extensionElements;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function isInOut(element, binding) {
|
||||
|
||||
if (binding.type === 'activiti:in') {
|
||||
// find based on target attribute
|
||||
if (binding.target) {
|
||||
return element.target === binding.target;
|
||||
}
|
||||
}
|
||||
|
||||
if (binding.type === 'activiti:out') {
|
||||
// find based on source / sourceExpression
|
||||
if (binding.source) {
|
||||
return element.source === binding.source;
|
||||
}
|
||||
|
||||
if (binding.sourceExpression) {
|
||||
return element.sourceExpression === binding.sourceExpression;
|
||||
}
|
||||
}
|
||||
|
||||
// find based variables / local combination
|
||||
if (binding.variables) {
|
||||
return element.variables === 'all' && (
|
||||
binding.variables !== 'local' || element.local
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
'use strict';
|
||||
|
||||
var isArray = require('lodash/isArray');
|
||||
var isObject = require('lodash/isObject');
|
||||
|
||||
var DROPDOWN_TYPE = 'Dropdown';
|
||||
|
||||
var VALID_TYPES = [ 'String', 'Text', 'Boolean', 'Hidden', DROPDOWN_TYPE ];
|
||||
|
||||
var PROPERTY_TYPE = 'property',
|
||||
ACTIVITI_PROPERTY_TYPE = 'activiti:property',
|
||||
ACTIVITI_INPUT_PARAMETER_TYPE = 'activiti:inputParameter',
|
||||
ACTIVITI_OUTPUT_PARAMETER_TYPE = 'activiti:outputParameter',
|
||||
ACTIVITI_IN_TYPE = 'activiti:in',
|
||||
ACTIVITI_OUT_TYPE = 'activiti:out',
|
||||
ACTIVITI_IN_BUSINESS_KEY_TYPE = 'activiti:in:businessKey',
|
||||
ACTIVITI_EXECUTION_LISTENER = 'activiti:executionListener',
|
||||
ACTIVITI_FIELD = 'activiti:field';
|
||||
|
||||
var VALID_BINDING_TYPES = [
|
||||
PROPERTY_TYPE,
|
||||
ACTIVITI_PROPERTY_TYPE,
|
||||
ACTIVITI_INPUT_PARAMETER_TYPE,
|
||||
ACTIVITI_OUTPUT_PARAMETER_TYPE,
|
||||
ACTIVITI_IN_TYPE,
|
||||
ACTIVITI_OUT_TYPE,
|
||||
ACTIVITI_IN_BUSINESS_KEY_TYPE,
|
||||
ACTIVITI_EXECUTION_LISTENER,
|
||||
ACTIVITI_FIELD
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* A element template validator.
|
||||
*/
|
||||
function Validator() {
|
||||
|
||||
this._templatesById = {};
|
||||
|
||||
this._validTemplates = [];
|
||||
this._errors = [];
|
||||
|
||||
|
||||
/**
|
||||
* Adds the templates.
|
||||
*
|
||||
* @param {Array<TemplateDescriptor>} templates
|
||||
*
|
||||
* @return {Validator} self
|
||||
*/
|
||||
this.addAll = function(templates) {
|
||||
|
||||
if (!isArray(templates)) {
|
||||
this._logError('templates must be []');
|
||||
} else {
|
||||
templates.forEach(this.add, this);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the given element template, if it is valid.
|
||||
*
|
||||
* @param {TemplateDescriptor} template
|
||||
*
|
||||
* @return {Validator} self
|
||||
*/
|
||||
this.add = function(template) {
|
||||
|
||||
var err = this._validateTemplate(template);
|
||||
|
||||
if (!err) {
|
||||
this._templatesById[template.id] = template;
|
||||
|
||||
this._validTemplates.push(template);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate given template and return error (if any).
|
||||
*
|
||||
* @param {TemplateDescriptor} template
|
||||
*
|
||||
* @return {Error} validation error, if any
|
||||
*/
|
||||
this._validateTemplate = function(template) {
|
||||
|
||||
var err,
|
||||
id = template.id,
|
||||
appliesTo = template.appliesTo,
|
||||
properties = template.properties,
|
||||
scopes = template.scopes;
|
||||
|
||||
if (!id) {
|
||||
return this._logError('missing template id');
|
||||
}
|
||||
|
||||
if (id in this._templatesById) {
|
||||
return this._logError('template id <' + id + '> already used');
|
||||
}
|
||||
|
||||
if (!isArray(appliesTo)) {
|
||||
err = this._logError('missing appliesTo=[]', template);
|
||||
}
|
||||
|
||||
if (!isArray(properties)) {
|
||||
err = this._logError('missing properties=[]', template);
|
||||
} else {
|
||||
if (!this._validateProperties(properties)) {
|
||||
err = new Error('invalid properties');
|
||||
}
|
||||
}
|
||||
|
||||
if (scopes) {
|
||||
err = this._validateScopes(template, scopes);
|
||||
}
|
||||
|
||||
return err;
|
||||
};
|
||||
|
||||
this._validateScopes = function(template, scopes) {
|
||||
|
||||
var err,
|
||||
scope,
|
||||
scopeName;
|
||||
|
||||
if (!isObject(scopes) || isArray(scopes)) {
|
||||
return this._logError('invalid scopes, should be scopes={}', template);
|
||||
}
|
||||
|
||||
for (scopeName in scopes) {
|
||||
scope = scopes[scopeName];
|
||||
|
||||
if (!isObject(scope) || isArray(scope)) {
|
||||
err = this._logError('invalid scope, should be scope={}', template);
|
||||
}
|
||||
|
||||
if (!isArray(scope.properties)) {
|
||||
err = this._logError(
|
||||
'missing properties=[] in scope <' + scopeName + '>', template
|
||||
);
|
||||
} else {
|
||||
if (!this._validateProperties(scope.properties)) {
|
||||
err = new Error('invalid properties in scope <' + scopeName + '>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate properties and return false if any is invalid.
|
||||
*
|
||||
* @param {Array<PropertyDescriptor>} properties
|
||||
*
|
||||
* @return {Boolean} true if all properties are valid
|
||||
*/
|
||||
this._validateProperties = function(properties) {
|
||||
var validProperties = properties.filter(this._validateProperty, this);
|
||||
|
||||
return properties.length === validProperties.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate property and return false, if there was
|
||||
* a validation error.
|
||||
*
|
||||
* @param {PropertyDescriptor} property
|
||||
*
|
||||
* @return {Boolean} true if property is valid
|
||||
*/
|
||||
this._validateProperty = function(property) {
|
||||
|
||||
var type = property.type,
|
||||
binding = property.binding;
|
||||
|
||||
var err;
|
||||
|
||||
var bindingType = binding.type;
|
||||
|
||||
if (VALID_TYPES.indexOf(type) === -1) {
|
||||
err = this._logError(
|
||||
'invalid property type <' + type + '>; ' +
|
||||
'must be any of { ' + VALID_TYPES.join(', ') + ' }'
|
||||
);
|
||||
}
|
||||
|
||||
if (type === DROPDOWN_TYPE && bindingType !== ACTIVITI_EXECUTION_LISTENER) {
|
||||
if (!isArray(property.choices)) {
|
||||
err = this._logError(
|
||||
'must provide choices=[] with ' + DROPDOWN_TYPE + ' type'
|
||||
);
|
||||
} else
|
||||
|
||||
if (!property.choices.every(isDropdownChoiceValid)) {
|
||||
err = this._logError(
|
||||
'{ name, value } must be specified for ' +
|
||||
DROPDOWN_TYPE + ' choices'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!binding) {
|
||||
return this._logError('property missing binding');
|
||||
}
|
||||
|
||||
if (VALID_BINDING_TYPES.indexOf(bindingType) === -1) {
|
||||
err = this._logError(
|
||||
'invalid property.binding type <' + bindingType + '>; ' +
|
||||
'must be any of { ' + VALID_BINDING_TYPES.join(', ') + ' }'
|
||||
);
|
||||
}
|
||||
|
||||
if (bindingType === PROPERTY_TYPE ||
|
||||
bindingType === ACTIVITI_PROPERTY_TYPE ||
|
||||
bindingType === ACTIVITI_INPUT_PARAMETER_TYPE ||
|
||||
bindingType === ACTIVITI_FIELD) {
|
||||
|
||||
if (!binding.name) {
|
||||
err = this._logError(
|
||||
'property.binding <' + bindingType + '> requires name'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_OUTPUT_PARAMETER_TYPE) {
|
||||
if (!binding.source) {
|
||||
err = this._logError(
|
||||
'property.binding <' + bindingType + '> requires source'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_IN_TYPE) {
|
||||
|
||||
if (!binding.variables && !binding.target) {
|
||||
err = this._logError(
|
||||
'property.binding <' + bindingType + '> requires ' +
|
||||
'variables or target'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_OUT_TYPE) {
|
||||
|
||||
if (!binding.variables && !binding.source && !binding.sourceExpression) {
|
||||
err = this._logError(
|
||||
'property.binding <' + bindingType + '> requires ' +
|
||||
'variables, sourceExpression or source'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_EXECUTION_LISTENER) {
|
||||
|
||||
if (type !== 'Hidden') {
|
||||
err = this._logError(
|
||||
'invalid property type <' + type + '> for ' + ACTIVITI_EXECUTION_LISTENER + '; ' +
|
||||
'must be <Hidden>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return !err;
|
||||
};
|
||||
|
||||
|
||||
this._logError = function(err, template) {
|
||||
|
||||
if (typeof err === 'string') {
|
||||
if (template) {
|
||||
err = 'template(id: ' + template.id + ') ' + err;
|
||||
}
|
||||
|
||||
err = new Error(err);
|
||||
}
|
||||
|
||||
this._errors.push(err);
|
||||
|
||||
return err;
|
||||
};
|
||||
|
||||
this.getErrors = function() {
|
||||
return this._errors;
|
||||
};
|
||||
|
||||
this.getValidTemplates = function() {
|
||||
return this._validTemplates;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = Validator;
|
||||
|
||||
|
||||
// helpers ///////////////////////////////////
|
||||
|
||||
function isDropdownChoiceValid(c) {
|
||||
return 'name' in c && 'value' in c;
|
||||
}
|
@ -0,0 +1,471 @@
|
||||
'use strict';
|
||||
|
||||
var findExtension = require('../Helper').findExtension,
|
||||
findExtensions = require('../Helper').findExtensions;
|
||||
|
||||
var createActivitiProperty = require('../CreateHelper').createActivitiProperty,
|
||||
createInputParameter = require('../CreateHelper').createInputParameter,
|
||||
createOutputParameter = require('../CreateHelper').createOutputParameter,
|
||||
createActivitiIn = require('../CreateHelper').createActivitiIn,
|
||||
createActivitiOut = require('../CreateHelper').createActivitiOut,
|
||||
createActivitiInWithBusinessKey = require('../CreateHelper').createActivitiInWithBusinessKey,
|
||||
createActivitiExecutionListenerScript = require('../CreateHelper').createActivitiExecutionListenerScript,
|
||||
createActivitiFieldInjection = require('../CreateHelper').createActivitiFieldInjection;
|
||||
|
||||
var forEach = require('lodash/forEach');
|
||||
|
||||
var ACTIVITI_SERVICE_TASK_LIKE = [
|
||||
'activiti:class',
|
||||
'activiti:delegateExpression',
|
||||
'activiti:expression'
|
||||
];
|
||||
|
||||
/**
|
||||
* A handler that changes the modeling template of a BPMN element.
|
||||
*/
|
||||
function ChangeElementTemplateHandler(modeling, commandStack, bpmnFactory) {
|
||||
|
||||
function getOrCreateExtensionElements(element) {
|
||||
|
||||
var bo = element.businessObject;
|
||||
|
||||
var extensionElements = bo.extensionElements;
|
||||
|
||||
// add extension elements
|
||||
if (!extensionElements) {
|
||||
extensionElements = bpmnFactory.create('bpmn:ExtensionElements', {
|
||||
values: []
|
||||
});
|
||||
|
||||
modeling.updateProperties(element, {
|
||||
extensionElements: extensionElements
|
||||
});
|
||||
}
|
||||
|
||||
return extensionElements;
|
||||
}
|
||||
|
||||
function updateModelerTemplate(element, newTemplate) {
|
||||
modeling.updateProperties(element, {
|
||||
'activiti:modelerTemplate': newTemplate && newTemplate.id
|
||||
});
|
||||
}
|
||||
|
||||
function updateIoMappings(element, newTemplate, context) {
|
||||
|
||||
var newMappings = createInputOutputMappings(newTemplate, bpmnFactory),
|
||||
oldMappings;
|
||||
|
||||
if (!newMappings) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
commandStack.execute('properties-panel.update-businessobject', {
|
||||
element: element,
|
||||
businessObject: context,
|
||||
properties: { inputOutput: newMappings }
|
||||
});
|
||||
} else {
|
||||
context = getOrCreateExtensionElements(element);
|
||||
oldMappings = findExtension(element, 'activiti:InputOutput');
|
||||
commandStack.execute('properties-panel.update-businessobject-list', {
|
||||
element: element,
|
||||
currentObject: context,
|
||||
propertyName: 'values',
|
||||
objectsToAdd: [ newMappings ],
|
||||
objectsToRemove: oldMappings ? [ oldMappings ] : []
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateActivitiField(element, newTemplate, context) {
|
||||
|
||||
var newMappings = createActivitiFieldInjections(newTemplate, bpmnFactory),
|
||||
oldMappings;
|
||||
|
||||
if (!newMappings) {
|
||||
return;
|
||||
}
|
||||
if (context) {
|
||||
commandStack.execute('properties-panel.update-businessobject', {
|
||||
element: element,
|
||||
businessObject: context,
|
||||
properties: { field: newMappings }
|
||||
});
|
||||
} else {
|
||||
context = getOrCreateExtensionElements(element);
|
||||
oldMappings = findExtensions(element, ['activiti:Field']);
|
||||
|
||||
commandStack.execute('properties-panel.update-businessobject-list', {
|
||||
element: element,
|
||||
currentObject: context,
|
||||
propertyName: 'values',
|
||||
objectsToAdd: newMappings,
|
||||
objectsToRemove: oldMappings ? oldMappings : []
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateActivitiProperties(element, newTemplate, context) {
|
||||
|
||||
var newProperties = createActivitiProperties(newTemplate, bpmnFactory),
|
||||
oldProperties;
|
||||
|
||||
if (!newProperties) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
commandStack.execute('properties-panel.update-businessobject', {
|
||||
element: element,
|
||||
businessObject: context,
|
||||
properties: { properties: newProperties }
|
||||
});
|
||||
} else {
|
||||
context = getOrCreateExtensionElements(element);
|
||||
oldProperties = findExtension(element, 'activiti:Properties');
|
||||
|
||||
commandStack.execute('properties-panel.update-businessobject-list', {
|
||||
element: element,
|
||||
currentObject: context,
|
||||
propertyName: 'values',
|
||||
objectsToAdd: [ newProperties ],
|
||||
objectsToRemove: oldProperties ? [ oldProperties ] : []
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateProperties(element, newTemplate, context) {
|
||||
|
||||
var newProperties = createBpmnPropertyUpdates(newTemplate, bpmnFactory);
|
||||
|
||||
var newPropertiesCount = Object.keys(newProperties).length;
|
||||
|
||||
if (!newPropertiesCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
commandStack.execute('properties-panel.update-businessobject', {
|
||||
element: element,
|
||||
businessObject: context,
|
||||
properties: newProperties
|
||||
});
|
||||
} else {
|
||||
modeling.updateProperties(element, newProperties);
|
||||
}
|
||||
}
|
||||
|
||||
function updateInOut(element, newTemplate, context) {
|
||||
|
||||
var newInOut = createActivitiInOut(newTemplate, bpmnFactory),
|
||||
oldInOut;
|
||||
|
||||
if (!newInOut) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
commandStack.execute('properties-panel.update-businessobject', {
|
||||
element: element,
|
||||
businessObject: context,
|
||||
properties: { inout: newInOut }
|
||||
});
|
||||
} else {
|
||||
context = getOrCreateExtensionElements(element);
|
||||
oldInOut = findExtensions(context, [ 'activiti:In', 'activiti:Out' ]);
|
||||
|
||||
commandStack.execute('properties-panel.update-businessobject-list', {
|
||||
element: element,
|
||||
currentObject: context,
|
||||
propertyName: 'values',
|
||||
objectsToAdd: newInOut,
|
||||
objectsToRemove: oldInOut
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateExecutionListener(element, newTemplate, context) {
|
||||
|
||||
var newExecutionListeners = createActivitiExecutionListeners(newTemplate, bpmnFactory),
|
||||
oldExecutionsListeners;
|
||||
|
||||
if (!newExecutionListeners.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
commandStack.execute('properties-panel.update-businessobject', {
|
||||
element: element,
|
||||
businessObject: context,
|
||||
properties: { executionListener: newExecutionListeners }
|
||||
});
|
||||
} else {
|
||||
context = getOrCreateExtensionElements(element);
|
||||
oldExecutionsListeners = findExtensions(context, [ 'activiti:ExecutionListener' ]);
|
||||
|
||||
commandStack.execute('properties-panel.update-businessobject-list', {
|
||||
element: element,
|
||||
currentObject: context,
|
||||
propertyName: 'values',
|
||||
objectsToAdd: newExecutionListeners,
|
||||
objectsToRemove: oldExecutionsListeners
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update / recreate a scoped element.
|
||||
*
|
||||
* @param {djs.model.Base} element the diagram parent element
|
||||
* @param {String} scopeName name of the scope, i.e. activiti:Connector
|
||||
* @param {Object} scopeDefinition
|
||||
*/
|
||||
function updateScopeElements(element, scopeName, scopeDefinition) {
|
||||
|
||||
var scopeElement = bpmnFactory.create(scopeName);
|
||||
|
||||
// update activiti:inputOutput
|
||||
updateIoMappings(element, scopeDefinition, scopeElement);
|
||||
|
||||
// update activiti:field
|
||||
updateActivitiField(element, scopeDefinition, scopeElement);
|
||||
|
||||
// update activiti:properties
|
||||
updateActivitiProperties(element, scopeDefinition, scopeElement);
|
||||
|
||||
// update other properties (bpmn:condition, activiti:async, ...)
|
||||
updateProperties(element, scopeDefinition, scopeElement);
|
||||
|
||||
// update activiti:in and activiti:out
|
||||
updateInOut(element, scopeDefinition, scopeElement);
|
||||
|
||||
// update activiti:executionListener
|
||||
updateExecutionListener(element, scopeDefinition, scopeElement);
|
||||
|
||||
var extensionElements = getOrCreateExtensionElements(element);
|
||||
var oldScope = findExtension(extensionElements, scopeName);
|
||||
|
||||
commandStack.execute('properties-panel.update-businessobject-list', {
|
||||
element: element,
|
||||
currentObject: extensionElements,
|
||||
propertyName: 'values',
|
||||
objectsToAdd: [ scopeElement ],
|
||||
objectsToRemove: oldScope ? [ oldScope ] : []
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose an element template change action, updating all
|
||||
* necessary underlying properties.
|
||||
*
|
||||
* @param {Object} context
|
||||
* @param {Object} context.element
|
||||
* @param {Object} context.oldTemplate
|
||||
* @param {Object} context.newTemplate
|
||||
*/
|
||||
this.preExecute = function(context) {
|
||||
|
||||
var element = context.element,
|
||||
newTemplate = context.newTemplate;
|
||||
|
||||
// update activiti:modelerTemplate attribute
|
||||
updateModelerTemplate(element, newTemplate);
|
||||
|
||||
if (newTemplate) {
|
||||
|
||||
// update activiti:inputOutput
|
||||
updateIoMappings(element, newTemplate);
|
||||
|
||||
// update activiti:field
|
||||
updateActivitiField(element, newTemplate);
|
||||
|
||||
// update activiti:properties
|
||||
updateActivitiProperties(element, newTemplate);
|
||||
|
||||
// update other properties (bpmn:condition, activiti:async, ...)
|
||||
updateProperties(element, newTemplate);
|
||||
|
||||
// update activiti:in and activiti:out
|
||||
updateInOut(element, newTemplate);
|
||||
|
||||
// update activiti:executionListener
|
||||
updateExecutionListener(element, newTemplate);
|
||||
|
||||
// loop on scopes properties
|
||||
forEach(newTemplate.scopes, function(scopeDefinition, scopeName) {
|
||||
updateScopeElements(element, scopeName, scopeDefinition);
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ChangeElementTemplateHandler.$inject = [ 'modeling', 'commandStack', 'bpmnFactory' ];
|
||||
|
||||
module.exports = ChangeElementTemplateHandler;
|
||||
|
||||
|
||||
|
||||
// helpers /////////////////////////////
|
||||
|
||||
function createBpmnPropertyUpdates(template, bpmnFactory) {
|
||||
|
||||
var propertyUpdates = {};
|
||||
|
||||
template.properties.forEach(function(p) {
|
||||
|
||||
var binding = p.binding,
|
||||
bindingTarget = binding.name,
|
||||
propertyValue;
|
||||
|
||||
if (binding.type === 'property') {
|
||||
|
||||
if (bindingTarget === 'conditionExpression') {
|
||||
propertyValue = bpmnFactory.create('bpmn:FormalExpression', {
|
||||
body: p.value,
|
||||
language: binding.scriptFormat
|
||||
});
|
||||
} else {
|
||||
propertyValue = p.value;
|
||||
}
|
||||
|
||||
// assigning activiti:async to true|false
|
||||
// assigning bpmn:conditionExpression to { $type: 'bpmn:FormalExpression', ... }
|
||||
propertyUpdates[bindingTarget] = propertyValue;
|
||||
|
||||
// make sure we unset other "implementation types"
|
||||
// when applying a activiti:class template onto a preconfigured
|
||||
// activiti:delegateExpression element
|
||||
if (ACTIVITI_SERVICE_TASK_LIKE.indexOf(bindingTarget) !== -1) {
|
||||
ACTIVITI_SERVICE_TASK_LIKE.forEach(function(prop) {
|
||||
if (prop !== bindingTarget) {
|
||||
propertyUpdates[prop] = undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return propertyUpdates;
|
||||
}
|
||||
|
||||
function createActivitiFieldInjections(template, bpmnFactory) {
|
||||
var injections = [];
|
||||
|
||||
template.properties.forEach(function(p) {
|
||||
var binding = p.binding,
|
||||
bindingType = binding.type;
|
||||
if (bindingType === 'activiti:field') {
|
||||
injections.push(createActivitiFieldInjection(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
if (injections.length) {
|
||||
return injections;
|
||||
}
|
||||
}
|
||||
|
||||
function createActivitiProperties(template, bpmnFactory) {
|
||||
|
||||
var properties = [];
|
||||
|
||||
template.properties.forEach(function(p) {
|
||||
var binding = p.binding,
|
||||
bindingType = binding.type;
|
||||
|
||||
if (bindingType === 'activiti:property') {
|
||||
properties.push(createActivitiProperty(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
if (properties.length) {
|
||||
return bpmnFactory.create('activiti:Properties', {
|
||||
values: properties
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createInputOutputMappings(template, bpmnFactory) {
|
||||
|
||||
var inputParameters = [],
|
||||
outputParameters = [];
|
||||
|
||||
template.properties.forEach(function(p) {
|
||||
var binding = p.binding,
|
||||
bindingType = binding.type;
|
||||
|
||||
if (bindingType === 'activiti:inputParameter') {
|
||||
inputParameters.push(createInputParameter(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
}
|
||||
|
||||
if (bindingType === 'activiti:outputParameter') {
|
||||
outputParameters.push(createOutputParameter(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
// do we need to create new ioMappings (?)
|
||||
if (outputParameters.length || inputParameters.length) {
|
||||
return bpmnFactory.create('activiti:InputOutput', {
|
||||
inputParameters: inputParameters,
|
||||
outputParameters: outputParameters
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function createActivitiInOut(template, bpmnFactory) {
|
||||
|
||||
var inOuts = [];
|
||||
|
||||
template.properties.forEach(function(p) {
|
||||
var binding = p.binding,
|
||||
bindingType = binding.type;
|
||||
|
||||
if (bindingType === 'activiti:in') {
|
||||
inOuts.push(createActivitiIn(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
} else
|
||||
if (bindingType === 'activiti:out') {
|
||||
inOuts.push(createActivitiOut(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
} else
|
||||
if (bindingType === 'activiti:in:businessKey') {
|
||||
inOuts.push(createActivitiInWithBusinessKey(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
return inOuts;
|
||||
}
|
||||
|
||||
|
||||
function createActivitiExecutionListeners(template, bpmnFactory) {
|
||||
|
||||
var executionListener = [];
|
||||
|
||||
template.properties.forEach(function(p) {
|
||||
var binding = p.binding,
|
||||
bindingType = binding.type;
|
||||
|
||||
if (bindingType === 'activiti:executionListener') {
|
||||
executionListener.push(createActivitiExecutionListenerScript(
|
||||
binding, p.value, bpmnFactory
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
return executionListener;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
var ChangeElementTemplateHandler = require('./ChangeElementTemplateHandler');
|
||||
|
||||
var getTemplate = require('../Helper').getTemplate,
|
||||
getDefaultTemplate = require('../Helper').getDefaultTemplate;
|
||||
|
||||
function registerHandlers(commandStack, elementTemplates, eventBus, elementRegistry) {
|
||||
commandStack.registerHandler(
|
||||
'propertiesPanel.activiti.changeTemplate',
|
||||
ChangeElementTemplateHandler
|
||||
);
|
||||
|
||||
// apply default element templates on shape creation
|
||||
eventBus.on([ 'commandStack.shape.create.postExecuted' ], function(context) {
|
||||
applyDefaultTemplate(context.context.shape, elementTemplates, commandStack);
|
||||
});
|
||||
|
||||
// apply default element templates on connection creation
|
||||
eventBus.on([ 'commandStack.connection.create.postExecuted' ], function(context) {
|
||||
applyDefaultTemplate(context.context.connection, elementTemplates, commandStack);
|
||||
});
|
||||
}
|
||||
|
||||
registerHandlers.$inject = [ 'commandStack', 'elementTemplates', 'eventBus', 'elementRegistry' ];
|
||||
|
||||
|
||||
module.exports = {
|
||||
__init__: [ registerHandlers ]
|
||||
};
|
||||
|
||||
|
||||
function applyDefaultTemplate(element, elementTemplates, commandStack) {
|
||||
|
||||
if (!getTemplate(element, elementTemplates)
|
||||
&& getDefaultTemplate(element, elementTemplates)) {
|
||||
|
||||
var command = 'propertiesPanel.activiti.changeTemplate';
|
||||
var commandContext = {
|
||||
element: element,
|
||||
newTemplate: getDefaultTemplate(element, elementTemplates)
|
||||
};
|
||||
|
||||
commandStack.execute(command, commandContext);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
__depends__: [
|
||||
require('./cmd/index'),
|
||||
require('diagram-js/lib/i18n/translate').default
|
||||
],
|
||||
__init__: [
|
||||
'customElementsPropertiesActivator',
|
||||
'elementTemplatesLoader'
|
||||
],
|
||||
customElementsPropertiesActivator: [ 'type', require('./CustomElementsPropertiesActivator') ],
|
||||
elementTemplates: [ 'type', require('./ElementTemplates') ],
|
||||
elementTemplatesLoader: [ 'type', require('./ElementTemplatesLoader') ]
|
||||
};
|
@ -0,0 +1,151 @@
|
||||
'use strict';
|
||||
|
||||
var entryFactory = require('../../../../factory/EntryFactory'),
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getTemplate = require('../Helper').getTemplate,
|
||||
getTemplateId = require('../Helper').getTemplateId;
|
||||
|
||||
var find = require('lodash/find');
|
||||
|
||||
var TEMPLATE_ATTR = require('../Helper').TEMPLATE_ATTR;
|
||||
|
||||
function isAny(element, types) {
|
||||
return types.reduce(function(result, type) {
|
||||
return result || is(element, type);
|
||||
}, false);
|
||||
}
|
||||
|
||||
|
||||
module.exports = function(group, element, elementTemplates, translate) {
|
||||
|
||||
var options = getTemplateOptions(element, elementTemplates, translate);
|
||||
|
||||
if (options.length === 1 && !options[0].isDefault) {
|
||||
return;
|
||||
}
|
||||
|
||||
// select element template (via dropdown)
|
||||
group.entries.push(entryFactory.selectBox({
|
||||
id: 'elementTemplate-chooser',
|
||||
label: translate('Element Template'),
|
||||
modelProperty: 'activiti:modelerTemplate',
|
||||
selectOptions: options,
|
||||
set: function(element, properties) {
|
||||
return applyTemplate(element, properties[TEMPLATE_ATTR], elementTemplates);
|
||||
},
|
||||
disabled: function() {
|
||||
var template = getTemplate(element, elementTemplates);
|
||||
|
||||
return template && isDefaultTemplate(template);
|
||||
}
|
||||
}));
|
||||
|
||||
};
|
||||
|
||||
|
||||
// helpers //////////////////////////////////////
|
||||
|
||||
function applyTemplate(element, newTemplateId, elementTemplates) {
|
||||
|
||||
// cleanup
|
||||
// clear input output mappings
|
||||
// undo changes to properties defined in template
|
||||
|
||||
// re-establish
|
||||
// set input output mappings
|
||||
// apply changes to properties as defined in new template
|
||||
|
||||
var oldTemplate = getTemplate(element, elementTemplates),
|
||||
newTemplate = elementTemplates.get(newTemplateId);
|
||||
|
||||
if (oldTemplate === newTemplate) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
cmd: 'propertiesPanel.activiti.changeTemplate',
|
||||
context: {
|
||||
element: element,
|
||||
oldTemplate: oldTemplate,
|
||||
newTemplate: newTemplate
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getTemplateOptions(element, elementTemplates, translate) {
|
||||
|
||||
var currentTemplateId = getTemplateId(element);
|
||||
|
||||
var emptyOption = {
|
||||
name: '',
|
||||
value: ''
|
||||
};
|
||||
|
||||
var allOptions = elementTemplates.getAll().reduce(function(templates, t) {
|
||||
if (!isAny(element, t.appliesTo)) {
|
||||
return templates;
|
||||
}
|
||||
|
||||
return templates.concat({
|
||||
name: translate(t.name),
|
||||
value: t.id,
|
||||
isDefault: t.isDefault
|
||||
});
|
||||
}, [ emptyOption ]);
|
||||
|
||||
|
||||
var defaultOption = find(allOptions, function(option) {
|
||||
return isDefaultTemplate(option);
|
||||
});
|
||||
|
||||
var currentOption = find(allOptions, function(option) {
|
||||
return option.value === currentTemplateId;
|
||||
});
|
||||
|
||||
if (currentTemplateId && !currentOption) {
|
||||
currentOption = unknownTemplate(currentTemplateId, translate);
|
||||
|
||||
allOptions.push(currentOption);
|
||||
}
|
||||
|
||||
if (!defaultOption) {
|
||||
|
||||
// return all options, including empty
|
||||
// and optionally unknownTemplate option
|
||||
return allOptions;
|
||||
}
|
||||
|
||||
// special limited handling for
|
||||
// default options
|
||||
|
||||
var options = [];
|
||||
|
||||
// current template not set
|
||||
if (!currentTemplateId) {
|
||||
options.push({
|
||||
name: '',
|
||||
value: ''
|
||||
});
|
||||
}
|
||||
|
||||
// current template not default
|
||||
if (currentOption && currentOption !== defaultOption) {
|
||||
options.push(currentOption);
|
||||
}
|
||||
|
||||
options.push(defaultOption);
|
||||
|
||||
// [ (empty), (current), defaultOption ]
|
||||
return options;
|
||||
}
|
||||
|
||||
function unknownTemplate(templateId, translate) {
|
||||
return {
|
||||
name: translate('[unknown template: {templateId}]', { templateId: templateId }),
|
||||
value: templateId
|
||||
};
|
||||
}
|
||||
|
||||
function isDefaultTemplate(elementTemplate) {
|
||||
return elementTemplate.isDefault;
|
||||
}
|
@ -0,0 +1,770 @@
|
||||
'use strict';
|
||||
|
||||
var assign = require('lodash/assign');
|
||||
|
||||
var entryFactory = require('../../../../factory/EntryFactory'),
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
getTemplate = require('../Helper').getTemplate,
|
||||
cmdHelper = require('../../../../helper/CmdHelper'),
|
||||
elementHelper = require('../../../../helper/ElementHelper');
|
||||
|
||||
var findExtension = require('../Helper').findExtension,
|
||||
findExtensions = require('../Helper').findExtensions,
|
||||
findInputParameter = require('../Helper').findInputParameter,
|
||||
findOutputParameter = require('../Helper').findOutputParameter,
|
||||
findActivitiProperty = require('../Helper').findActivitiProperty,
|
||||
findActivitiInOut = require('../Helper').findActivitiInOut;
|
||||
|
||||
var createActivitiProperty = require('../CreateHelper').createActivitiProperty,
|
||||
createInputParameter = require('../CreateHelper').createInputParameter,
|
||||
createOutputParameter = require('../CreateHelper').createOutputParameter,
|
||||
createActivitiIn = require('../CreateHelper').createActivitiIn,
|
||||
createActivitiOut = require('../CreateHelper').createActivitiOut,
|
||||
createActivitiInWithBusinessKey = require('../CreateHelper').createActivitiInWithBusinessKey,
|
||||
createActivitiFieldInjection = require('../CreateHelper').createActivitiFieldInjection;
|
||||
|
||||
var ACTIVITI_PROPERTY_TYPE = 'activiti:property',
|
||||
ACTIVITI_INPUT_PARAMETER_TYPE = 'activiti:inputParameter',
|
||||
ACTIVITI_OUTPUT_PARAMETER_TYPE = 'activiti:outputParameter',
|
||||
ACTIVITI_IN_TYPE = 'activiti:in',
|
||||
ACTIVITI_OUT_TYPE = 'activiti:out',
|
||||
ACTIVITI_IN_BUSINESS_KEY_TYPE = 'activiti:in:businessKey',
|
||||
ACTIVITI_EXECUTION_LISTENER_TYPE = 'activiti:executionListener',
|
||||
ACTIVITI_FIELD = 'activiti:field';
|
||||
|
||||
var BASIC_MODDLE_TYPES = [
|
||||
'Boolean',
|
||||
'Integer',
|
||||
'String'
|
||||
];
|
||||
|
||||
var EXTENSION_BINDING_TYPES = [
|
||||
ACTIVITI_PROPERTY_TYPE,
|
||||
ACTIVITI_INPUT_PARAMETER_TYPE,
|
||||
ACTIVITI_OUTPUT_PARAMETER_TYPE,
|
||||
ACTIVITI_IN_TYPE,
|
||||
ACTIVITI_OUT_TYPE,
|
||||
ACTIVITI_IN_BUSINESS_KEY_TYPE,
|
||||
ACTIVITI_FIELD
|
||||
];
|
||||
|
||||
var IO_BINDING_TYPES = [
|
||||
ACTIVITI_INPUT_PARAMETER_TYPE,
|
||||
ACTIVITI_OUTPUT_PARAMETER_TYPE
|
||||
];
|
||||
|
||||
var IN_OUT_BINDING_TYPES = [
|
||||
ACTIVITI_IN_TYPE,
|
||||
ACTIVITI_OUT_TYPE,
|
||||
ACTIVITI_IN_BUSINESS_KEY_TYPE
|
||||
];
|
||||
|
||||
/**
|
||||
* Injects custom properties into the given group.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {ElementTemplates} elementTemplates
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
* @param {Function} translate
|
||||
*/
|
||||
module.exports = function(element, elementTemplates, bpmnFactory, translate) {
|
||||
|
||||
var template = getTemplate(element, elementTemplates);
|
||||
|
||||
if (!template) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var renderCustomField = function(id, p, idx) {
|
||||
var propertyType = p.type;
|
||||
|
||||
var entryOptions = {
|
||||
id: id,
|
||||
description: p.description,
|
||||
label: p.label ? translate(p.label) : p.label,
|
||||
modelProperty: id,
|
||||
get: propertyGetter(id, p),
|
||||
set: propertySetter(id, p, bpmnFactory),
|
||||
validate: propertyValidator(id, p, translate)
|
||||
};
|
||||
|
||||
var entry;
|
||||
|
||||
if (propertyType === 'Boolean') {
|
||||
entry = entryFactory.checkbox(entryOptions);
|
||||
}
|
||||
|
||||
if (propertyType === 'String') {
|
||||
entry = entryFactory.textField(entryOptions);
|
||||
}
|
||||
|
||||
if (propertyType === 'Text') {
|
||||
entry = entryFactory.textBox(entryOptions);
|
||||
}
|
||||
|
||||
if (propertyType === 'Dropdown') {
|
||||
entryOptions.selectOptions = p.choices;
|
||||
|
||||
entry = entryFactory.selectBox(entryOptions);
|
||||
}
|
||||
|
||||
return entry;
|
||||
};
|
||||
|
||||
var groups = [];
|
||||
var id, entry;
|
||||
|
||||
var customFieldsGroup = {
|
||||
id: 'customField',
|
||||
label: translate('Custom Fields'),
|
||||
entries: []
|
||||
};
|
||||
template.properties.forEach(function(p, idx) {
|
||||
|
||||
id = 'custom-' + template.id + '-' + idx;
|
||||
|
||||
entry = renderCustomField(id, p, idx);
|
||||
if (entry) {
|
||||
customFieldsGroup.entries.push(entry);
|
||||
}
|
||||
});
|
||||
if (customFieldsGroup.entries.length > 0) {
|
||||
groups.push(customFieldsGroup);
|
||||
}
|
||||
|
||||
if (template.scopes) {
|
||||
for (var scopeName in template.scopes) {
|
||||
|
||||
var scope = template.scopes[scopeName];
|
||||
var idScopeName = scopeName.replace(/:/g, '_');
|
||||
|
||||
var customScopeFieldsGroup = {
|
||||
id: 'customField-' + idScopeName,
|
||||
label: translate('Custom Fields for scope: ') + scopeName,
|
||||
entries: []
|
||||
};
|
||||
|
||||
scope.properties.forEach(function(p, idx) {
|
||||
|
||||
var propertyId = 'custom-' + template.id + '-' + idScopeName + '-' + idx;
|
||||
|
||||
var scopedProperty = propertyWithScope(p, scopeName);
|
||||
|
||||
entry = renderCustomField(propertyId, scopedProperty, idx);
|
||||
if (entry) {
|
||||
customScopeFieldsGroup.entries.push(entry);
|
||||
}
|
||||
});
|
||||
|
||||
if (customScopeFieldsGroup.entries.length > 0) {
|
||||
groups.push(customScopeFieldsGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return groups;
|
||||
};
|
||||
|
||||
|
||||
// getters, setters and validators ///////////////
|
||||
|
||||
|
||||
/**
|
||||
* Return a getter that retrieves the given property.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {PropertyDescriptor} property
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function propertyGetter(name, property) {
|
||||
|
||||
/* getter */
|
||||
return function get(element) {
|
||||
var value = getPropertyValue(element, property);
|
||||
|
||||
return objectWithKey(name, value);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a setter that updates the given property.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {PropertyDescriptor} property
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function propertySetter(name, property, bpmnFactory) {
|
||||
|
||||
/* setter */
|
||||
return function set(element, values) {
|
||||
|
||||
var value = values[name];
|
||||
|
||||
return setPropertyValue(element, property, value, bpmnFactory);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a validator that ensures the property is ok.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {PropertyDescriptor} property
|
||||
* @param {Function} translate
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function propertyValidator(name, property, translate) {
|
||||
|
||||
/* validator */
|
||||
return function validate(element, values) {
|
||||
var value = values[name];
|
||||
|
||||
var error = validateValue(value, property, translate);
|
||||
|
||||
if (error) {
|
||||
return objectWithKey(name, error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// get, set and validate helpers ///////////////////
|
||||
|
||||
/**
|
||||
* Return the value of the specified property descriptor,
|
||||
* on the passed diagram element.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {PropertyDescriptor} property
|
||||
*
|
||||
* @return {Any}
|
||||
*/
|
||||
function getPropertyValue(element, property) {
|
||||
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
var binding = property.binding,
|
||||
scope = property.scope;
|
||||
|
||||
var bindingType = binding.type,
|
||||
bindingName = binding.name;
|
||||
|
||||
var propertyValue = property.value || '';
|
||||
|
||||
if (scope) {
|
||||
bo = findExtension(bo, scope.name);
|
||||
if (!bo) {
|
||||
return propertyValue;
|
||||
}
|
||||
}
|
||||
|
||||
// property
|
||||
if (bindingType === 'property') {
|
||||
|
||||
var value = bo.get(bindingName);
|
||||
|
||||
if (bindingName === 'conditionExpression') {
|
||||
if (value) {
|
||||
return value.body;
|
||||
} else {
|
||||
// return defined default
|
||||
return propertyValue;
|
||||
}
|
||||
} else {
|
||||
// return value; default to defined default
|
||||
return typeof value !== 'undefined' ? value : propertyValue;
|
||||
}
|
||||
}
|
||||
|
||||
var activitiProperties,
|
||||
activitiProperty;
|
||||
|
||||
if (bindingType === ACTIVITI_PROPERTY_TYPE) {
|
||||
if (scope) {
|
||||
activitiProperties = bo.get('properties');
|
||||
} else {
|
||||
activitiProperties = findExtension(bo, 'activiti:Properties');
|
||||
}
|
||||
|
||||
if (activitiProperties) {
|
||||
activitiProperty = findActivitiProperty(activitiProperties, binding);
|
||||
|
||||
if (activitiProperty) {
|
||||
return activitiProperty.value;
|
||||
}
|
||||
}
|
||||
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
var inputOutput,
|
||||
ioParameter;
|
||||
|
||||
if (IO_BINDING_TYPES.indexOf(bindingType) !== -1) {
|
||||
|
||||
if (scope) {
|
||||
inputOutput = bo.get('inputOutput');
|
||||
} else {
|
||||
inputOutput = findExtension(bo, 'activiti:InputOutput');
|
||||
}
|
||||
|
||||
if (!inputOutput) {
|
||||
// ioParameter cannot exist yet, return property value
|
||||
return propertyValue;
|
||||
}
|
||||
}
|
||||
|
||||
// activiti input parameter
|
||||
if (bindingType === ACTIVITI_INPUT_PARAMETER_TYPE) {
|
||||
ioParameter = findInputParameter(inputOutput, binding);
|
||||
|
||||
if (ioParameter) {
|
||||
if (binding.scriptFormat) {
|
||||
if (ioParameter.definition) {
|
||||
return ioParameter.definition.value;
|
||||
}
|
||||
} else {
|
||||
return ioParameter.value || '';
|
||||
}
|
||||
}
|
||||
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
// activiti output parameter
|
||||
if (binding.type === ACTIVITI_OUTPUT_PARAMETER_TYPE) {
|
||||
ioParameter = findOutputParameter(inputOutput, binding);
|
||||
|
||||
if (ioParameter) {
|
||||
return ioParameter.name;
|
||||
}
|
||||
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
|
||||
var ioElement;
|
||||
|
||||
if (IN_OUT_BINDING_TYPES.indexOf(bindingType) != -1) {
|
||||
ioElement = findActivitiInOut(bo, binding);
|
||||
|
||||
if (ioElement) {
|
||||
if (bindingType === ACTIVITI_IN_BUSINESS_KEY_TYPE) {
|
||||
return ioElement.businessKey;
|
||||
} else
|
||||
if (bindingType === ACTIVITI_OUT_TYPE) {
|
||||
return ioElement.target;
|
||||
} else
|
||||
if (bindingType === ACTIVITI_IN_TYPE) {
|
||||
return ioElement[binding.expression ? 'sourceExpression' : 'source'];
|
||||
}
|
||||
}
|
||||
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_EXECUTION_LISTENER_TYPE) {
|
||||
var executionListener;
|
||||
if (scope) {
|
||||
executionListener = bo.get('executionListener');
|
||||
} else {
|
||||
executionListener = findExtension(bo, 'activiti:ExecutionListener');
|
||||
}
|
||||
|
||||
return executionListener.script.value;
|
||||
}
|
||||
|
||||
var fieldInjection;
|
||||
if (ACTIVITI_FIELD === bindingType) {
|
||||
var fieldInjections = findExtensions(bo, [ 'activiti:Field' ]);
|
||||
fieldInjections.forEach(function(item) {
|
||||
if (item.name === binding.name) {
|
||||
fieldInjection = item;
|
||||
}
|
||||
});
|
||||
if (fieldInjection) {
|
||||
return fieldInjection.string || fieldInjection.expression;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
throw unknownPropertyBinding(property);
|
||||
}
|
||||
|
||||
module.exports.getPropertyValue = getPropertyValue;
|
||||
|
||||
|
||||
/**
|
||||
* Return an update operation that changes the diagram
|
||||
* element's custom property to the given value.
|
||||
*
|
||||
* The response of this method will be processed via
|
||||
* {@link PropertiesPanel#applyChanges}.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {PropertyDescriptor} property
|
||||
* @param {String} value
|
||||
* @param {BpmnFactory} bpmnFactory
|
||||
*
|
||||
* @return {Object|Array<Object>} results to be processed
|
||||
*/
|
||||
function setPropertyValue(element, property, value, bpmnFactory) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
var binding = property.binding,
|
||||
scope = property.scope;
|
||||
|
||||
var bindingType = binding.type,
|
||||
bindingName = binding.name;
|
||||
|
||||
var propertyValue;
|
||||
|
||||
var updates = [];
|
||||
|
||||
var extensionElements;
|
||||
|
||||
if (EXTENSION_BINDING_TYPES.indexOf(bindingType) !== -1) {
|
||||
extensionElements = bo.get('extensionElements');
|
||||
|
||||
// create extension elements, if they do not exist (yet)
|
||||
if (!extensionElements) {
|
||||
extensionElements = elementHelper.createElement('bpmn:ExtensionElements', null, element, bpmnFactory);
|
||||
|
||||
updates.push(cmdHelper.updateBusinessObject(
|
||||
element, bo, objectWithKey('extensionElements', extensionElements)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (scope) {
|
||||
bo = findExtension(bo, scope.name);
|
||||
if (!bo) {
|
||||
bo = elementHelper.createElement(scope.name, null, element, bpmnFactory);
|
||||
|
||||
updates.push(cmdHelper.addElementsTolist(
|
||||
bo, extensionElements, 'values', [ bo ]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// property
|
||||
if (bindingType === 'property') {
|
||||
|
||||
if (bindingName === 'conditionExpression') {
|
||||
|
||||
propertyValue = elementHelper.createElement('bpmn:FormalExpression', {
|
||||
body: value,
|
||||
language: binding.scriptFormat
|
||||
}, bo, bpmnFactory);
|
||||
} else {
|
||||
|
||||
var moddlePropertyDescriptor = bo.$descriptor.propertiesByName[bindingName];
|
||||
|
||||
var moddleType = moddlePropertyDescriptor.type;
|
||||
|
||||
// make sure we only update String, Integer, Real and
|
||||
// Boolean properties (do not accidentally override complex objects...)
|
||||
if (BASIC_MODDLE_TYPES.indexOf(moddleType) === -1) {
|
||||
throw new Error('cannot set moddle type <' + moddleType + '>');
|
||||
}
|
||||
|
||||
if (moddleType === 'Boolean') {
|
||||
propertyValue = !!value;
|
||||
} else
|
||||
if (moddleType === 'Integer') {
|
||||
propertyValue = parseInt(value, 10);
|
||||
|
||||
if (isNaN(propertyValue)) {
|
||||
// do not write NaN value
|
||||
propertyValue = undefined;
|
||||
}
|
||||
} else {
|
||||
propertyValue = value;
|
||||
}
|
||||
}
|
||||
|
||||
if (propertyValue !== undefined) {
|
||||
updates.push(cmdHelper.updateBusinessObject(
|
||||
element, bo, objectWithKey(bindingName, propertyValue)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// activiti:property
|
||||
var activitiProperties,
|
||||
existingActivitiProperty,
|
||||
newActivitiProperty;
|
||||
|
||||
if (bindingType === ACTIVITI_PROPERTY_TYPE) {
|
||||
|
||||
if (scope) {
|
||||
activitiProperties = bo.get('properties');
|
||||
} else {
|
||||
activitiProperties = findExtension(extensionElements, 'activiti:Properties');
|
||||
}
|
||||
|
||||
if (!activitiProperties) {
|
||||
activitiProperties = elementHelper.createElement('activiti:Properties', null, bo, bpmnFactory);
|
||||
|
||||
if (scope) {
|
||||
updates.push(cmdHelper.updateBusinessObject(
|
||||
element, bo, { properties: activitiProperties }
|
||||
));
|
||||
}
|
||||
else {
|
||||
updates.push(cmdHelper.addElementsTolist(
|
||||
element, extensionElements, 'values', [ activitiProperties ]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
existingActivitiProperty = findActivitiProperty(activitiProperties, binding);
|
||||
|
||||
newActivitiProperty = createActivitiProperty(binding, value, bpmnFactory);
|
||||
|
||||
updates.push(cmdHelper.addAndRemoveElementsFromList(
|
||||
element,
|
||||
activitiProperties,
|
||||
'values',
|
||||
null,
|
||||
[ newActivitiProperty ],
|
||||
existingActivitiProperty ? [ existingActivitiProperty ] : []
|
||||
));
|
||||
}
|
||||
|
||||
// activiti:inputParameter
|
||||
// activiti:outputParameter
|
||||
var inputOutput,
|
||||
existingIoParameter,
|
||||
newIoParameter;
|
||||
|
||||
if (IO_BINDING_TYPES.indexOf(bindingType) !== -1) {
|
||||
|
||||
if (scope) {
|
||||
inputOutput = bo.get('inputOutput');
|
||||
} else {
|
||||
inputOutput = findExtension(extensionElements, 'activiti:InputOutput');
|
||||
}
|
||||
|
||||
// create inputOutput element, if it do not exist (yet)
|
||||
if (!inputOutput) {
|
||||
inputOutput = elementHelper.createElement('activiti:InputOutput', null, bo, bpmnFactory);
|
||||
|
||||
if (scope) {
|
||||
updates.push(cmdHelper.updateBusinessObject(
|
||||
element, bo, { inputOutput: inputOutput }
|
||||
));
|
||||
}
|
||||
else {
|
||||
updates.push(cmdHelper.addElementsTolist(
|
||||
element, extensionElements, 'values', inputOutput
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_INPUT_PARAMETER_TYPE) {
|
||||
|
||||
existingIoParameter = findInputParameter(inputOutput, binding);
|
||||
|
||||
newIoParameter = createInputParameter(binding, value, bpmnFactory);
|
||||
|
||||
updates.push(cmdHelper.addAndRemoveElementsFromList(
|
||||
element,
|
||||
inputOutput,
|
||||
'inputParameters',
|
||||
null,
|
||||
[ newIoParameter ],
|
||||
existingIoParameter ? [ existingIoParameter ] : []
|
||||
));
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_OUTPUT_PARAMETER_TYPE) {
|
||||
|
||||
existingIoParameter = findOutputParameter(inputOutput, binding);
|
||||
|
||||
newIoParameter = createOutputParameter(binding, value, bpmnFactory);
|
||||
|
||||
updates.push(cmdHelper.addAndRemoveElementsFromList(
|
||||
element,
|
||||
inputOutput,
|
||||
'outputParameters',
|
||||
null,
|
||||
[ newIoParameter ],
|
||||
existingIoParameter ? [ existingIoParameter ] : []
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// activiti:in
|
||||
// activiti:out
|
||||
// activiti:in:businessKey
|
||||
var existingInOut,
|
||||
newInOut;
|
||||
|
||||
if (IN_OUT_BINDING_TYPES.indexOf(bindingType) !== -1) {
|
||||
|
||||
existingInOut = findActivitiInOut(bo, binding);
|
||||
|
||||
if (bindingType === ACTIVITI_IN_TYPE) {
|
||||
newInOut = createActivitiIn(binding, value, bpmnFactory);
|
||||
} else
|
||||
if (bindingType === ACTIVITI_OUT_TYPE) {
|
||||
newInOut = createActivitiOut(binding, value, bpmnFactory);
|
||||
} else {
|
||||
newInOut = createActivitiInWithBusinessKey(binding, value, bpmnFactory);
|
||||
}
|
||||
|
||||
updates.push(cmdHelper.addAndRemoveElementsFromList(
|
||||
element,
|
||||
extensionElements,
|
||||
'values',
|
||||
null,
|
||||
[ newInOut ],
|
||||
existingInOut ? [ existingInOut ] : []
|
||||
));
|
||||
}
|
||||
|
||||
if (bindingType === ACTIVITI_FIELD) {
|
||||
var existingFieldInjections = findExtensions(bo, [ 'activiti:Field' ]);
|
||||
var newFieldInjections = [];
|
||||
|
||||
if (existingFieldInjections.length > 0) {
|
||||
existingFieldInjections.forEach(function(item) {
|
||||
if (item.name === binding.name) {
|
||||
newFieldInjections.push(createActivitiFieldInjection(binding, value, bpmnFactory));
|
||||
} else {
|
||||
newFieldInjections.push(item);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
newFieldInjections.push(createActivitiFieldInjection(binding, value, bpmnFactory));
|
||||
}
|
||||
|
||||
updates.push(cmdHelper.addAndRemoveElementsFromList(
|
||||
element,
|
||||
extensionElements,
|
||||
'values',
|
||||
null,
|
||||
newFieldInjections,
|
||||
existingFieldInjections ? existingFieldInjections : []
|
||||
));
|
||||
}
|
||||
|
||||
if (updates.length) {
|
||||
return updates;
|
||||
}
|
||||
|
||||
// quick warning for better debugging
|
||||
console.warn('no update', element, property, value);
|
||||
}
|
||||
|
||||
module.exports.setPropertyValue = setPropertyValue;
|
||||
|
||||
/**
|
||||
* Validate value of a given property.
|
||||
*
|
||||
* @param {String} value
|
||||
* @param {PropertyDescriptor} property
|
||||
* @param {Function} translate
|
||||
*
|
||||
* @return {Object} with validation errors
|
||||
*/
|
||||
function validateValue(value, property, translate) {
|
||||
|
||||
var constraints = property.constraints || {};
|
||||
|
||||
if (constraints.notEmpty && isEmpty(value)) {
|
||||
return translate('Must not be empty');
|
||||
}
|
||||
|
||||
if (constraints.maxLength && value.length > constraints.maxLength) {
|
||||
return translate('Must have max length {length}', { length: constraints.maxLength });
|
||||
}
|
||||
|
||||
if (constraints.minLength && value.length < constraints.minLength) {
|
||||
return translate('Must have min length {length}', { length: constraints.minLength });
|
||||
}
|
||||
|
||||
var pattern = constraints.pattern,
|
||||
message;
|
||||
|
||||
if (pattern) {
|
||||
|
||||
if (typeof pattern !== 'string') {
|
||||
message = pattern.message;
|
||||
pattern = pattern.value;
|
||||
}
|
||||
|
||||
if (!matchesPattern(value, pattern)) {
|
||||
return message || translate('Must match pattern {pattern}', { pattern: pattern });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// misc helpers ///////////////////////////////
|
||||
|
||||
function propertyWithScope(property, scopeName) {
|
||||
if (!scopeName) {
|
||||
return property;
|
||||
}
|
||||
|
||||
return assign({}, property, {
|
||||
scope: {
|
||||
name: scopeName
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an object with a single key -> value association.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {Any} value
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
function objectWithKey(key, value) {
|
||||
var obj = {};
|
||||
|
||||
obj[key] = value;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the given string match the specified pattern?
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {String} pattern
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function matchesPattern(str, pattern) {
|
||||
var regexp = new RegExp(pattern);
|
||||
|
||||
return regexp.test(str);
|
||||
}
|
||||
|
||||
function isEmpty(str) {
|
||||
return !str || /^\s*$/.test(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Error} indicating an unknown
|
||||
* property binding.
|
||||
*
|
||||
* @param {PropertyDescriptor} property
|
||||
*
|
||||
* @return {Error}
|
||||
*/
|
||||
function unknownPropertyBinding(property) {
|
||||
var binding = property.binding;
|
||||
|
||||
return new Error('unknown binding: <' + binding.type + '>');
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
var Validator = require('../Validator');
|
||||
|
||||
/**
|
||||
* Validate the given template descriptors and
|
||||
* return a list of errors.
|
||||
*
|
||||
* @param {Array<TemplateDescriptor>} descriptors
|
||||
*
|
||||
* @return {Array<Error>}
|
||||
*/
|
||||
module.exports = function validate(descriptors) {
|
||||
|
||||
return new Validator().addAll(descriptors).getErrors();
|
||||
};
|
@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
__depends__: [
|
||||
require('./element-templates/index'),
|
||||
require('diagram-js/lib/i18n/translate').default
|
||||
],
|
||||
__init__: [ 'propertiesProvider' ],
|
||||
propertiesProvider: [ 'type', require('./ActivitiPropertiesProvider') ]
|
||||
};
|
||||
|
@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
asyncContinuation = require('./implementation/AsyncContinuation');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
if (is(element, 'activiti:AsyncCapable')) {
|
||||
|
||||
group.entries = group.entries.concat(asyncContinuation(element, bpmnFactory, {
|
||||
getBusinessObject: getBusinessObject
|
||||
}, translate));
|
||||
|
||||
}
|
||||
};
|
@ -0,0 +1,90 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is;
|
||||
|
||||
var entryFactory = require('../../../factory/EntryFactory');
|
||||
|
||||
var callable = require('./implementation/Callable');
|
||||
|
||||
var cmdHelper = require('../../../helper/CmdHelper');
|
||||
|
||||
var flattenDeep = require('lodash/flattenDeep');
|
||||
var assign = require('lodash/assign');
|
||||
|
||||
function getCallableType(element) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
var boCalledElement = bo.get('calledElement'),
|
||||
boCaseRef = bo.get('activiti:caseRef');
|
||||
|
||||
var callActivityType = '';
|
||||
if (typeof boCalledElement !== 'undefined') {
|
||||
callActivityType = 'bpmn';
|
||||
} else
|
||||
|
||||
if (typeof boCaseRef !== 'undefined') {
|
||||
callActivityType = 'cmmn';
|
||||
}
|
||||
|
||||
return callActivityType;
|
||||
}
|
||||
|
||||
var DEFAULT_PROPS = {
|
||||
calledElement: undefined,
|
||||
'activiti:calledElementBinding': 'latest',
|
||||
'activiti:calledElementVersion': undefined,
|
||||
'activiti:calledElementTenantId': undefined,
|
||||
'activiti:variableMappingClass' : undefined,
|
||||
'activiti:variableMappingDelegateExpression' : undefined,
|
||||
'activiti:caseRef': undefined,
|
||||
'activiti:caseBinding': 'latest',
|
||||
'activiti:caseVersion': undefined,
|
||||
'activiti:caseTenantId': undefined
|
||||
};
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
if (!is(element, 'activiti:CallActivity')) {
|
||||
return;
|
||||
}
|
||||
|
||||
group.entries.push(entryFactory.selectBox({
|
||||
id : 'callActivity',
|
||||
label: translate('CallActivity Type'),
|
||||
selectOptions: [
|
||||
{ name: 'BPMN', value: 'bpmn' },
|
||||
{ name: 'CMMN', value: 'cmmn' }
|
||||
],
|
||||
emptyParameter: true,
|
||||
modelProperty: 'callActivityType',
|
||||
|
||||
get: function(element, node) {
|
||||
return {
|
||||
callActivityType: getCallableType(element)
|
||||
};
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var type = values.callActivityType;
|
||||
|
||||
var props = assign({}, DEFAULT_PROPS);
|
||||
|
||||
if (type === 'bpmn') {
|
||||
props.calledElement = '';
|
||||
}
|
||||
else if (type === 'cmmn') {
|
||||
props['activiti:caseRef'] = '';
|
||||
}
|
||||
|
||||
return cmdHelper.updateProperties(element, props);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
group.entries.push(callable(element, bpmnFactory, {
|
||||
getCallableType: getCallableType
|
||||
}, translate));
|
||||
|
||||
group.entries = flattenDeep(group.entries);
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
var candidateStarter = require('./implementation/CandidateStarter');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
var businessObject = getBusinessObject(element);
|
||||
|
||||
if (is(element, 'activiti:Process') ||
|
||||
is(element, 'bpmn:Participant') && businessObject.get('processRef')) {
|
||||
|
||||
group.entries = group.entries.concat(candidateStarter(element, bpmnFactory, {
|
||||
getBusinessObject: function(element) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (!is(bo, 'bpmn:Participant')) {
|
||||
return bo;
|
||||
}
|
||||
|
||||
return bo.get('processRef');
|
||||
}
|
||||
}, translate));
|
||||
|
||||
}
|
||||
};
|
@ -0,0 +1,185 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
isAny = require('bpmn-js/lib/features/modeling/util/ModelingUtil').isAny,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
escapeHTML = require('../../../Utils').escapeHTML,
|
||||
domQuery = require('min-dom').query,
|
||||
cmdHelper = require('../../../helper/CmdHelper'),
|
||||
elementHelper = require('../../../helper/ElementHelper'),
|
||||
eventDefinitionHelper = require('../../../helper/EventDefinitionHelper'),
|
||||
scriptImplementation = require('./implementation/Script');
|
||||
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (!bo) {
|
||||
return;
|
||||
}
|
||||
|
||||
var conditionalEventDefinition = eventDefinitionHelper.getConditionalEventDefinition(element);
|
||||
|
||||
if (!(is(element, 'bpmn:SequenceFlow') && isConditionalSource(element.source))
|
||||
&& !conditionalEventDefinition) {
|
||||
return;
|
||||
}
|
||||
|
||||
var script = scriptImplementation('language', 'body', true, translate);
|
||||
group.entries.push({
|
||||
id: 'condition',
|
||||
label: translate('Condition'),
|
||||
html: '<div class="bpp-row">' +
|
||||
'<label for="cam-condition-type">'+ escapeHTML(translate('Condition Type')) + '</label>' +
|
||||
'<div class="bpp-field-wrapper">' +
|
||||
'<select id="cam-condition-type" name="conditionType" data-value>' +
|
||||
'<option value="expression">'+ escapeHTML(translate('Expression')) + '</option>' +
|
||||
'<option value="script">'+ escapeHTML(translate('Script')) + '</option>' +
|
||||
'<option value="" selected></option>' +
|
||||
'</select>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
// expression
|
||||
'<div class="bpp-row">' +
|
||||
'<label for="cam-condition" data-show="isExpression">' + escapeHTML(translate('Expression')) + '</label>' +
|
||||
'<div class="bpp-field-wrapper" data-show="isExpression">' +
|
||||
'<input id="cam-condition" type="text" name="condition" />' +
|
||||
'<button class="clear" data-action="clear" data-show="canClear">' +
|
||||
'<span>X</span>' +
|
||||
'</button>' +
|
||||
'</div>' +
|
||||
'<div data-show="isScript">' +
|
||||
script.template +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
|
||||
get: function(element, propertyName) {
|
||||
var conditionalEventDefinition = eventDefinitionHelper.getConditionalEventDefinition(element);
|
||||
|
||||
var conditionExpression = conditionalEventDefinition
|
||||
? conditionalEventDefinition.condition
|
||||
: bo.conditionExpression;
|
||||
|
||||
var values = {},
|
||||
conditionType = '';
|
||||
|
||||
if (conditionExpression) {
|
||||
var conditionLanguage = conditionExpression.language;
|
||||
if (typeof conditionLanguage !== 'undefined') {
|
||||
conditionType = 'script';
|
||||
values = script.get(element, conditionExpression);
|
||||
} else {
|
||||
conditionType = 'expression';
|
||||
values.condition = conditionExpression.get('body');
|
||||
}
|
||||
}
|
||||
|
||||
values.conditionType = conditionType;
|
||||
|
||||
return values;
|
||||
|
||||
},
|
||||
|
||||
set: function(element, values, containerElement) {
|
||||
var conditionType = values.conditionType;
|
||||
var commands = [];
|
||||
|
||||
var conditionProps = {
|
||||
body: undefined
|
||||
};
|
||||
|
||||
if (conditionType === 'script') {
|
||||
conditionProps = script.set(element, values, containerElement);
|
||||
} else {
|
||||
var condition = values.condition;
|
||||
|
||||
conditionProps.body = condition;
|
||||
}
|
||||
|
||||
var conditionOrConditionExpression;
|
||||
|
||||
if (conditionType) {
|
||||
conditionOrConditionExpression = elementHelper.createElement(
|
||||
'bpmn:FormalExpression',
|
||||
conditionProps,
|
||||
conditionalEventDefinition || bo,
|
||||
bpmnFactory
|
||||
);
|
||||
|
||||
var source = element.source;
|
||||
|
||||
// if default-flow, remove default-property from source
|
||||
if (source && source.businessObject.default === bo) {
|
||||
commands.push(cmdHelper.updateProperties(source, { 'default': undefined }));
|
||||
}
|
||||
}
|
||||
|
||||
var update = conditionalEventDefinition
|
||||
? { condition: conditionOrConditionExpression }
|
||||
: { conditionExpression: conditionOrConditionExpression };
|
||||
|
||||
commands.push(cmdHelper.updateBusinessObject(element, conditionalEventDefinition || bo, update));
|
||||
|
||||
return commands;
|
||||
},
|
||||
|
||||
validate: function(element, values) {
|
||||
var validationResult = {};
|
||||
|
||||
if (!values.condition && values.conditionType === 'expression') {
|
||||
validationResult.condition = translate('Must provide a value');
|
||||
}
|
||||
else if (values.conditionType === 'script') {
|
||||
validationResult = script.validate(element, values);
|
||||
}
|
||||
|
||||
return validationResult;
|
||||
},
|
||||
|
||||
isExpression: function(element, inputNode) {
|
||||
var conditionType = domQuery('select[name=conditionType]', inputNode);
|
||||
if (conditionType.selectedIndex >= 0) {
|
||||
return conditionType.options[conditionType.selectedIndex].value === 'expression';
|
||||
}
|
||||
},
|
||||
|
||||
isScript: function(element, inputNode) {
|
||||
var conditionType = domQuery('select[name=conditionType]', inputNode);
|
||||
if (conditionType.selectedIndex >= 0) {
|
||||
return conditionType.options[conditionType.selectedIndex].value === 'script';
|
||||
}
|
||||
},
|
||||
|
||||
clear: function(element, inputNode) {
|
||||
// clear text input
|
||||
domQuery('input[name=condition]', inputNode).value='';
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
canClear: function(element, inputNode) {
|
||||
var input = domQuery('input[name=condition]', inputNode);
|
||||
|
||||
return input.value !== '';
|
||||
},
|
||||
|
||||
script : script,
|
||||
|
||||
cssClasses: [ 'bpp-textfield' ]
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// utilities //////////////////////////
|
||||
|
||||
var CONDITIONAL_SOURCES = [
|
||||
'bpmn:Activity',
|
||||
'bpmn:ExclusiveGateway',
|
||||
'bpmn:InclusiveGateway',
|
||||
'bpmn:ComplexGateway'
|
||||
];
|
||||
|
||||
function isConditionalSource(element) {
|
||||
return isAny(element, CONDITIONAL_SOURCES);
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
var ImplementationTypeHelper = require('../../../helper/ImplementationTypeHelper'),
|
||||
InputOutputHelper = require('../../../helper/InputOutputHelper');
|
||||
|
||||
var entryFactory = require('../../../factory/EntryFactory'),
|
||||
cmdHelper = require('../../../helper/CmdHelper');
|
||||
|
||||
function getImplementationType(element) {
|
||||
return ImplementationTypeHelper.getImplementationType(element);
|
||||
}
|
||||
|
||||
function getBusinessObject(element) {
|
||||
return ImplementationTypeHelper.getServiceTaskLikeBusinessObject(element);
|
||||
}
|
||||
|
||||
function getConnector(bo) {
|
||||
return InputOutputHelper.getConnector(bo);
|
||||
}
|
||||
|
||||
function isConnector(element) {
|
||||
return getImplementationType(element) === 'connector';
|
||||
}
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
group.entries.push(entryFactory.textField({
|
||||
id: 'connectorId',
|
||||
label: translate('Connector Id'),
|
||||
modelProperty: 'connectorId',
|
||||
|
||||
get: function(element, node) {
|
||||
var bo = getBusinessObject(element);
|
||||
var connector = bo && getConnector(bo);
|
||||
var value = connector && connector.get('connectorId');
|
||||
return { connectorId: value };
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var bo = getBusinessObject(element);
|
||||
var connector = getConnector(bo);
|
||||
return cmdHelper.updateBusinessObject(element, connector, {
|
||||
connectorId: values.connectorId || undefined
|
||||
});
|
||||
},
|
||||
|
||||
validate: function(element, values, node) {
|
||||
return isConnector(element) && !values.connectorId ? { connectorId: translate('Must provide a value') } : {};
|
||||
},
|
||||
|
||||
hidden: function(element, node) {
|
||||
return !isConnector(element);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
var assign = require('lodash/assign');
|
||||
|
||||
var inputOutputParameter = require('./implementation/InputOutputParameter');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, options, translate) {
|
||||
|
||||
options = assign({
|
||||
idPrefix: 'connector-',
|
||||
insideConnector: true
|
||||
}, options);
|
||||
|
||||
group.entries = group.entries.concat(inputOutputParameter(element, bpmnFactory, options, translate));
|
||||
|
||||
};
|
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
var inputOutput = require('./implementation/InputOutput');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
var inputOutputEntry = inputOutput(element, bpmnFactory, {
|
||||
idPrefix: 'connector-',
|
||||
insideConnector: true
|
||||
}, translate);
|
||||
|
||||
group.entries = group.entries.concat(inputOutputEntry.entries);
|
||||
|
||||
return {
|
||||
getSelectedParameter: inputOutputEntry.getSelectedParameter
|
||||
};
|
||||
|
||||
};
|
@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
eventDefinitionHelper = require('../../../helper/EventDefinitionHelper'),
|
||||
error = require('./implementation/ErrorEventDefinition');
|
||||
|
||||
var forEach = require('lodash/forEach');
|
||||
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
var errorEvents = [
|
||||
'bpmn:StartEvent',
|
||||
'bpmn:BoundaryEvent',
|
||||
'bpmn:EndEvent'
|
||||
];
|
||||
|
||||
forEach(errorEvents, function(event) {
|
||||
if (is(element, event)) {
|
||||
|
||||
var errorEventDefinition = eventDefinitionHelper.getErrorEventDefinition(element);
|
||||
|
||||
if (errorEventDefinition) {
|
||||
var isCatchingErrorEvent = is(element, 'bpmn:StartEvent') || is (element, 'bpmn:BoundaryEvent');
|
||||
|
||||
var showErrorCodeVariable = isCatchingErrorEvent,
|
||||
showErrorMessageVariable = isCatchingErrorEvent;
|
||||
|
||||
error(
|
||||
group,
|
||||
element,
|
||||
bpmnFactory,
|
||||
errorEventDefinition,
|
||||
showErrorCodeVariable,
|
||||
showErrorMessageVariable,
|
||||
translate);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
var ImplementationTypeHelper = require('../../../helper/ImplementationTypeHelper');
|
||||
|
||||
var externalTaskPriority = require('./implementation/ExternalTaskPriority');
|
||||
|
||||
function getServiceTaskLikeBusinessObject(element) {
|
||||
var bo = ImplementationTypeHelper.getServiceTaskLikeBusinessObject(element);
|
||||
|
||||
// if the element is not a serviceTaskLike element, fetch the normal business object
|
||||
// This avoids the loss of the process / participant business object
|
||||
if (!bo) {
|
||||
bo = getBusinessObject(element);
|
||||
}
|
||||
|
||||
return bo;
|
||||
}
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
var bo = getServiceTaskLikeBusinessObject(element);
|
||||
|
||||
if (!bo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is(bo, 'activiti:TaskPriorized') || (is(bo, 'bpmn:Participant')) && bo.get('processRef')) {
|
||||
group.entries = group.entries.concat(externalTaskPriority(element, bpmnFactory, {
|
||||
getBusinessObject: function(element) {
|
||||
if (!is(bo, 'bpmn:Participant')) {
|
||||
return bo;
|
||||
}
|
||||
return bo.get('processRef');
|
||||
}
|
||||
}, translate));
|
||||
}
|
||||
};
|
@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
var ImplementationTypeHelper = require('../../../helper/ImplementationTypeHelper');
|
||||
|
||||
var fieldInjection = require('./implementation/FieldInjection');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
var bo = ImplementationTypeHelper.getServiceTaskLikeBusinessObject(element);
|
||||
|
||||
if (!bo) {
|
||||
return;
|
||||
}
|
||||
|
||||
var fieldInjectionEntry = fieldInjection(element, bpmnFactory, translate, { businessObject: bo });
|
||||
|
||||
if (fieldInjectionEntry && fieldInjectionEntry.length > 0) {
|
||||
group.entries = group.entries.concat(fieldInjectionEntry);
|
||||
}
|
||||
|
||||
};
|
@ -0,0 +1,476 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
getExtensionElements = require('../../../helper/ExtensionElementsHelper').getExtensionElements,
|
||||
removeEntry = require('../../../helper/ExtensionElementsHelper').removeEntry,
|
||||
extensionElements = require('./implementation/ExtensionElements'),
|
||||
properties = require('./implementation/Properties'),
|
||||
entryFactory = require('../../../factory/EntryFactory'),
|
||||
elementHelper = require('../../../helper/ElementHelper'),
|
||||
cmdHelper = require('../../../helper/CmdHelper'),
|
||||
formHelper = require('../../../helper/FormHelper'),
|
||||
utils = require('../../../Utils'),
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
find = require('lodash/find'),
|
||||
each = require('lodash/forEach');
|
||||
|
||||
function generateValueId() {
|
||||
return utils.nextId('Value_');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a form field specific textField using entryFactory.
|
||||
*
|
||||
* @param {string} options.id
|
||||
* @param {string} options.label
|
||||
* @param {string} options.modelProperty
|
||||
* @param {function} options.validate
|
||||
*
|
||||
* @return {Object} an entryFactory.textField object
|
||||
*/
|
||||
function formFieldTextField(options, getSelectedFormField) {
|
||||
|
||||
var id = options.id,
|
||||
label = options.label,
|
||||
modelProperty = options.modelProperty,
|
||||
validate = options.validate;
|
||||
|
||||
return entryFactory.textField({
|
||||
id: id,
|
||||
label: label,
|
||||
modelProperty: modelProperty,
|
||||
get: function(element, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node) || {},
|
||||
values = {};
|
||||
|
||||
values[modelProperty] = selectedFormField[modelProperty];
|
||||
|
||||
return values;
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var commands = [];
|
||||
|
||||
if (typeof options.set === 'function') {
|
||||
var cmd = options.set(element, values, node);
|
||||
|
||||
if (cmd) {
|
||||
commands.push(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
var formField = getSelectedFormField(element, node),
|
||||
properties = {};
|
||||
|
||||
properties[modelProperty] = values[modelProperty] || undefined;
|
||||
|
||||
commands.push(cmdHelper.updateBusinessObject(element, formField, properties));
|
||||
|
||||
return commands;
|
||||
},
|
||||
hidden: function(element, node) {
|
||||
return !getSelectedFormField(element, node);
|
||||
},
|
||||
validate: validate
|
||||
});
|
||||
}
|
||||
|
||||
function ensureFormKeyAndDataSupported(element) {
|
||||
return (
|
||||
is(element, 'bpmn:StartEvent') && !is(element.parent, 'bpmn:SubProcess')
|
||||
) || is(element, 'bpmn:UserTask');
|
||||
}
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
if (!ensureFormKeyAndDataSupported(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the currently selected form field querying the form field select box
|
||||
* from the DOM.
|
||||
*
|
||||
* @param {djs.model.Base} element
|
||||
* @param {DOMElement} node - DOM element of any form field text input
|
||||
*
|
||||
* @return {ModdleElement} the currently selected form field
|
||||
*/
|
||||
function getSelectedFormField(element, node) {
|
||||
var selected = formFieldsEntry.getSelected(element, node.parentNode);
|
||||
|
||||
if (selected.idx === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
return formHelper.getFormField(element, selected.idx);
|
||||
}
|
||||
|
||||
// [FormKey] form key text input field
|
||||
group.entries.push(entryFactory.textField({
|
||||
id : 'form-key',
|
||||
label : translate('Form Key'),
|
||||
modelProperty: 'formKey',
|
||||
get: function(element, node) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
return {
|
||||
formKey: bo.get('activiti:formKey')
|
||||
};
|
||||
},
|
||||
set: function(element, values, node) {
|
||||
var bo = getBusinessObject(element),
|
||||
formKey = values.formKey || undefined;
|
||||
|
||||
return cmdHelper.updateBusinessObject(element, bo, { 'activiti:formKey': formKey });
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] form field select box
|
||||
var formFieldsEntry = extensionElements(element, bpmnFactory, {
|
||||
id: 'form-fields',
|
||||
label: translate('Form Fields'),
|
||||
modelProperty: 'id',
|
||||
prefix: 'FormProperty',
|
||||
createExtensionElement: function(element, extensionElements, value) {
|
||||
var bo = getBusinessObject(element), commands = [];
|
||||
|
||||
if (!extensionElements) {
|
||||
extensionElements = elementHelper.createElement('bpmn:ExtensionElements', { values: [] }, bo, bpmnFactory);
|
||||
commands.push(cmdHelper.updateProperties(element, { extensionElements: extensionElements }));
|
||||
}
|
||||
/* var formData = formHelper.getFormData(element);
|
||||
|
||||
if (!formData) {
|
||||
formData = elementHelper.createElement('activiti:FormData', { fields: [] }, extensionElements, bpmnFactory);
|
||||
commands.push(cmdHelper.addAndRemoveElementsFromList(
|
||||
element,
|
||||
extensionElements,
|
||||
'values',
|
||||
'extensionElements',
|
||||
[formData],
|
||||
[]
|
||||
));
|
||||
}*/
|
||||
/**activiti 是向 extensionElements 下追加元素,而不是 formData 下,*/
|
||||
var field = elementHelper.createElement('activiti:FormProperty', { id: value }, extensionElements, bpmnFactory);
|
||||
if (typeof extensionElements.values !== 'undefined') {
|
||||
commands.push(cmdHelper.addElementsTolist(element, extensionElements, 'values', [ field ]));
|
||||
} else {
|
||||
commands.push(cmdHelper.updateBusinessObject(element, extensionElements, {
|
||||
values: [ field ]
|
||||
}));
|
||||
}
|
||||
return commands;
|
||||
},
|
||||
removeExtensionElement: function(element, extensionElements, value, idx) {
|
||||
var fields = formHelper.getFormFields(element);
|
||||
var entry = fields[idx],
|
||||
commands = [];
|
||||
|
||||
if (fields.length < 2) {
|
||||
commands.push(removeEntry(getBusinessObject(element), element, extensionElements));
|
||||
} else {
|
||||
commands.push(cmdHelper.removeElementsFromList(element, extensionElements, 'values', null, [entry]));
|
||||
/* if (entry.id === formData.get('businessKey')) {
|
||||
commands.push(cmdHelper.updateBusinessObject(element, extensionElements, { 'businessKey': undefined }));
|
||||
}*/
|
||||
}
|
||||
|
||||
return commands;
|
||||
},
|
||||
getExtensionElements: function(element) {
|
||||
return formHelper.getFormFields(element);
|
||||
},
|
||||
hideExtensionElements: function(element, node) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
group.entries.push(formFieldsEntry);
|
||||
|
||||
|
||||
// [FormData] Form Field label
|
||||
group.entries.push(entryFactory.label({
|
||||
id: 'form-field-header',
|
||||
labelText: translate('Form Field'),
|
||||
showLabel: function(element, node) {
|
||||
return !!getSelectedFormField(element, node);
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] form field id text input field
|
||||
group.entries.push(entryFactory.validationAwareTextField({
|
||||
id: 'form-field-id',
|
||||
label: translate('ID'),
|
||||
modelProperty: 'id',
|
||||
|
||||
getProperty: function(element, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node) || {};
|
||||
|
||||
return selectedFormField.id;
|
||||
},
|
||||
|
||||
setProperty: function(element, properties, node) {
|
||||
var formField = getSelectedFormField(element, node);
|
||||
|
||||
return cmdHelper.updateBusinessObject(element, formField, properties);
|
||||
},
|
||||
|
||||
hidden: function(element, node) {
|
||||
return !getSelectedFormField(element, node);
|
||||
},
|
||||
|
||||
validate: function(element, values, node) {
|
||||
|
||||
var formField = getSelectedFormField(element, node);
|
||||
|
||||
if (formField) {
|
||||
|
||||
var idValue = values.id;
|
||||
|
||||
if (!idValue || idValue.trim() === '') {
|
||||
return { id: 'Form field id must not be empty' };
|
||||
}
|
||||
|
||||
var formFields = formHelper.getFormFields(element);
|
||||
|
||||
var existingFormField = find(formFields, function(f) {
|
||||
return f !== formField && f.id === idValue;
|
||||
});
|
||||
|
||||
if (existingFormField) {
|
||||
return { id: 'Form field id already used in form data.' };
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] form field type combo box
|
||||
group.entries.push(entryFactory.comboBox({
|
||||
id: 'form-field-type',
|
||||
label: translate('Type'),
|
||||
selectOptions: [
|
||||
{ name: 'string', value: 'string' },
|
||||
{ name: 'long', value: 'long' },
|
||||
{ name: 'boolean', value: 'boolean' },
|
||||
{ name: 'date', value: 'date' },
|
||||
{ name: 'enum', value: 'enum' }
|
||||
],
|
||||
modelProperty: 'type',
|
||||
emptyParameter: true,
|
||||
|
||||
get: function(element, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node);
|
||||
|
||||
if (selectedFormField) {
|
||||
return { type: selectedFormField.type };
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
set: function(element, values, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node),
|
||||
commands = [];
|
||||
|
||||
if (selectedFormField.type === 'enum' && values.type !== 'enum') {
|
||||
// delete activiti:value objects from formField.values when switching from type enum
|
||||
commands.push(cmdHelper.updateBusinessObject(element, selectedFormField, { values: undefined }));
|
||||
}
|
||||
commands.push(cmdHelper.updateBusinessObject(element, selectedFormField, values));
|
||||
|
||||
return commands;
|
||||
},
|
||||
hidden: function(element, node) {
|
||||
return !getSelectedFormField(element, node);
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] form field label text input field
|
||||
group.entries.push(formFieldTextField({
|
||||
id: 'form-field-label',
|
||||
label: translate('Label'),
|
||||
modelProperty: 'label'
|
||||
}, getSelectedFormField));
|
||||
|
||||
// [FormData] form field defaultValue text input field
|
||||
group.entries.push(formFieldTextField({
|
||||
id: 'form-field-defaultValue',
|
||||
label: translate('Default Value'),
|
||||
modelProperty: 'defaultValue'
|
||||
}, getSelectedFormField));
|
||||
|
||||
|
||||
// [FormData] form field enum values label
|
||||
group.entries.push(entryFactory.label({
|
||||
id: 'form-field-enum-values-header',
|
||||
labelText: translate('Values'),
|
||||
divider: true,
|
||||
showLabel: function(element, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node);
|
||||
|
||||
return selectedFormField && selectedFormField.type === 'enum';
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] form field enum values table
|
||||
group.entries.push(entryFactory.table({
|
||||
id: 'form-field-enum-values',
|
||||
labels: [ translate('Id'), translate('Name') ],
|
||||
modelProperties: [ 'id', 'name' ],
|
||||
addLabel:translate('Add Value'),
|
||||
show: function(element, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node);
|
||||
|
||||
return selectedFormField && selectedFormField.type === 'enum';
|
||||
},
|
||||
getElements: function(element, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node);
|
||||
|
||||
return formHelper.getEnumValues(selectedFormField);
|
||||
},
|
||||
addElement: function(element, node) {
|
||||
var selectedFormField = getSelectedFormField(element, node),
|
||||
id = generateValueId();
|
||||
|
||||
var enumValue = elementHelper.createElement(
|
||||
'activiti:Value',
|
||||
{ id: id, name: undefined },
|
||||
getBusinessObject(element),
|
||||
bpmnFactory
|
||||
);
|
||||
|
||||
return cmdHelper.addElementsTolist(element, selectedFormField, 'values', [enumValue]);
|
||||
},
|
||||
removeElement: function(element, node, idx) {
|
||||
var selectedFormField = getSelectedFormField(element, node),
|
||||
enumValue = selectedFormField.values[idx];
|
||||
|
||||
return cmdHelper.removeElementsFromList(element, selectedFormField, 'values', null, [enumValue]);
|
||||
},
|
||||
updateElement: function(element, value, node, idx) {
|
||||
var selectedFormField = getSelectedFormField(element, node),
|
||||
enumValue = selectedFormField.values[idx];
|
||||
|
||||
value.name = value.name || undefined;
|
||||
return cmdHelper.updateBusinessObject(element, enumValue, value);
|
||||
},
|
||||
validate: function(element, value, node, idx) {
|
||||
|
||||
var selectedFormField = getSelectedFormField(element, node),
|
||||
enumValue = selectedFormField.values[idx];
|
||||
|
||||
if (enumValue) {
|
||||
// check if id is valid
|
||||
var validationError = utils.isIdValid(enumValue, value.id, translate);
|
||||
|
||||
if (validationError) {
|
||||
return { id: validationError };
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] Validation label
|
||||
group.entries.push(entryFactory.label({
|
||||
id: 'form-field-validation-header',
|
||||
labelText: translate('Validation'),
|
||||
divider: true,
|
||||
showLabel: function(element, node) {
|
||||
return !!getSelectedFormField(element, node);
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] form field constraints table
|
||||
group.entries.push(entryFactory.table({
|
||||
id: 'constraints-list',
|
||||
modelProperties: [ 'name', 'config' ],
|
||||
labels: [ translate('Name'), translate('Config') ],
|
||||
addLabel: translate('Add Constraint'),
|
||||
getElements: function(element, node) {
|
||||
var formField = getSelectedFormField(element, node);
|
||||
|
||||
return formHelper.getConstraints(formField);
|
||||
},
|
||||
addElement: function(element, node) {
|
||||
|
||||
var commands = [],
|
||||
formField = getSelectedFormField(element, node),
|
||||
validation = formField.validation;
|
||||
|
||||
if (!validation) {
|
||||
// create validation business object and add it to form data, if it doesn't exist
|
||||
validation = elementHelper.createElement('activiti:Validation', {}, getBusinessObject(element), bpmnFactory);
|
||||
|
||||
commands.push(cmdHelper.updateBusinessObject(element, formField, { 'validation': validation }));
|
||||
}
|
||||
|
||||
var newConstraint = elementHelper.createElement(
|
||||
'activiti:Constraint',
|
||||
{ name: undefined, config: undefined },
|
||||
validation,
|
||||
bpmnFactory
|
||||
);
|
||||
|
||||
commands.push(cmdHelper.addElementsTolist(element, validation, 'constraints', [ newConstraint ]));
|
||||
|
||||
return commands;
|
||||
},
|
||||
updateElement: function(element, value, node, idx) {
|
||||
var formField = getSelectedFormField(element, node),
|
||||
constraint = formHelper.getConstraints(formField)[idx];
|
||||
|
||||
value.name = value.name || undefined;
|
||||
value.config = value.config || undefined;
|
||||
|
||||
return cmdHelper.updateBusinessObject(element, constraint, value);
|
||||
},
|
||||
removeElement: function(element, node, idx) {
|
||||
var commands = [],
|
||||
formField = getSelectedFormField(element, node),
|
||||
constraints = formHelper.getConstraints(formField),
|
||||
currentConstraint = constraints[idx];
|
||||
|
||||
commands.push(cmdHelper.removeElementsFromList(
|
||||
element,
|
||||
formField.validation,
|
||||
'constraints',
|
||||
null,
|
||||
[ currentConstraint ]
|
||||
));
|
||||
|
||||
if (constraints.length === 1) {
|
||||
// remove activiti:validation if the last existing constraint has been removed
|
||||
commands.push(cmdHelper.updateBusinessObject(element, formField, { validation: undefined }));
|
||||
}
|
||||
|
||||
return commands;
|
||||
},
|
||||
show: function(element, node) {
|
||||
return !!getSelectedFormField(element, node);
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] Properties label
|
||||
group.entries.push(entryFactory.label({
|
||||
id: 'form-field-properties-header',
|
||||
labelText: translate('Properties'),
|
||||
divider: true,
|
||||
showLabel: function(element, node) {
|
||||
return !!getSelectedFormField(element, node);
|
||||
}
|
||||
}));
|
||||
|
||||
// [FormData] activiti:properties table
|
||||
group.entries.push(properties(element, bpmnFactory, {
|
||||
id: 'form-field-properties',
|
||||
modelProperties: [ 'id', 'value' ],
|
||||
labels: [ translate('Id'), translate('Value') ],
|
||||
getParent: function(element, node) {
|
||||
return getSelectedFormField(element, node);
|
||||
},
|
||||
show: function(element, node) {
|
||||
return !!getSelectedFormField(element, node);
|
||||
}
|
||||
}, translate));
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
var historyTimeToLive = require('./implementation/HistoryTimeToLive');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
var businessObject = getBusinessObject(element);
|
||||
|
||||
if (is(element, 'activiti:Process') ||
|
||||
is(element, 'bpmn:Participant') && businessObject.get('processRef')) {
|
||||
|
||||
group.entries = group.entries.concat(historyTimeToLive(element, bpmnFactory, {
|
||||
getBusinessObject: function(element) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (!is(bo, 'bpmn:Participant')) {
|
||||
return bo;
|
||||
}
|
||||
|
||||
return bo.get('processRef');
|
||||
}
|
||||
}, translate));
|
||||
|
||||
}
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
var inputOutputParameter = require('./implementation/InputOutputParameter');
|
||||
|
||||
var assign = require('lodash/assign');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, options, translate) {
|
||||
|
||||
group.entries = group.entries.concat(inputOutputParameter(element, bpmnFactory, assign({}, options), translate));
|
||||
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
var inputOutput = require('./implementation/InputOutput');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
var inputOutputEntry = inputOutput(element, bpmnFactory, {}, translate);
|
||||
|
||||
group.entries = group.entries.concat(inputOutputEntry.entries);
|
||||
|
||||
return {
|
||||
getSelectedParameter: inputOutputEntry.getSelectedParameter
|
||||
};
|
||||
|
||||
};
|
@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
var jobPriority = require('./implementation/JobPriority'),
|
||||
jobRetryTimeCycle = require('./implementation/JobRetryTimeCycle');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
var businessObject = getBusinessObject(element);
|
||||
|
||||
if (is(element, 'activiti:JobPriorized') ||
|
||||
is(element, 'bpmn:Participant') && businessObject.get('processRef')) {
|
||||
|
||||
group.entries = group.entries.concat(jobPriority(element, bpmnFactory, {
|
||||
getBusinessObject: function(element) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (!is(bo, 'bpmn:Participant')) {
|
||||
return bo;
|
||||
}
|
||||
|
||||
return bo.get('processRef');
|
||||
}
|
||||
}, translate));
|
||||
}
|
||||
|
||||
if (is(element, 'activiti:AsyncCapable')) {
|
||||
group.entries = group.entries.concat(jobRetryTimeCycle(element, bpmnFactory, {
|
||||
getBusinessObject: getBusinessObject
|
||||
}, translate));
|
||||
}
|
||||
|
||||
};
|
@ -0,0 +1,208 @@
|
||||
'use strict';
|
||||
|
||||
var entryFactory = require('../../../factory/EntryFactory');
|
||||
|
||||
var cmdHelper = require('../../../helper/CmdHelper'),
|
||||
ImplementationTypeHelper = require('../../../helper/ImplementationTypeHelper'),
|
||||
|
||||
scriptImplementation = require('./implementation/Script');
|
||||
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, options, translate) {
|
||||
|
||||
var LISTENER_TYPE_LABEL = {
|
||||
class: translate('Java Class'),
|
||||
expression: translate('Expression'),
|
||||
delegateExpression: translate('Delegate Expression'),
|
||||
script: translate('Script')
|
||||
};
|
||||
|
||||
options = options || {};
|
||||
|
||||
var getSelectedListener = options.getSelectedListener;
|
||||
|
||||
var classProp = 'class',
|
||||
expressionProp = 'expression',
|
||||
delegateExpressionProp = 'delegateExpression',
|
||||
scriptProp = 'script';
|
||||
|
||||
var executionListenerEventTypeOptions = ImplementationTypeHelper.isSequenceFlow(element) ? [
|
||||
{ name: translate('take'), value: 'take' }
|
||||
] : [
|
||||
{ name: translate('start'), value: 'start' },
|
||||
{ name: translate('end'), value: 'end' }
|
||||
];
|
||||
|
||||
var taskListenerEventTypeOptions = [
|
||||
{ name: translate('create'), value: 'create' },
|
||||
{ name: translate('assignment'), value: 'assignment' },
|
||||
{ name: translate('complete'), value: 'complete' },
|
||||
{ name: translate('delete'), value: 'delete' }
|
||||
];
|
||||
|
||||
var isSelected = function(element, node) {
|
||||
return getSelectedListener(element, node);
|
||||
};
|
||||
|
||||
group.entries.push(entryFactory.selectBox({
|
||||
id: 'listener-event-type',
|
||||
label: translate('Event Type'),
|
||||
modelProperty: 'eventType',
|
||||
emptyParameter: false,
|
||||
|
||||
get: function(element, node) {
|
||||
|
||||
|
||||
var listener = getSelectedListener(element, node);
|
||||
|
||||
var eventType = listener && listener.get('event');
|
||||
|
||||
return {
|
||||
eventType: eventType
|
||||
};
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var eventType = values.eventType;
|
||||
|
||||
return cmdHelper.updateBusinessObject(element, getSelectedListener(element, node), { event: eventType });
|
||||
},
|
||||
|
||||
selectOptions: function(element, node) {
|
||||
var eventTypeOptions;
|
||||
|
||||
var selectedListener = getSelectedListener(element, node);
|
||||
if (ImplementationTypeHelper.isTaskListener(selectedListener)) {
|
||||
eventTypeOptions = taskListenerEventTypeOptions;
|
||||
} else if (ImplementationTypeHelper.isExecutionListener(selectedListener)) {
|
||||
eventTypeOptions = executionListenerEventTypeOptions;
|
||||
}
|
||||
|
||||
return eventTypeOptions;
|
||||
|
||||
},
|
||||
|
||||
hidden: function(element, node) {
|
||||
return !isSelected(element, node);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
|
||||
group.entries.push(entryFactory.selectBox({
|
||||
id: 'listener-type',
|
||||
label: translate('Listener Type'),
|
||||
selectOptions: [
|
||||
{ value: classProp, name: translate('Java Class') },
|
||||
{ value: expressionProp, name: translate('Expression') },
|
||||
{ value: delegateExpressionProp, name: translate('Delegate Expression') },
|
||||
{ value: scriptProp, name: translate('Script') }
|
||||
],
|
||||
modelProperty: 'listenerType',
|
||||
emptyParameter: false,
|
||||
|
||||
get: function(element, node) {
|
||||
var listener = getSelectedListener(element, node);
|
||||
return {
|
||||
listenerType: ImplementationTypeHelper.getImplementationType(listener)
|
||||
};
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var listener = getSelectedListener(element, node),
|
||||
listenerType = values.listenerType || undefined,
|
||||
update = {};
|
||||
|
||||
update[classProp] = listenerType === classProp ? '' : undefined;
|
||||
update[expressionProp] = listenerType === expressionProp ? '' : undefined;
|
||||
update[delegateExpressionProp] = listenerType === delegateExpressionProp ? '' : undefined;
|
||||
update[scriptProp] = listenerType === scriptProp ? bpmnFactory.create('activiti:Script') : undefined;
|
||||
|
||||
return cmdHelper.updateBusinessObject(element, listener, update);
|
||||
},
|
||||
|
||||
hidden: function(element, node) {
|
||||
return !isSelected(element, node);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
|
||||
group.entries.push(entryFactory.textField({
|
||||
id: 'listener-value',
|
||||
dataValueLabel: 'listenerValueLabel',
|
||||
modelProperty: 'listenerValue',
|
||||
|
||||
get: function(element, node) {
|
||||
var value = {},
|
||||
listener = getSelectedListener(element, node),
|
||||
listenerType = ImplementationTypeHelper.getImplementationType(listener);
|
||||
|
||||
value.listenerValueLabel = LISTENER_TYPE_LABEL[listenerType] || '';
|
||||
value.listenerValue = (listener && listener.get(listenerType)) || undefined;
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var update = {},
|
||||
listener = getSelectedListener(element, node),
|
||||
listenerType = ImplementationTypeHelper.getImplementationType(listener);
|
||||
|
||||
update[listenerType] = values.listenerValue || '';
|
||||
|
||||
return cmdHelper.updateBusinessObject(element, listener, update);
|
||||
},
|
||||
|
||||
hidden: function(element, node) {
|
||||
var listener = getSelectedListener(element, node);
|
||||
return !listener || listener.script;
|
||||
},
|
||||
|
||||
validate: function(element, values) {
|
||||
var value = values.listenerValue,
|
||||
validate = {};
|
||||
|
||||
if (!value) {
|
||||
validate.listenerValue = translate('Must provide a value');
|
||||
}
|
||||
|
||||
return validate;
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
var script = scriptImplementation('scriptFormat', 'value', true, translate);
|
||||
|
||||
group.entries.push({
|
||||
id: 'listener-script-value',
|
||||
html: '<div data-show="isScript">' +
|
||||
script.template +
|
||||
'</div>',
|
||||
|
||||
get: function(element, node) {
|
||||
var listener = getSelectedListener(element, node);
|
||||
return listener && listener.script ? script.get(element, listener.script) : {};
|
||||
},
|
||||
|
||||
set: function(element, values, node) {
|
||||
var listener = getSelectedListener(element, node);
|
||||
var update = script.set(element, values, listener);
|
||||
return cmdHelper.updateBusinessObject(element, listener.script, update);
|
||||
},
|
||||
|
||||
validate: function(element, values, node) {
|
||||
var listener = getSelectedListener(element, node);
|
||||
return listener && listener.script ? script.validate(element, values) : {};
|
||||
},
|
||||
|
||||
isScript: function(element, node) {
|
||||
var listener = getSelectedListener(element, node);
|
||||
return listener && listener.script;
|
||||
},
|
||||
|
||||
script: script
|
||||
|
||||
});
|
||||
|
||||
};
|
@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
var assign = require('lodash/assign');
|
||||
|
||||
var fieldInjection = require('./implementation/FieldInjection');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, options, translate) {
|
||||
|
||||
options = assign({
|
||||
idPrefix: 'listener-',
|
||||
insideListener: true
|
||||
}, options);
|
||||
|
||||
var fieldInjectionEntry = fieldInjection(element, bpmnFactory, translate, options);
|
||||
|
||||
if (fieldInjectionEntry && fieldInjectionEntry.length > 0) {
|
||||
group.entries = group.entries.concat(fieldInjectionEntry);
|
||||
}
|
||||
|
||||
};
|
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
var listener = require('./implementation/Listener');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
var listenerEntry = listener(element, bpmnFactory, {}, translate);
|
||||
|
||||
group.entries = group.entries.concat(listenerEntry.entries);
|
||||
|
||||
return {
|
||||
getSelectedListener: listenerEntry.getSelectedListener
|
||||
};
|
||||
|
||||
};
|
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is;
|
||||
|
||||
var multiInstanceLoopCharacteristics = require('./implementation/MultiInstanceLoopCharacteristics');
|
||||
|
||||
var jobRetryTimeCycle = require('./implementation/JobRetryTimeCycle'),
|
||||
asyncContinuation = require('./implementation/AsyncContinuation');
|
||||
|
||||
|
||||
function getLoopCharacteristics(element) {
|
||||
var bo = getBusinessObject(element);
|
||||
return bo.loopCharacteristics;
|
||||
}
|
||||
|
||||
|
||||
function ensureMultiInstanceSupported(element) {
|
||||
var loopCharacteristics = getLoopCharacteristics(element);
|
||||
return !!loopCharacteristics && is(loopCharacteristics, 'activiti:Collectable');
|
||||
}
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
if (!ensureMultiInstanceSupported(element)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// multi instance properties
|
||||
group.entries = group.entries.concat(multiInstanceLoopCharacteristics(element, bpmnFactory, translate));
|
||||
|
||||
// async continuation ///////////////////////////////////////////////////////
|
||||
group.entries = group.entries.concat(asyncContinuation(element, bpmnFactory, {
|
||||
getBusinessObject: getLoopCharacteristics,
|
||||
idPrefix: 'multiInstance-',
|
||||
labelPrefix: translate('Multi Instance ')
|
||||
}, translate));
|
||||
|
||||
|
||||
// retry time cycle //////////////////////////////////////////////////////////
|
||||
group.entries = group.entries.concat(jobRetryTimeCycle(element, bpmnFactory, {
|
||||
getBusinessObject: getLoopCharacteristics,
|
||||
idPrefix: 'multiInstance-',
|
||||
labelPrefix: translate('Multi Instance ')
|
||||
}, translate));
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
var properties = require('./implementation/Properties'),
|
||||
elementHelper = require('../../../helper/ElementHelper'),
|
||||
cmdHelper = require('../../../helper/CmdHelper');
|
||||
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
var propertiesEntry = properties(element, bpmnFactory, {
|
||||
id: 'properties',
|
||||
modelProperties: [ 'name', 'value' ],
|
||||
labels: [ translate('Name'), translate('Value') ],
|
||||
|
||||
getParent: function(element, node, bo) {
|
||||
return bo.extensionElements;
|
||||
},
|
||||
|
||||
createParent: function(element, bo) {
|
||||
var parent = elementHelper.createElement('bpmn:ExtensionElements', { values: [] }, bo, bpmnFactory);
|
||||
var cmd = cmdHelper.updateBusinessObject(element, bo, { extensionElements: parent });
|
||||
return {
|
||||
cmd: cmd,
|
||||
parent: parent
|
||||
};
|
||||
}
|
||||
}, translate);
|
||||
|
||||
if (propertiesEntry) {
|
||||
group.entries.push(propertiesEntry);
|
||||
}
|
||||
|
||||
};
|
@ -0,0 +1,68 @@
|
||||
'use strict';
|
||||
|
||||
var getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject,
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
entryFactory = require('../../../factory/EntryFactory'),
|
||||
cmdHelper = require('../../../helper/CmdHelper'),
|
||||
scriptImplementation = require('./implementation/Script');
|
||||
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
var bo;
|
||||
|
||||
if (is(element, 'bpmn:ScriptTask')) {
|
||||
bo = getBusinessObject(element);
|
||||
}
|
||||
|
||||
if (!bo) {
|
||||
return;
|
||||
}
|
||||
|
||||
var script = scriptImplementation('scriptFormat', 'script', false, translate);
|
||||
group.entries.push({
|
||||
id: 'script-implementation',
|
||||
label: translate('Script'),
|
||||
html: script.template,
|
||||
|
||||
get: function(element) {
|
||||
return script.get(element, bo);
|
||||
},
|
||||
|
||||
set: function(element, values, containerElement) {
|
||||
var properties = script.set(element, values, containerElement);
|
||||
|
||||
return cmdHelper.updateProperties(element, properties);
|
||||
},
|
||||
|
||||
validate: function(element, values) {
|
||||
return script.validate(element, values);
|
||||
},
|
||||
|
||||
script : script,
|
||||
|
||||
cssClasses: ['bpp-textfield']
|
||||
|
||||
});
|
||||
|
||||
group.entries.push(entryFactory.textField({
|
||||
id : 'scriptResultVariable',
|
||||
label : translate('Result Variable'),
|
||||
modelProperty : 'scriptResultVariable',
|
||||
|
||||
get: function(element, propertyName) {
|
||||
var boResultVariable = bo.get('activiti:resultVariable');
|
||||
|
||||
return { scriptResultVariable : boResultVariable };
|
||||
},
|
||||
|
||||
set: function(element, values, containerElement) {
|
||||
return cmdHelper.updateProperties(element, {
|
||||
'activiti:resultVariable': values.scriptResultVariable.length
|
||||
? values.scriptResultVariable
|
||||
: undefined
|
||||
});
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
};
|
@ -0,0 +1,151 @@
|
||||
'use strict';
|
||||
|
||||
var ImplementationTypeHelper = require('../../../helper/ImplementationTypeHelper'),
|
||||
InputOutputHelper = require('../../../helper/InputOutputHelper');
|
||||
|
||||
var utils = require('../../../Utils'),
|
||||
escapeHTML = utils.escapeHTML,
|
||||
triggerClickEvent = utils.triggerClickEvent;
|
||||
|
||||
var implementationType = require('./implementation/ImplementationType'),
|
||||
delegate = require('./implementation/Delegate'),
|
||||
external = require('./implementation/External'),
|
||||
callable = require('./implementation/Callable'),
|
||||
resultVariable = require('./implementation/ResultVariable');
|
||||
|
||||
var entryFactory = require('../../../factory/EntryFactory');
|
||||
|
||||
var domQuery = require('min-dom').query,
|
||||
domClosest = require('min-dom').closest,
|
||||
domClasses = require('min-dom').classes;
|
||||
|
||||
function getImplementationType(element) {
|
||||
return ImplementationTypeHelper.getImplementationType(element);
|
||||
}
|
||||
|
||||
function getBusinessObject(element) {
|
||||
return ImplementationTypeHelper.getServiceTaskLikeBusinessObject(element);
|
||||
}
|
||||
|
||||
function isDmnCapable(element) {
|
||||
return ImplementationTypeHelper.isDmnCapable(element);
|
||||
}
|
||||
|
||||
function isExternalCapable(element) {
|
||||
return ImplementationTypeHelper.isExternalCapable(element);
|
||||
}
|
||||
|
||||
function isServiceTaskLike(element) {
|
||||
return ImplementationTypeHelper.isServiceTaskLike(element);
|
||||
}
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
|
||||
if (!isServiceTaskLike(getBusinessObject(element))) {
|
||||
return;
|
||||
}
|
||||
|
||||
var hasDmnSupport = isDmnCapable(element);
|
||||
var hasExternalSupport = isExternalCapable(getBusinessObject(element));
|
||||
|
||||
// implementation type ////////////////////////////////////
|
||||
|
||||
group.entries = group.entries.concat(implementationType(element, bpmnFactory, {
|
||||
getBusinessObject: getBusinessObject,
|
||||
getImplementationType: getImplementationType,
|
||||
hasDmnSupport: hasDmnSupport,
|
||||
hasExternalSupport: hasExternalSupport,
|
||||
hasServiceTaskLikeSupport: true
|
||||
}, translate));
|
||||
|
||||
|
||||
// delegate (class, expression, delegateExpression) //////////
|
||||
|
||||
group.entries = group.entries.concat(delegate(element, bpmnFactory, {
|
||||
getBusinessObject: getBusinessObject,
|
||||
getImplementationType: getImplementationType
|
||||
}, translate));
|
||||
|
||||
|
||||
// result variable /////////////////////////////////////////
|
||||
|
||||
group.entries = group.entries.concat(resultVariable(element, bpmnFactory, {
|
||||
getBusinessObject: getBusinessObject,
|
||||
getImplementationType: getImplementationType,
|
||||
hideResultVariable: function(element, node) {
|
||||
return getImplementationType(element) !== 'expression';
|
||||
}
|
||||
}, translate));
|
||||
|
||||
// external //////////////////////////////////////////////////
|
||||
|
||||
if (hasExternalSupport) {
|
||||
group.entries = group.entries.concat(external(element, bpmnFactory, {
|
||||
getBusinessObject: getBusinessObject,
|
||||
getImplementationType: getImplementationType
|
||||
}, translate));
|
||||
}
|
||||
|
||||
|
||||
// dmn ////////////////////////////////////////////////////////
|
||||
|
||||
if (hasDmnSupport) {
|
||||
group.entries = group.entries.concat(callable(element, bpmnFactory, {
|
||||
getCallableType: getImplementationType
|
||||
}, translate));
|
||||
}
|
||||
|
||||
|
||||
// connector ////////////////////////////////////////////////
|
||||
|
||||
var isConnector = function(element) {
|
||||
return getImplementationType(element) === 'connector';
|
||||
};
|
||||
|
||||
group.entries.push(entryFactory.link({
|
||||
id: 'configureConnectorLink',
|
||||
label: translate('Configure Connector'),
|
||||
handleClick: function(element, node, event) {
|
||||
|
||||
var connectorTabEl = getTabNode(node, 'connector');
|
||||
|
||||
if (connectorTabEl) {
|
||||
triggerClickEvent(connectorTabEl);
|
||||
}
|
||||
|
||||
// suppress actual link click
|
||||
return false;
|
||||
},
|
||||
showLink: function(element, node) {
|
||||
var link = domQuery('a', node);
|
||||
link.textContent = '';
|
||||
|
||||
domClasses(link).remove('bpp-error-message');
|
||||
|
||||
if (isConnector(element)) {
|
||||
var connectorId = InputOutputHelper.getConnector(element).get('connectorId');
|
||||
if (connectorId) {
|
||||
link.textContent = translate('Configure Connector');
|
||||
} else {
|
||||
link.innerHTML = '<span class="bpp-icon-warning"></span> ' + escapeHTML(translate('Must configure Connector'));
|
||||
domClasses(link).add('bpp-error-message');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// helpers ///////////////////////////
|
||||
|
||||
function getTabNode(el, id) {
|
||||
var containerEl = domClosest(el, '.bpp-properties-panel');
|
||||
|
||||
return domQuery('a[data-tab-target="' + id + '"]', containerEl);
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
var entryFactory = require('../../../factory/EntryFactory'),
|
||||
is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
|
||||
module.exports = function(group, element, translate) {
|
||||
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (!bo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is(element, 'activiti:Initiator') && !is(element.parent, 'bpmn:SubProcess')) {
|
||||
group.entries.push(entryFactory.textField({
|
||||
id: 'initiator',
|
||||
label: translate('Initiator'),
|
||||
modelProperty: 'initiator'
|
||||
}));
|
||||
}
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
var is = require('bpmn-js/lib/util/ModelUtil').is,
|
||||
getBusinessObject = require('bpmn-js/lib/util/ModelUtil').getBusinessObject;
|
||||
|
||||
var tasklist = require('./implementation/Tasklist');
|
||||
|
||||
module.exports = function(group, element, bpmnFactory, translate) {
|
||||
var businessObject = getBusinessObject(element);
|
||||
|
||||
if (is(element, 'activiti:Process') ||
|
||||
is(element, 'bpmn:Participant') && businessObject.get('processRef')) {
|
||||
|
||||
group.entries = group.entries.concat(tasklist(element, bpmnFactory, {
|
||||
getBusinessObject: function(element) {
|
||||
var bo = getBusinessObject(element);
|
||||
|
||||
if (!is(bo, 'bpmn:Participant')) {
|
||||
return bo;
|
||||
}
|
||||
|
||||
return bo.get('processRef');
|
||||
}
|
||||
}, translate));
|
||||
|
||||
}
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue