Move an entire workbook to schema

This is a preparation for integrating with Barricade.js

Change-Id: Iba9424ddc8337497d5bb8431c114b1b07902f6b8
This commit is contained in:
Timur Sufiev 2015-01-15 20:53:04 +03:00
parent b408d89815
commit b922fad15b
14 changed files with 650 additions and 372 deletions

View File

@ -9,3 +9,6 @@ ADD_INSTALLED_APPS = ['merlin', 'mistral']
# Python panel class of the PANEL to be added.
ADD_PANEL = 'mistral.panel.MistralPanel'
ADD_ANGULAR_MODULES = ['angular.filter']
ADD_JS_FILES = ['merlin/lib/angular-filter.js']

View File

@ -1,11 +1,17 @@
<div class="panel panel-default merlin-panel">
<div ng-if="title">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-target="#elem-{$ $id $}" href="#">{$ title $}</a>
<a href="#" ng-click="removable()"><i ng-show="removable" class="fa fa-times-circle pull-right"></i></a></h4>
<a href="#" ng-click="onRemove()"><i ng-show="removable" class="fa fa-times-circle pull-right"></i></a></h4>
</div>
<div id="elem-{$ $id $}" class="panel-collapse collapse in">
<div class="panel-body" ng-transclude>
</div>
</div>
</div>
<div ng-if="!title">
<div class="panel-body" ng-transclude>
</div>
</div>
</div>

View File

@ -1,3 +1,4 @@
<collapsible-group title="{$ spec.title || makeTitle(spec.name) $}" on-add="add(item[spec.name], '')">
<div class="three-columns" ng-repeat="(key, value) in item[spec.name] track by key">
<div class="left-column">
<div class="form-group">
@ -11,3 +12,4 @@
</div>
</div>
</div>
</collapsible-group>

View File

@ -1,4 +1,4 @@
<collapsible-group title="{$ spec.title || makeTitle(spec.name) $}" additive="false">
<collapsible-group title="{$ spec.title || makeTitle(spec.name) $}">
<div class="three-columns">
<div class="left-column">
<div class="form-group" ng-repeat="(key, item) in item[spec.name] track by key">

View File

@ -0,0 +1,11 @@
<collapsible-group title="{$ spec.title || makeTitle(spec.name) $}" on-add="add(item[spec.name])">
<div ng-repeat="specs in spec.value | groupBy: 'row' | toArray: true | orderBy: '$key' track by specs.$key">
<div ng-class="{'three-columns': specs[0].row !== undefined }">
<div ng-repeat="spec in specs track by spec.name"
ng-class="{'right-column': $odd && isAtomic(spec.type), 'left-column': $even && isAtomic(spec.type)}">
<typed-field></typed-field>
<div class="clearfix" ng-show="$odd"></div>
</div>
</div>
</div>
</collapsible-group>

View File

@ -0,0 +1,4 @@
<div class="form-group">
<label for="elem-{$ $id $}">{$ spec.title || makeTitle(spec.name) $}</label>
<textarea class="form-control" id="elem-{$ $id $}" ng-model="item[spec.name]"></textarea>
</div>

View File

@ -1,4 +1,5 @@
<collapsible-group title="{$ spec.title || makeTitle(spec.name) $}" on-add="add(item[spec.name], {type: 'string', value: '', id: 'varlist'+item[spec.name].length})">
<collapsible-group title="{$ spec.title || makeTitle(spec.name) $}"
on-add="add(item[spec.name], {type: 'string', value: '', id: 'varlist'+item[spec.name].length})">
<div class="three-columns" ng-repeat="subItem in item[spec.name] track by subItem.id"
ng-class="{dictionary: subItem.type == 'dictionary', list: subItem.type == 'list'}">
<div class="left-column">

View File

@ -0,0 +1,18 @@
<collapsible-group title="{$ spec.title || makeTitle(spec.name) $}" on-add="add(item[spec.name], '')">
<div class="three-columns">
<div class="left-column" style="display:none">
<div class="form-group">
<textarea class="form-control">{$ yaqlExpresion $}</textarea>
</div>
</div>
<div class="right-column">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon yaql-condition fa fa-unlock" role="button"></span>
<input type="text" class="form-control" value="{$ value $}">
<span class="input-group-addon fa fa-minus-circle"></span>
</div>
</div>
</div>
</div>
</collapsible-group>

View File

@ -65,33 +65,219 @@
type: 'list',
value: ['', '']
}]
}],
workflows: [{
id: 'workflow1',
name: 'Workflow1',
base: '', // FIXME
input: [''],
output: [{
id: 'varlist1',
type: 'string',
value: ''
}],
taskDefaults: {
onError: {
type: 'list',
value: ['', '']
},
onSuccess: {
type: 'list',
value: ['']
},
onComplete: {
type: 'list',
value: ['', '']
}
]
}
}]
};
$scope.schema = {
action: [{
name: 'name',
name: {
type: 'string',
group: 'one'
}, {
name: 'base',
index: 0,
panelIndex: 0,
row: 0
},
description: {
type: 'text',
index: 1,
panelIndex: 0,
row: 0
},
actions: {
index: 2,
type: 'panel',
multiple: true,
value: {
name: {
type: 'string',
group: 'one'
}, {
name: 'baseInput',
row: 0,
index: 0
},
base: {
type: 'string',
row: 0,
index: 1
},
baseInput: {
type: 'frozendict',
group: ''
}, {
name: 'input',
title: 'Base Input',
index: 2
},
input: {
type: 'list',
group: ''
}, {
name: 'output',
index: 3
},
output: {
type: 'varlist',
group: ''
index: 4
}
}
},
workflows: {
index: 3,
type: 'panel',
multiple: true,
value: {
name: {
type: 'string',
index: 0,
row: 0
},
base: {
type: 'string',
index: 1,
row: 0
},
input: {
type: 'list',
index: 2
},
output: {
type: 'varlist',
index: 3
},
taskDefaults: {
type: 'group',
title: 'Task defaults',
additive: false,
index: 4,
value: {
onError: {
type: 'yaqllist',
title: 'On error',
index: 0
},
onSuccess: {
type: 'yaqllist',
title: 'On success',
index: 1
},
onComplete: {
type: 'yaqllist',
title: 'On complete',
index: 2
}
}
},
tasks: {
type: 'group',
index: 5,
value: {
task: {
type: 'group',
additive: false,
multiple: true,
index: 0,
value: {
name: {
type: 'string',
index: 0,
row: 0
},
type: {
type: 'string',
index: 1,
row: 0
},
action: {
type: 'string',
index: 2,
row: 1
},
input: {
type: 'dictionary',
index: 3
},
publish: {
type: 'dictionary',
index: 4
},
onError: {
type: 'yaqllist',
title: 'On error',
index: 5
},
onSuccess: {
type: 'yaqllist',
title: 'On success',
index: 6
},
onComplete: {
type: 'yaqllist',
title: 'On complete',
index: 7
},
policies: {
type: 'group',
additive: false,
index: 8,
value: {
waitBefore: {
type: 'string',
title: 'Wait before',
index: 0,
row: 0
},
waitAfter: {
type: 'string',
title: 'Wait after',
index: 1,
row: 0
},
timeout: {
type: 'string',
index: 2,
row: 1
},
retryCount: {
type: 'string',
title: 'Retry count',
index: 3,
row: 2
},
retryDelay: {
type: 'string',
title: 'Retry delay',
index: 4,
row: 2
},
retryBreakOn: {
type: 'string',
title: 'Retry break on',
index: 5,
row: 3
}
}
}
}
}
}
}
}
}
]
};
$scope.makeTitle = function(str) {
@ -107,7 +293,7 @@
};
$scope.isAtomic = function(type) {
return ['string'].indexOf(type) > -1;
return ['string', 'text'].indexOf(type) > -1;
};
$scope.remove = function(parent, item) {

View File

@ -60,22 +60,25 @@
}
})
.directive('collapsiblePanel', function($parse, defaultSetter) {
.directive('panel', function() {
return {
restrict: 'E',
templateUrl: '/static/mistral/js/angular-templates/collapsible-panel.html',
transclude: true,
scope: {
title: '@',
removable: '&'
onRemove: '&'
},
link: function(scope, element, attrs) {
disableClickDefaultBehaviour(element);
if ( attrs.onRemove ) {
scope.removable = true;
}
}
}
})
.directive('collapsibleGroup', function($parse, defaultSetter) {
.directive('collapsibleGroup', function() {
return {
restrict: 'E',
templateUrl: '/static/mistral/js/angular-templates/collapsible-group.html',

View File

@ -48,6 +48,7 @@
types.Mistral.Action = Barricade.create({
'@type': Object,
'@meta': {'groups': ['panel2']},
'name': {'@type': String},
'base': {
@ -258,6 +259,7 @@
types.Mistral.Workflow = Barricade.create({
'@type': Object,
'@meta': {'groups': 'panel3'},
'name': {'@type': String},
'type': {
@ -299,13 +301,16 @@
'version': {
'@type': Number,
'@meta': {'groups': ['panel1']},
'@default': 2
},
'name': {
'@type': String
'@type': String,
'@meta': {'groups': ['panel1']}
},
'description': {
'@type': String,
'@meta': {'groups': ['panel1']},
'@required': false
},
'actions': {

View File

@ -16,7 +16,8 @@
})
.run(function($http, $templateCache) {
var fields = ['dictionary', 'frozendict', 'list', 'string', 'varlist'];
var fields = ['dictionary', 'frozendict', 'list', 'string',
'varlist', 'text', 'group', 'yaqllist'];
fields.forEach(function(field) {
var base = '/static/mistral/js/angular-templates/fields/';
$http.get(base + field + '.html').success(function(templateContent) {
@ -25,4 +26,42 @@
})
})
.filter('prepareSchema', function($filter) {
var toArray = $filter('toArray'),
orderBy = $filter('orderBy');
function schemaToArray(schema) {
return angular.isArray(schema) ? schema : orderBy(
toArray(schema, true), 'index').map(function(item) {
item.name = item.$key;
if ( item.type === 'panel' ) {
item.panelIndex = item.index;
}
if ( item.type === 'panel' || item.type === 'group' ) {
item.value = schemaToArray(item.value);
}
return item;
});
}
return schemaToArray;
})
.filter('normalizePanels', function() {
return function(collection) {
return collection.map(function(panelSpec) {
if ( panelSpec[0].type === 'panel' ) {
var data = panelSpec[0];
panelSpec.length = data.value.length;
for ( var i = 0; i < panelSpec.length; i++ ) {
panelSpec[i] = data.value[i];
}
panelSpec.multiple = data.multiple;
panelSpec.name = data.name;
}
return panelSpec;
});
}
})
})();

View File

@ -51,29 +51,10 @@
<!-- Data panel start -->
<div class="two-panels">
<div class="left-panel">
<!-- root-level parameters -->
<div class="panel panel-default merlin-panel" id="panel0">
<div class="panel-body">
<div class="two-columns">
<div class="left-column">
<div class="form-group">
<label for="workbookName">Name</label>
<input type="text" class="form-control" id="workbookName" placeholder="Workbook1">
</div>
</div>
<div class="right-column">
<div class="form-group">
<label for="workbookDesc">Description</label>
<textarea class="form-control" id="workbookDesc" placeholder="Type a description here"></textarea>
</div>
</div>
</div>
</div>
</div>
<!-- Action added -->
<collapsible-panel ng-controller="actionCtrl" ng-repeat="item in data.actions track by item.id" title="{$ item.name $}" removable="remove('actions', item)">
<div ng-repeat="specs in schema.action | groupBy: 'group' | toArray:true | orderBy: '-$key' track by specs.$key">
<div ng-class="{'three-columns': specs[0].group}">
<div ng-repeat="panelSpec in schema | prepareSchema | groupBy: 'panelIndex' | toArray:true | orderBy: '$key' | normalizePanels track by panelSpec.$key">
<panel ng-if="panelSpec.multiple" ng-repeat="item in data[panelSpec.name] track by item.id" title="{$ item.name $}" on-remove="remove('{$ panelSpec.name $}', item)">
<div ng-repeat="specs in panelSpec | groupBy: 'row' | toArray: true | orderBy: '$key' track by specs.$key">
<div ng-class="{'three-columns': specs[0].row !== undefined }">
<div ng-repeat="spec in specs track by spec.name"
ng-class="{'right-column': $even && isAtomic(spec.type), 'left-column': $odd && isAtomic(spec.type)}">
<typed-field></typed-field>
@ -81,10 +62,23 @@
</div>
</div>
</div>
</collapsible-panel>
</panel>
<panel ng-if="!panelSpec.multiple">
<!-- ugly duplication here -->
<div ng-repeat="specs in panelSpec | groupBy: 'row' | toArray: true | orderBy: '$key' track by specs.$key">
<div ng-class="{'two-columns': specs[0].row !== undefined }">
<div ng-repeat="spec in specs track by spec.name"
ng-class="{'right-column': $even && isAtomic(spec.type), 'left-column': $odd && isAtomic(spec.type)}">
<typed-field></typed-field>
<div class="clearfix" ng-show="$even"></div>
</div>
</div>
</div>
</panel>
</div>
<!-- panel with workflow -->
<div ng-controller="workflowsCtrl">
<collapsible-panel title="Workflow1" removable="true">
<panel title="Workflow1" removable="true">
<!-- 2 simple inputs in a single row -->
<div class="three-columns">
<div class="left-column">
@ -267,7 +261,7 @@
</collapsible-group>
</collapsible-group>
</collapsible-group>
</collapsible-panel>
</panel>
</div>
</div>
<!-- YAML Panel -->

File diff suppressed because one or more lines are too long