You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
334 lines
13 KiB
334 lines
13 KiB
6 months ago
|
/* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
angular.module('flowableModeler')
|
||
|
.directive('loading', ['$translate', function ($translate) {
|
||
|
return {
|
||
|
restrict: 'E',
|
||
|
template: '<div class=\'loading pull-right\' ng-show=\'status.loading\'><div class=\'l1\'></div><div class=\'l2\'></div><div class=\'l2\'></div></div>'
|
||
|
};
|
||
|
}]);
|
||
|
|
||
|
angular.module('flowableModeler')
|
||
|
.directive('loadingLeftPull', ['$translate', function ($translate) {
|
||
|
return {
|
||
|
restrict: 'E',
|
||
|
template: '<div class=\'loading pull-left\' ng-show=\'status.loading\'><div class=\'l1\'></div><div class=\'l2\'></div><div class=\'l2\'></div></div>'
|
||
|
};
|
||
|
}]);
|
||
|
|
||
|
/**
|
||
|
* This is a template for the icon of a stencil item.
|
||
|
*/
|
||
|
angular.module('flowableModeler')
|
||
|
.directive('stencilItemIcon', [function () {
|
||
|
return {
|
||
|
scope: {
|
||
|
item: '=stencilItem'
|
||
|
},
|
||
|
restrict: 'E',
|
||
|
template: '<img class="stencil-item-list-icon" ng-if=\"item.customIconId != null && item.customIconId != undefined\" ng-src=\"' + getImageUrl(item.customIconId) + '\" width=\"16px\" height=\"16px\"/>' +
|
||
|
'<img class="stencil-item-list-icon" ng-if=\"(item.customIconId == null || item.customIconId == undefined) && item.icon != null && item.icon != undefined\" ng-src=\"editor-app/stencilsets/bpmn2.0/icons/{{item.icon}}\" width=\"16px\" height=\"16px\"/>'
|
||
|
};
|
||
|
}]);
|
||
|
|
||
|
// Workaround for https://github.com/twbs/bootstrap/issues/8379 :
|
||
|
// prototype.js interferes with regular dropdown behavior
|
||
|
angular.module('flowableModeler')
|
||
|
.directive('activitiFixDropdownBug', function () {
|
||
|
return {
|
||
|
restrict: 'AEC',
|
||
|
link: function (scope, element, attrs) {
|
||
|
if (!element.hasClass('btn-group')) {
|
||
|
// Fix applied to button, use parent instead
|
||
|
element = element.parent();
|
||
|
}
|
||
|
element.on('hidden.bs.dropdown ', function () {
|
||
|
element.show(); // evil prototype.js has added display:none to it ...
|
||
|
})
|
||
|
}
|
||
|
};
|
||
|
});
|
||
|
|
||
|
|
||
|
//form builder element renderer
|
||
|
angular.module('flowableModeler').directive('formBuilderElement', ['$rootScope', '$timeout', '$modal', '$http', '$templateCache', '$translate', 'RecursionHelper', 'FormBuilderService',
|
||
|
function ($rootScope, $timeout, $modal, $http, $templateCache, $translate, RecursionHelper, FormBuilderService) {
|
||
|
return {
|
||
|
restrict: 'AE',
|
||
|
templateUrl: 'views/templates/form-builder-element-template.html',
|
||
|
transclude: false,
|
||
|
scope: {
|
||
|
formElement: '=formElement',
|
||
|
editState: '=editState',
|
||
|
formMode: '=formMode',
|
||
|
drop: "&",
|
||
|
moved: "&"
|
||
|
},
|
||
|
compile: function(element) {
|
||
|
return RecursionHelper.compile(element, this.link);
|
||
|
},
|
||
|
link: function ($scope, $element, attributes) {
|
||
|
|
||
|
$scope.formTabs = [
|
||
|
{
|
||
|
"id": "general",
|
||
|
"name": $translate.instant('FORM-BUILDER.TABS.GENERAL')
|
||
|
},
|
||
|
{
|
||
|
"id": "options",
|
||
|
"name": $translate.instant('FORM-BUILDER.TABS.OPTIONS'),
|
||
|
"show": ['dropdown', 'radio-buttons']
|
||
|
},
|
||
|
{
|
||
|
"id": "upload",
|
||
|
"name": $translate.instant('FORM-BUILDER.TABS.UPLOAD-OPTIONS'),
|
||
|
"show": ['upload']
|
||
|
},
|
||
|
{
|
||
|
"id": "advanced",
|
||
|
"name": $translate.instant('FORM-BUILDER.TABS.ADVANCED-OPTIONS'),
|
||
|
"show": ['text', 'password', 'multi-line-text', 'integer', 'decimal','hyperlink']
|
||
|
}
|
||
|
];
|
||
|
|
||
|
$scope.activeTab = $scope.formTabs[0];
|
||
|
|
||
|
$scope.tabClicked = function (tab) {
|
||
|
$scope.activeTab = tab;
|
||
|
};
|
||
|
|
||
|
var templateUrl = 'views/popover/formfield-edit-popover.html';
|
||
|
|
||
|
|
||
|
$scope.removeFormElement = function (formElement) {
|
||
|
if ($rootScope.formItems.indexOf(formElement) >= 0) {
|
||
|
$rootScope.formItems.splice($rootScope.formItems.indexOf(formElement), 1);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$scope.pristine = true;
|
||
|
$scope.newOption = {
|
||
|
name: ''
|
||
|
};
|
||
|
|
||
|
$scope.insertFormField = {
|
||
|
position: 0
|
||
|
};
|
||
|
|
||
|
$scope.openFieldPopover = function () {
|
||
|
|
||
|
// Storing original values. In case the changes would trigger a layout change
|
||
|
var originalFormElementType = $scope.formElement.type;
|
||
|
var originalDisplayFieldType = undefined;
|
||
|
if (originalFormElementType === 'readonly') {
|
||
|
if ($scope.formElement.params
|
||
|
&& $scope.formElement.params.field
|
||
|
&& $scope.formElement.params.field.type) {
|
||
|
originalDisplayFieldType = $scope.formElement.params.field.type;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create popover
|
||
|
$scope.fieldEditPopup = _internalCreateModal({
|
||
|
template: 'views/popover/formfield-edit-popover.html?version=' + Date.now(),
|
||
|
scope: $scope,
|
||
|
backdrop: 'static',
|
||
|
keyboard: false
|
||
|
}, $modal, $scope);
|
||
|
|
||
|
// Check for layout changes
|
||
|
var deregisterHideListener = $scope.$on('modal.hide', function() {
|
||
|
if ($scope.formElement.type === 'readonly') {
|
||
|
|
||
|
if ($scope.formElement.params && $scope.formElement.params.field && $scope.formElement.params.field.type
|
||
|
&& $scope.formElement.params.field.type !== originalFormElementType) {
|
||
|
|
||
|
$scope.$emit('readonly-field-referenced-field-changed', {
|
||
|
formElement: $scope.formElement,
|
||
|
originalDisplayFieldType: originalDisplayFieldType
|
||
|
});
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
deregisterHideListener();
|
||
|
});
|
||
|
|
||
|
};
|
||
|
|
||
|
$scope.formElementNameChanged = function (field) {
|
||
|
if (!field.overrideId) {
|
||
|
var fieldId;
|
||
|
if (field.name && field.name.length > 0) {
|
||
|
fieldId = field.name.toLowerCase();
|
||
|
fieldId = fieldId.replace(new RegExp(' ', 'g'), '');
|
||
|
fieldId = fieldId.replace(/[&\/\\#,+~%.'":*?!<>{}()$@;]/g, '');
|
||
|
} else {
|
||
|
var index = 1;
|
||
|
if (field.layout) {
|
||
|
index = 1 + (2 * field.layout.row) + field.layout.column;
|
||
|
}
|
||
|
fieldId = 'field' + index;
|
||
|
}
|
||
|
field.id = fieldId;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$scope.confirmNewOption = function ($event) {
|
||
|
if ($scope.newOption.name) {
|
||
|
var options = $scope.formElement.options;
|
||
|
options.push($scope.newOption);
|
||
|
|
||
|
$scope.newOption = {name: ''};
|
||
|
|
||
|
// if first additional option; first option is defaulted
|
||
|
if (options.length == 2) {
|
||
|
$scope.formElement.value = $scope.formElement.options[0].name;
|
||
|
}
|
||
|
|
||
|
if ($event) {
|
||
|
// Focus the input field again, to make adding more options possible immediatly
|
||
|
$($event.target).focus();
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$scope.optionKeyDown = function ($event) {
|
||
|
if ($event.keyCode == 13) {
|
||
|
$scope.confirmNewOption($event);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$scope.removeOption = function (index) {
|
||
|
$scope.formElement.options.splice(index, 1);
|
||
|
|
||
|
|
||
|
// if only 1 option left; reset default
|
||
|
if ($scope.formElement.options == 1) {
|
||
|
$scope.formElement.value = '';
|
||
|
} else {
|
||
|
|
||
|
// if removed element is the default option; first option is defaulted
|
||
|
var isPresent = false;
|
||
|
for (var i = 0; i < $scope.formElement.options.length; i++) {
|
||
|
if ($scope.formElement.options[i].name == $scope.formElement.value) {
|
||
|
isPresent = true;
|
||
|
}
|
||
|
}
|
||
|
if (!isPresent) {
|
||
|
$scope.formElement.value = $scope.formElement.options[0].name;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$scope.optionsExpressionChanged = function ($event) {
|
||
|
if(event.target.checked) {
|
||
|
$scope.formElement.options = [];
|
||
|
$scope.formElement.value = '';
|
||
|
$scope.formElement.optionsExpression = '${}';
|
||
|
} else {
|
||
|
$scope.formElement.optionsExpression = null;
|
||
|
if ($scope.formElement.type === 'radio-buttons') {
|
||
|
$scope.formElement.options = [{
|
||
|
name: $translate.instant('FORM-BUILDER.COMPONENT.RADIO-BUTTON-DEFAULT')
|
||
|
}];
|
||
|
} else if($scope.formElement.type === 'dropdown') {
|
||
|
$scope.formElement.options = [
|
||
|
{name: $translate.instant('FORM-BUILDER.COMPONENT.DROPDOWN-DEFAULT-EMPTY-SELECTION')}
|
||
|
];
|
||
|
$scope.formElement.value = field.options[0];
|
||
|
$scope.formElement.hasEmptyValue = true;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$scope.doneEditing = function () {
|
||
|
|
||
|
if ($scope.fieldEditPopup) {
|
||
|
$scope.fieldEditPopup.$scope.$hide();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Readonly field
|
||
|
$scope.$watch('formElement.params.field', function (newValue, oldValue) {
|
||
|
if (!$scope.pristine || (oldValue !== undefined && oldValue.id != newValue.id)) {
|
||
|
if (newValue && newValue.name) {
|
||
|
// Update the element's name
|
||
|
$scope.formElement.name = newValue.name;
|
||
|
}
|
||
|
} else {
|
||
|
$scope.pristine = false;
|
||
|
}
|
||
|
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
}]);
|
||
|
|
||
|
|
||
|
angular.module('flowableModeler').directive('storeCursorPosition', ['$rootScope', '$timeout', '$popover', '$http', '$templateCache', function ($rootScope, $timeout, $popover, $http, $templateCache) {
|
||
|
return {
|
||
|
restrict: 'A',
|
||
|
scope: {
|
||
|
storeCursorPosition: '=storeCursorPosition'
|
||
|
},
|
||
|
link: function ($scope, $element, attributes) {
|
||
|
$element.on('click change keypress', function () {
|
||
|
if ($scope.storeCursorPosition !== undefined) {
|
||
|
$scope.storeCursorPosition = $element[0].selectionStart;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
}]);
|
||
|
|
||
|
angular.module('flowableModeler').
|
||
|
directive('editorInputCheck', function () {
|
||
|
|
||
|
return {
|
||
|
require: 'ngModel',
|
||
|
link: function (scope, element, attrs, modelCtrl) {
|
||
|
|
||
|
modelCtrl.$parsers.push(function (inputValue) {
|
||
|
|
||
|
var transformedInput = inputValue.replace(/[&\/\\#,+~%.'":*?<>{}()$@;]/g, '');
|
||
|
|
||
|
if (transformedInput != inputValue) {
|
||
|
modelCtrl.$setViewValue(transformedInput);
|
||
|
modelCtrl.$render();
|
||
|
}
|
||
|
|
||
|
return transformedInput;
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
});
|
||
|
|
||
|
angular.module('flowableModeler').
|
||
|
directive('hotAutoDestroy',["hotRegisterer",function(hotRegisterer) {
|
||
|
return {
|
||
|
restrict: 'A',
|
||
|
link: function (scope, element, attr){
|
||
|
element.on("$destroy", function() {
|
||
|
try{
|
||
|
var hotInstance = hotRegisterer.getInstance(attr.hotId);
|
||
|
hotInstance.destroy();
|
||
|
}
|
||
|
catch(er){
|
||
|
console.log(er);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
}]);
|