add & remove childs
gitea/salix/1625-worker_department_treeview This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-10-04 07:41:24 +02:00
parent 6a184496d6
commit 9919f9a46e
12 changed files with 187 additions and 181 deletions

View File

@ -25,11 +25,11 @@
label="{{::item.name}}"> label="{{::item.name}}">
</vn-check> </vn-check>
--> -->
<vn-icon-button <vn-icon-button title="Create"
icon="add_circle" icon="add_circle"
ng-click="$ctrl.treeview.onAdd(item, item.childs)"> ng-click="$ctrl.treeview.onCreate(item, item.childs)">
</vn-icon-button> </vn-icon-button>
<vn-icon-button <vn-icon-button title="Remove"
icon="delete" icon="delete"
ng-click="$ctrl.treeview.onRemove(item, $ctrl.items, $ctrl.parent)"> ng-click="$ctrl.treeview.onRemove(item, $ctrl.items, $ctrl.parent)">
</vn-icon-button> </vn-icon-button>

View File

@ -1,4 +1,4 @@
<section class="add-item" ng-click="$ctrl.onAdd(null, $ctrl.items)" > <section class="add-item" ng-click="$ctrl.onCreate(null, $ctrl.items)" >
<vn-icon-button <vn-icon-button
icon="add_circle"> icon="add_circle">
</vn-icon-button> </vn-icon-button>

View File

@ -27,24 +27,20 @@ export default class Treeview extends Component {
}); });
} }
/**
* Emits selection event
* @param {Object} item - Selected item
* @param {Boolean} value - Changed value
*/
onSelection(item, value) {
this.emit('selection', {item, value});
}
onCreate(parent) {
this.emit('create', {parent});
}
onToggle(item) { onToggle(item) {
if (item.active) if (item.active)
this.fold(item);
else
this.unfold(item);
}
fold(item) {
item.childs = undefined; item.childs = undefined;
else { item.active = false;
this.model.applyFilter({}, {parentFk: item.id}).then(() => { }
unfold(item) {
return this.model.applyFilter({}, {parentFk: item.id}).then(() => {
const newData = this.model.data; const newData = this.model.data;
if (item.childs) { if (item.childs) {
@ -68,10 +64,7 @@ export default class Treeview extends Component {
return a.name.localeCompare(b.name); return a.name.localeCompare(b.name);
}); });
}); }).then(() => item.active = true);
}
item.active = !item.active;
} }
onDrop(item, dragged, dropped) { onDrop(item, dragged, dropped) {
@ -80,7 +73,7 @@ export default class Treeview extends Component {
onRemove(item, items, parent) { onRemove(item, items, parent) {
if (!this.removeFunc) return; if (!this.removeFunc) return;
let res = this.removeFunc({$item: item}); let res = this.removeFunc({$item: item, $parent: parent});
function remove() { function remove() {
let index = items.indexOf(item); let index = items.indexOf(item);
@ -94,25 +87,50 @@ export default class Treeview extends Component {
remove(); remove();
} }
onAdd(parent, childs) { onCreate(parent, childs) {
if (!this.addFunc) return; if (!this.createFunc) return;
let res = this.addFunc({$parent: parent}); let res = this.createFunc({$parent: parent, $childs: childs});
function add() { function create() {
if (!childs) childs = []; if (!childs) childs = [];
childs.push(res); childs.push(res);
if (parent) { if (parent) parent.sons++;
parent.childs = childs;
parent.sons++;
parent.active = true;
}
} }
if (res instanceof Object && res.then) if (res instanceof Object && res.then) {
res.then(add); if (parent && !parent.active)
else if (res) this.unfold(parent).then(() => res.then(create));
add(); else res.then(create);
} else if (res) {
if (parent && !parent.active)
this.unfold(parent).then(() => create());
else create();
} else if (parent && !parent.active)
this.unfold(parent);
} }
/* onCreate(parent, childs) {
if (!this.createFunc) return;
let res = this.createFunc({$parent: parent});
function create() {
if (!childs) childs = [];
childs.push(res);
if (parent) parent.sons++;
}
if (res instanceof Object && res.then) {
if (!parent.active)
this.unfold(parent).then(() => res.then(create));
else res.then(create);
} else if (res) {
if (!parent.active)
this.unfold(parent).then(() => create());
else create();
}
} */
} }
Treeview.$inject = ['$element', '$scope', '$transclude']; Treeview.$inject = ['$element', '$scope', '$transclude'];
@ -130,7 +148,7 @@ ngModule.component('vnTreeview', {
droppable: '<?', droppable: '<?',
aclRole: '@?', aclRole: '@?',
removeFunc: '&?', removeFunc: '&?',
addFunc: '&?' createFunc: '&?'
}, },
transclude: true transclude: true
}); });

View File

@ -107,5 +107,6 @@
"Invalid quantity": "Cantidad invalida", "Invalid quantity": "Cantidad invalida",
"This postal code is not valid": "This postal code is not valid", "This postal code is not valid": "This postal code is not valid",
"is invalid": "is invalid", "is invalid": "is invalid",
"The postcode doesn't exists. Ensure you put the correct format": "El código postal no existe. Asegúrate de ponerlo con el formato correcto" "The postcode doesn't exists. Ensure you put the correct format": "El código postal no existe. Asegúrate de ponerlo con el formato correcto",
"The department name can't be repeated": "The department name can't be repeated"
} }

View File

@ -0,0 +1,40 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('createChild', {
description: 'Creates a new child department',
accessType: 'WRITE',
accepts: [{
arg: 'parentId',
type: 'Number'
},
{
arg: 'name',
type: 'String',
required: true,
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/createChild`,
verb: 'POST'
}
});
Self.createChild = async(parentId = null, name) => {
const models = Self.app.models;
const nameExists = await models.Department.count({name});
if (nameExists)
throw new UserError(`The department name can't be repeated`);
const newDep = await models.Department.create({
parentFk: parentId,
name: name
});
return newDep;
};
};

View File

@ -1,43 +0,0 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => {
Self.remoteMethod('nodeAdd', {
description: 'Returns the first shipped and landed possible for params',
accessType: 'WRITE',
accepts: [{
arg: 'parentFk',
type: 'Number',
required: false,
},
{
arg: 'name',
type: 'String',
required: true,
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/nodeAdd`,
verb: 'POST'
}
});
Self.nodeAdd = async(parentFk = 1, name) => {
let stmts = [];
let conn = Self.dataSource.connector;
let nodeIndex = stmts.push(new ParameterizedSQL(
`CALL nst.nodeAdd('vn', 'department', ?, ?)`, [parentFk, name])) - 1;
stmts.push(`CALL nst.nodeRecalc('vn', 'department')`);
let sql = ParameterizedSQL.join(stmts, ';');
let result = await conn.executeStmt(sql);
let [node] = result[nodeIndex];
return node;
};
};

View File

@ -1,29 +0,0 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => {
Self.remoteMethod('nodeDelete', {
description: 'Returns the first shipped and landed possible for params',
accessType: 'WRITE',
accepts: [{
arg: 'parentFk',
type: 'Number',
required: false,
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/nodeDelete`,
verb: 'POST'
}
});
Self.nodeDelete = async parentFk => {
let stmt = new ParameterizedSQL(
`CALL nst.nodeDelete('vn', 'department', ?)`, [parentFk]);
return await Self.rawStmt(stmt);
};
};

View File

@ -0,0 +1,27 @@
module.exports = Self => {
Self.remoteMethod('removeChild', {
description: 'Returns the first shipped and landed possible for params',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'Number',
description: 'The department id',
http: {source: 'path'}
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/:id/removeChild`,
verb: 'POST'
}
});
Self.removeChild = async id => {
const models = Self.app.models;
const department = await models.Department.findById(id);
return await department.destroy();
};
};

View File

@ -1,15 +1,5 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
require('../methods/department/getLeaves')(Self); require('../methods/department/getLeaves')(Self);
require('../methods/department/nodeAdd')(Self); require('../methods/department/createChild')(Self);
require('../methods/department/nodeDelete')(Self); require('../methods/department/removeChild')(Self);
Self.rewriteDbError(function(err) {
if (err.code === 'ER_ROW_IS_REFERENCED_2')
return new UserError(`You cannot remove this department`);
if (err.code === 'ER_DUP_ENTRY')
return new UserError(`The department name can't be repeated`);
return err;
});
}; };

View File

@ -13,6 +13,9 @@
}, },
"name": { "name": {
"type": "String" "type": "String"
},
"parentFk": {
"type": "Number"
} }
} }
} }

View File

@ -6,12 +6,9 @@
<div class="content-block" compact> <div class="content-block" compact>
<form name="form" compact> <form name="form" compact>
<vn-card margin-medium-v pad-medium> <vn-card margin-medium-v pad-medium>
<vn-treeview <vn-treeview vn-id="treeview" model="model"
vn-id="treeview" remove-func="$ctrl.onRemove($item)"
model="model" create-func="$ctrl.onCreate($parent, $childs)">
on-selection="$ctrl.onSelection(item, value)"
remove-func="true"
add-func="{name: 'Dept1'}">
{{::item.name}} {{::item.name}}
</vn-treeview> </vn-treeview>
</vn-card> </vn-card>
@ -37,7 +34,7 @@
<vn-horizontal> <vn-horizontal>
<vn-textfield vn-one <vn-textfield vn-one
label="Name" label="Name"
model="$ctrl.newNode.name"> model="$ctrl.newChild.name">
</vn-textfield> </vn-textfield>
</vn-horizontal> </vn-horizontal>
</tpl-body> </tpl-body>

View File

@ -6,23 +6,6 @@ class Controller {
this.$http = $http; this.$http = $http;
this.vnApp = vnApp; this.vnApp = vnApp;
this.$translate = $translate; this.$translate = $translate;
this.icons = [{icon: 'delete', tooltip: 'Delete', callback: this.onDelete}];
this.newNode = {
name: ''
};
}
onCreate(parent) {
if (parent instanceof Object)
this.newNode.parentFk = parent.id;
this.selectedNode = {parent};
this.$scope.createNode.show();
}
onDelete(item, parent, index) {
this.selectedNode = {id: item.id, parent, index};
this.$scope.deleteNode.show();
} }
onDrop(item, dragged, dropped) { onDrop(item, dragged, dropped) {
@ -39,25 +22,37 @@ class Controller {
} }
} }
onCreate(parent, childs) {
this.newChild = {
parent: parent,
childs: childs,
name: ''
};
this.$scope.createNode.show();
}
onCreateDialogOpen() { onCreateDialogOpen() {
this.newNode.name = ''; this.newChild.name = '';
} }
onCreateResponse(response) { onCreateResponse(response) {
if (response == 'ACCEPT') { if (response == 'ACCEPT') {
try { try {
if (!this.newNode.name) if (!this.newChild.name)
throw new Error(`Name can't be empty`); throw new Error(`Name can't be empty`);
this.$http.post(`/worker/api/Departments/nodeAdd`, this.newNode).then(response => { const params = {name: this.newChild.name};
if (response.data) { const parent = this.newChild.parent;
let parent = this.selectedNode.parent; const parentId = parent && parent.id || null;
if ((parent instanceof Object) && !(parent instanceof Array)) { let childs = this.newChild.childs;
const childs = parent.childs;
if (parent) params.parentId = parentId;
const query = `/api/departments/createChild`;
this.$http.post(query, params).then(response => {
if (!childs) childs = [];
childs.push(response.data); childs.push(response.data);
} else if ((parent instanceof Object) && (parent instanceof Array))
parent.push(response.data);
}
}); });
} catch (e) { } catch (e) {
this.vnApp.showError(this.$translate.instant(e.message)); this.vnApp.showError(this.$translate.instant(e.message));
@ -67,17 +62,24 @@ class Controller {
return true; return true;
} }
onRemove(item) {
this.removedChild = item;
this.$scope.deleteNode.show();
}
onRemoveResponse(response) { onRemoveResponse(response) {
if (response === 'ACCEPT') { if (response === 'ACCEPT') {
const path = `/worker/api/Departments/nodeDelete`; const childId = this.removedChild.id;
this.$http.post(path, {parentFk: this.selectedNode.id}).then(() => { const path = `/api/departments/${childId}/removeChild`;
let parent = this.selectedNode.parent; this.$http.post(path).then(() => {
items.splice(index, 1);
/* let parent = this.selectedNode.parent;
if ((parent instanceof Object) && !(parent instanceof Array)) { if ((parent instanceof Object) && !(parent instanceof Array)) {
const childs = parent.childs; const childs = parent.childs;
childs.splice(this.selectedNode.index, 1); childs.splice(this.selectedNode.index, 1);
} else if ((parent instanceof Object) && (parent instanceof Array)) } else if ((parent instanceof Object) && (parent instanceof Array))
parent.splice(this.selectedNode.index, 1); parent.splice(this.selectedNode.index, 1); */
}); });
} }
} }