add & remove childs
gitea/salix/1625-worker_department_treeview This commit looks good
Details
gitea/salix/1625-worker_department_treeview This commit looks good
Details
This commit is contained in:
parent
6a184496d6
commit
9919f9a46e
|
@ -25,11 +25,11 @@
|
|||
label="{{::item.name}}">
|
||||
</vn-check>
|
||||
-->
|
||||
<vn-icon-button
|
||||
<vn-icon-button title="Create"
|
||||
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 title="Remove"
|
||||
icon="delete"
|
||||
ng-click="$ctrl.treeview.onRemove(item, $ctrl.items, $ctrl.parent)">
|
||||
</vn-icon-button>
|
||||
|
|
|
@ -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
|
||||
icon="add_circle">
|
||||
</vn-icon-button>
|
||||
|
|
|
@ -27,51 +27,44 @@ 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) {
|
||||
if (item.active)
|
||||
item.childs = undefined;
|
||||
else {
|
||||
this.model.applyFilter({}, {parentFk: item.id}).then(() => {
|
||||
const newData = this.model.data;
|
||||
this.fold(item);
|
||||
else
|
||||
this.unfold(item);
|
||||
}
|
||||
|
||||
if (item.childs) {
|
||||
let childs = item.childs;
|
||||
childs.forEach(child => {
|
||||
let index = newData.findIndex(newChild => {
|
||||
return newChild.id == child.id;
|
||||
});
|
||||
newData[index] = child;
|
||||
fold(item) {
|
||||
item.childs = undefined;
|
||||
item.active = false;
|
||||
}
|
||||
|
||||
unfold(item) {
|
||||
return this.model.applyFilter({}, {parentFk: item.id}).then(() => {
|
||||
const newData = this.model.data;
|
||||
|
||||
if (item.childs) {
|
||||
let childs = item.childs;
|
||||
childs.forEach(child => {
|
||||
let index = newData.findIndex(newChild => {
|
||||
return newChild.id == child.id;
|
||||
});
|
||||
newData[index] = child;
|
||||
});
|
||||
}
|
||||
|
||||
item.childs = newData.sort((a, b) => {
|
||||
if (b.selected !== a.selected) {
|
||||
if (a.selected == null)
|
||||
return 1;
|
||||
if (b.selected == null)
|
||||
return -1;
|
||||
return b.selected - a.selected;
|
||||
}
|
||||
|
||||
item.childs = newData.sort((a, b) => {
|
||||
if (b.selected !== a.selected) {
|
||||
if (a.selected == null)
|
||||
return 1;
|
||||
if (b.selected == null)
|
||||
return -1;
|
||||
return b.selected - a.selected;
|
||||
}
|
||||
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
}
|
||||
|
||||
item.active = !item.active;
|
||||
}).then(() => item.active = true);
|
||||
}
|
||||
|
||||
onDrop(item, dragged, dropped) {
|
||||
|
@ -80,7 +73,7 @@ export default class Treeview extends Component {
|
|||
|
||||
onRemove(item, items, parent) {
|
||||
if (!this.removeFunc) return;
|
||||
let res = this.removeFunc({$item: item});
|
||||
let res = this.removeFunc({$item: item, $parent: parent});
|
||||
|
||||
function remove() {
|
||||
let index = items.indexOf(item);
|
||||
|
@ -94,25 +87,50 @@ export default class Treeview extends Component {
|
|||
remove();
|
||||
}
|
||||
|
||||
onAdd(parent, childs) {
|
||||
if (!this.addFunc) return;
|
||||
let res = this.addFunc({$parent: parent});
|
||||
onCreate(parent, childs) {
|
||||
if (!this.createFunc) return;
|
||||
let res = this.createFunc({$parent: parent, $childs: childs});
|
||||
|
||||
function add() {
|
||||
function create() {
|
||||
if (!childs) childs = [];
|
||||
childs.push(res);
|
||||
if (parent) {
|
||||
parent.childs = childs;
|
||||
parent.sons++;
|
||||
parent.active = true;
|
||||
}
|
||||
if (parent) parent.sons++;
|
||||
}
|
||||
|
||||
if (res instanceof Object && res.then)
|
||||
res.then(add);
|
||||
else if (res)
|
||||
add();
|
||||
if (res instanceof Object && res.then) {
|
||||
if (parent && !parent.active)
|
||||
this.unfold(parent).then(() => res.then(create));
|
||||
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'];
|
||||
|
@ -130,7 +148,7 @@ ngModule.component('vnTreeview', {
|
|||
droppable: '<?',
|
||||
aclRole: '@?',
|
||||
removeFunc: '&?',
|
||||
addFunc: '&?'
|
||||
createFunc: '&?'
|
||||
},
|
||||
transclude: true
|
||||
});
|
||||
|
|
|
@ -107,5 +107,6 @@
|
|||
"Invalid quantity": "Cantidad invalida",
|
||||
"This postal code is not valid": "This postal code is not valid",
|
||||
"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"
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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);
|
||||
};
|
||||
};
|
|
@ -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();
|
||||
};
|
||||
};
|
|
@ -1,15 +1,5 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
require('../methods/department/getLeaves')(Self);
|
||||
require('../methods/department/nodeAdd')(Self);
|
||||
require('../methods/department/nodeDelete')(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;
|
||||
});
|
||||
require('../methods/department/createChild')(Self);
|
||||
require('../methods/department/removeChild')(Self);
|
||||
};
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
},
|
||||
"name": {
|
||||
"type": "String"
|
||||
},
|
||||
"parentFk": {
|
||||
"type": "Number"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,9 @@
|
|||
<div class="content-block" compact>
|
||||
<form name="form" compact>
|
||||
<vn-card margin-medium-v pad-medium>
|
||||
<vn-treeview
|
||||
vn-id="treeview"
|
||||
model="model"
|
||||
on-selection="$ctrl.onSelection(item, value)"
|
||||
remove-func="true"
|
||||
add-func="{name: 'Dept1'}">
|
||||
<vn-treeview vn-id="treeview" model="model"
|
||||
remove-func="$ctrl.onRemove($item)"
|
||||
create-func="$ctrl.onCreate($parent, $childs)">
|
||||
{{::item.name}}
|
||||
</vn-treeview>
|
||||
</vn-card>
|
||||
|
@ -37,7 +34,7 @@
|
|||
<vn-horizontal>
|
||||
<vn-textfield vn-one
|
||||
label="Name"
|
||||
model="$ctrl.newNode.name">
|
||||
model="$ctrl.newChild.name">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
|
|
|
@ -6,23 +6,6 @@ class Controller {
|
|||
this.$http = $http;
|
||||
this.vnApp = vnApp;
|
||||
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) {
|
||||
|
@ -39,25 +22,37 @@ class Controller {
|
|||
}
|
||||
}
|
||||
|
||||
onCreate(parent, childs) {
|
||||
this.newChild = {
|
||||
parent: parent,
|
||||
childs: childs,
|
||||
name: ''
|
||||
};
|
||||
|
||||
this.$scope.createNode.show();
|
||||
}
|
||||
|
||||
onCreateDialogOpen() {
|
||||
this.newNode.name = '';
|
||||
this.newChild.name = '';
|
||||
}
|
||||
|
||||
onCreateResponse(response) {
|
||||
if (response == 'ACCEPT') {
|
||||
try {
|
||||
if (!this.newNode.name)
|
||||
if (!this.newChild.name)
|
||||
throw new Error(`Name can't be empty`);
|
||||
|
||||
this.$http.post(`/worker/api/Departments/nodeAdd`, this.newNode).then(response => {
|
||||
if (response.data) {
|
||||
let parent = this.selectedNode.parent;
|
||||
if ((parent instanceof Object) && !(parent instanceof Array)) {
|
||||
const childs = parent.childs;
|
||||
childs.push(response.data);
|
||||
} else if ((parent instanceof Object) && (parent instanceof Array))
|
||||
parent.push(response.data);
|
||||
}
|
||||
const params = {name: this.newChild.name};
|
||||
const parent = this.newChild.parent;
|
||||
const parentId = parent && parent.id || null;
|
||||
let childs = this.newChild.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);
|
||||
});
|
||||
} catch (e) {
|
||||
this.vnApp.showError(this.$translate.instant(e.message));
|
||||
|
@ -67,17 +62,24 @@ class Controller {
|
|||
return true;
|
||||
}
|
||||
|
||||
onRemove(item) {
|
||||
this.removedChild = item;
|
||||
this.$scope.deleteNode.show();
|
||||
}
|
||||
|
||||
onRemoveResponse(response) {
|
||||
if (response === 'ACCEPT') {
|
||||
const path = `/worker/api/Departments/nodeDelete`;
|
||||
this.$http.post(path, {parentFk: this.selectedNode.id}).then(() => {
|
||||
let parent = this.selectedNode.parent;
|
||||
const childId = this.removedChild.id;
|
||||
const path = `/api/departments/${childId}/removeChild`;
|
||||
this.$http.post(path).then(() => {
|
||||
items.splice(index, 1);
|
||||
/* let parent = this.selectedNode.parent;
|
||||
|
||||
if ((parent instanceof Object) && !(parent instanceof Array)) {
|
||||
const childs = parent.childs;
|
||||
childs.splice(this.selectedNode.index, 1);
|
||||
} else if ((parent instanceof Object) && (parent instanceof Array))
|
||||
parent.splice(this.selectedNode.index, 1);
|
||||
parent.splice(this.selectedNode.index, 1); */
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue