last refactor
gitea/salix/1625-worker_department_treeview This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-10-08 07:22:38 +02:00
parent 366d1123d4
commit b32cf4a386
14 changed files with 225 additions and 207 deletions

View File

@ -14,25 +14,15 @@
<vn-treeview-content
item="::item">
</vn-treeview-content>
<!--
<vn-check
vn-acl="{{$ctrl.aclRole}}"
ng-if="$ctrl.selectable"
field="item.selected"
disabled="$ctrl.treeview.disabled"
on-change="$ctrl.select(item, value)"
triple-state="true"
label="{{::item.name}}">
</vn-check>
-->
<section class="buttons">
<vn-icon-button title="Create"
icon="add_circle"
ng-click="$ctrl.treeview.onCreate(item, item.childs)">
</vn-icon-button>
<vn-icon-button title="Remove"
<section class="buttons" ng-if="::!$ctrl.treeview.readOnly">
<vn-icon-button translate-attr="::{title: 'Remove'}"
icon="delete"
ng-click="$ctrl.treeview.onRemove(item, $ctrl.items, $ctrl.parent)">
ng-click="$ctrl.treeview.onRemove(item)"
ng-if="item.parent">
</vn-icon-button>
<vn-icon-button translate-attr="::{title: 'Create'}"
icon="add_circle"
ng-click="$ctrl.treeview.onCreate(item)">
</vn-icon-button>
</section>
</div>

View File

@ -1,16 +1,24 @@
import ngModule from '../../module';
class Controller {
constructor($element) {
constructor($element, $scope, $compile) {
this.$element = $element;
this.$scope = $scope;
this.$compile = $compile;
}
$onInit() {
this.treeview.$transclude(($clone, $scope) => {
this.$contentScope = $scope;
$scope.item = this.item;
if (this.item.parent) {
this.treeview.$transclude(($clone, $scope) => {
this.$contentScope = $scope;
$scope.item = this.item;
this.$element.append($clone);
});
} else {
let template = `<span translate>{{$ctrl.treeview.rootLabel}}</span>`;
let $clone = this.$compile(template)(this.$scope);
this.$element.append($clone);
});
}
}
$onDestroy() {
@ -18,7 +26,7 @@ class Controller {
this.$contentScope.$destroy();
}
}
Controller.$inject = ['$element'];
Controller.$inject = ['$element', '$scope', '$compile'];
ngModule.component('vnTreeviewContent', {
controller: Controller,

View File

@ -1,11 +1,3 @@
<section class="add-item" ng-click="$ctrl.onCreate(null, $ctrl.items)" >
<vn-icon-button
icon="add_circle">
</vn-icon-button>
<span class="description" translate>
Create new one
</span>
</section>
<vn-treeview-childs
items="$ctrl.items">
</vn-treeview-childs>

View File

@ -7,23 +7,45 @@ import './content';
/**
* Treeview
*
* @property {String} position The relative position to the parent
*/
export default class Treeview extends Component {
constructor($element, $scope, $transclude) {
super($element, $scope);
this.$transclude = $transclude;
this.items = [];
this.readOnly = true;
}
$onInit() {
this.refresh();
get data() {
return this._data;
}
refresh() {
this.model.refresh().then(() => {
this.items = this.model.data;
set data(value) {
this._data = value;
const sons = value.length;
const rootElement = [{
childs: value,
active: true,
sons: sons
}];
this.setParent(rootElement[0], value);
this.items = rootElement;
}
fetch() {
return this.fetchFunc().then(res =>
this.data = res
);
}
setParent(parent, childs) {
childs.forEach(child => {
child.parent = parent;
if (child.childs)
this.setParent(parent, child.childs);
});
}
@ -40,11 +62,11 @@ export default class Treeview extends Component {
}
unfold(item) {
return this.model.applyFilter({}, {parentFk: item.id}).then(() => {
const newData = this.model.data;
return this.fetchFunc({$item: item}).then(newData => {
this.setParent(item, newData);
if (item.childs) {
let childs = item.childs;
const childs = item.childs;
if (childs) {
childs.forEach(child => {
let index = newData.findIndex(newChild => {
return newChild.id == child.id;
@ -53,84 +75,54 @@ export default class Treeview extends Component {
});
}
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);
});
if (this.sortFunc) {
item.childs = newData.sort((a, b) =>
this.sortFunc({$a: a, $b: b})
);
}
}).then(() => item.active = true);
}
onRemove(item) {
if (this.removeFunc)
this.removeFunc({$item: item});
}
remove(item) {
const parent = item.parent;
let childs = parent.childs;
if (!childs) childs = [];
let index = childs.indexOf(item);
childs.splice(index, 1);
if (parent) parent.sons--;
}
onCreate(parent) {
if (this.createFunc)
this.createFunc({$parent: parent});
}
create(item) {
const parent = item.parent;
let childs = parent.childs;
if (!childs) childs = [];
childs.push(item);
if (this.sortFunc) {
childs = childs.sort((a, b) =>
this.sortFunc({$a: a, $b: b})
);
}
if (parent) parent.sons++;
}
onDrop(item, dragged, dropped) {
this.emit('drop', {item, dragged, dropped});
}
onRemove(item, items, parent) {
if (!this.removeFunc) return;
let res = this.removeFunc({$item: item, $parent: parent});
function remove() {
let index = items.indexOf(item);
items.splice(index, 1);
if (parent) parent.sons--;
}
if (res instanceof Object && res.then)
res.then(remove);
else if (res)
remove();
}
onCreate(parent, childs) {
if (!this.createFunc) return;
let res = this.createFunc({$parent: parent, $childs: childs});
function create() {
if (!childs) childs = [];
childs.push(res);
if (parent) parent.sons++;
}
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'];
@ -139,16 +131,15 @@ ngModule.component('vnTreeview', {
template: require('./index.html'),
controller: Treeview,
bindings: {
model: '<',
icons: '<?',
disabled: '<?',
selectable: '<?',
editable: '<?',
rootLabel: '@',
data: '<?',
draggable: '<?',
droppable: '<?',
aclRole: '@?',
fetchFunc: '&',
removeFunc: '&?',
createFunc: '&?'
createFunc: '&?',
sortFunc: '&?',
readOnly: '<?'
},
transclude: true
});

View File

@ -5,6 +5,7 @@ vn-treeview {
@extend %clickable;
}
}
vn-treeview-childs {
display: block;
@ -22,6 +23,8 @@ vn-treeview-childs {
}
vn-icon-button {
display: table-cell;
vertical-align: middle;
padding: 0;
}

View File

@ -1,35 +0,0 @@
module.exports = Self => {
Self.remoteMethod('toggleIsIncluded', {
description: 'Toggle include to delivery',
accepts: [{
arg: 'zoneFk',
type: 'Number',
required: true,
},
{
arg: 'item',
type: 'Object',
required: true,
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/toggleIsIncluded`,
verb: 'POST'
}
});
Self.toggleIsIncluded = async(zoneFk, item) => {
if (item.isIncluded === null)
return Self.destroyAll({zoneFk, geoFk: item.id});
else {
return Self.upsert({
zoneFk: zoneFk,
geoFk: item.id,
isIncluded: item.isIncluded
});
}
};
};

View File

@ -6,10 +6,11 @@ module.exports = Self => {
{
arg: 'id',
type: 'Number',
description: 'The zone id',
http: {source: 'path'},
required: true
}, {
arg: 'parentFk',
arg: 'parentId',
type: 'Number',
description: 'Get the children of the specified father',
}, {
@ -28,10 +29,10 @@ module.exports = Self => {
}
});
Self.getLeaves = async(id, parentFk = null, search) => {
Self.getLeaves = async(id, parentId = null, search) => {
let [res] = await Self.rawSql(
`CALL zone_getLeaves(?, ?, ?)`,
[id, parentFk, search]
[id, parentId, search]
);
let map = new Map();
@ -49,7 +50,7 @@ module.exports = Self => {
}
}
let leaves = map.get(parentFk);
let leaves = map.get(parentId);
setLeaves(leaves);
return leaves || [];

View File

@ -0,0 +1,41 @@
module.exports = Self => {
Self.remoteMethod('toggleIsIncluded', {
description: 'Toggle include to delivery',
accepts: [{
arg: 'id',
type: 'Number',
description: 'The zone id',
http: {source: 'path'},
required: true
}, {
arg: 'geoId',
type: 'Number',
required: true
}, {
arg: 'isIncluded',
type: 'Boolean'
}],
returns: {
type: 'object',
root: true
},
http: {
path: `/:id/toggleIsIncluded`,
verb: 'POST'
}
});
Self.toggleIsIncluded = async(id, geoId, isIncluded) => {
const models = Self.app.models;
if (isIncluded === undefined)
return models.ZoneIncluded.destroyAll({zoneFk: id, geoFk: geoId});
else {
return models.ZoneIncluded.upsert({
zoneFk: id,
geoFk: geoId,
isIncluded: isIncluded
});
}
};
};

View File

@ -1,3 +0,0 @@
module.exports = Self => {
require('../methods/zone-included/toggleIsIncluded')(Self);
};

View File

@ -3,6 +3,7 @@ module.exports = Self => {
require('../methods/zone/editPrices')(Self);
require('../methods/zone/getLeaves')(Self);
require('../methods/zone/getEvents')(Self);
require('../methods/zone/toggleIsIncluded')(Self);
Self.validatesPresenceOf('agencyModeFk', {
message: `Agency cannot be blank`

View File

@ -1,26 +1,22 @@
<vn-crud-model
vn-id="model"
url="/api/Zones/{{$ctrl.$stateParams.id}}/getLeaves"
filter="::$ctrl.filter"
auto-load="false">
filter="::$ctrl.filter">
</vn-crud-model>
<div compact>
<vn-card pad-large-h>
<vn-searchbar
<vn-searchbar auto-load="false"
on-search="$ctrl.onSearch($params)"
vn-focus>
</vn-searchbar>
</vn-card>
<vn-card pad-large margin-medium-top>
<vn-treeview
vn-id="treeview"
model="model"
acl-role="deliveryBoss"
on-selection="$ctrl.onSelection(item, value)"
selectable="true">
<vn-treeview vn-id="treeview" root-label="Locations"
fetch-func="$ctrl.onFetch($item)"
sort-func="$ctrl.onSort($a, $b)">
<vn-check
field="item.selected"
on-change="$ctrl.onSelection(item, value)"
on-change="$ctrl.onSelection(value, item)"
triple-state="true"
label="{{::item.name}}">
</vn-check>

View File

@ -8,8 +8,29 @@ class Controller {
}
onSearch(params) {
this.$.model.applyFilter(null, params);
this.$.$applyAsync(() => this.$.treeview.refresh());
this.$.model.applyFilter({}, params).then(() => {
const data = this.$.model.data;
this.$.treeview.data = data;
});
}
onFetch(item) {
const params = item ? {parentId: item.id} : null;
return this.$.model.applyFilter({}, params).then(() => {
return this.$.model.data;
});
}
onSort(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);
}
exprBuilder(param, value) {
@ -19,13 +40,11 @@ class Controller {
}
}
onSelection(item, isIncluded) {
let node = Object.assign({}, item);
node.isIncluded = isIncluded;
node.childs = []; // Data too large
const path = '/agency/api/ZoneIncludeds/toggleIsIncluded';
const params = {zoneFk: this.zone.id, item: node};
onSelection(value, item) {
if (value == null)
value = undefined;
const params = {geoId: item.id, isIncluded: value};
const path = `/api/zones/${this.zone.id}/toggleIsIncluded`;
this.$http.post(path, params);
}
}

View File

@ -6,9 +6,11 @@
<div class="content-block" compact>
<form name="form" compact>
<vn-card margin-medium-v pad-medium>
<vn-treeview vn-id="treeview" model="model"
<vn-treeview vn-id="treeview" root-label="Departments" read-only="false"
fetch-func="$ctrl.onFetch($item)"
remove-func="$ctrl.onRemove($item)"
create-func="$ctrl.onCreate($parent, $childs)">
create-func="$ctrl.onCreate($parent)"
sort-func="$ctrl.onSort($a, $b)">
{{::item.name}}
</vn-treeview>
</vn-card>

View File

@ -2,13 +2,28 @@ import ngModule from '../module';
class Controller {
constructor($scope, $http, vnApp, $translate) {
this.$scope = $scope;
this.$ = $scope;
this.$http = $http;
this.vnApp = vnApp;
this.$translate = $translate;
}
onDrop(item, dragged, dropped) {
$postLink() {
this.$.treeview.fetch();
}
onFetch(item) {
const params = item ? {parentFk: item.id} : null;
return this.$.model.applyFilter({}, params).then(() => {
return this.$.model.data;
});
}
onSort(a, b) {
return a.name.localeCompare(b.name);
}
/* onDrop(item, dragged, dropped) {
if (dropped.scope.item) {
const droppedItem = dropped.scope.item;
const draggedItem = dragged.scope.item;
@ -20,16 +35,15 @@ class Controller {
this.$scope.$apply();
}
}
} */
onCreate(parent, childs) {
onCreate(parent) {
this.newChild = {
parent: parent,
childs: childs,
name: ''
};
this.$scope.createNode.show();
this.$.createNode.show();
}
onCreateDialogOpen() {
@ -44,15 +58,20 @@ class Controller {
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;
if (parent && parent.id)
params.parentId = parent.id;
if (!parent.active)
this.$.treeview.unfold(parent);
const query = `/api/departments/createChild`;
this.$http.post(query, params).then(response => {
if (!childs) childs = [];
childs.push(response.data);
this.$http.post(query, params).then(res => {
const parent = this.newChild.parent;
const item = res.data;
item.parent = parent;
this.$.treeview.create(item);
});
} catch (e) {
this.vnApp.showError(this.$translate.instant(e.message));
@ -64,7 +83,7 @@ class Controller {
onRemove(item) {
this.removedChild = item;
this.$scope.deleteNode.show();
this.$.deleteNode.show();
}
onRemoveResponse(response) {
@ -72,14 +91,7 @@ class Controller {
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); */
this.$.treeview.remove(this.removedChild);
});
}
}