fixed treeview #1374
gitea/salix/dev This commit looks good Details

This commit is contained in:
Joan Sanchez 2019-04-29 11:49:43 +02:00
parent a8a5193a86
commit 69403223d8
15 changed files with 215 additions and 71 deletions

View File

@ -0,0 +1,71 @@
DROP procedure IF EXISTS `nst`.`nodeAdd`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `nst`.`nodeAdd`(IN `vScheme` VARCHAR(45), IN `vTable` VARCHAR(45), IN `vParentFk` INT, IN `vChild` VARCHAR(100))
BEGIN
DECLARE vSql TEXT;
DECLARE vTableClone VARCHAR(45);
SET vTableClone = CONCAT(vTable, 'Clone');
CALL util.exec(CONCAT('DROP TEMPORARY TABLE IF EXISTS tmp.', vTableClone));
CALL util.exec(CONCAT(
'CREATE TEMPORARY TABLE tmp.', vTableClone,
' ENGINE = MEMORY',
' SELECT * FROM ', vScheme, '.', vTable
));
CALL util.exec(CONCAT(
'SELECT COUNT(c.id) INTO @childs',
' FROM ', vScheme, '.', vTable, ' p',
' LEFT JOIN tmp.', vTableClone, ' c ON c.lft',
' BETWEEN p.lft AND p.rgt AND c.id != ', vParentFk,
' WHERE p.id = ', vParentFk
));
IF @childs = 0 THEN
CALL util.exec(CONCAT(
'SELECT lft INTO @vLeft',
' FROM ', vScheme, '.', vTable,
' WHERE id = ', vParentFk
));
ELSE
CALL util.exec(CONCAT(
'SELECT c.rgt INTO @vLeft',
' FROM ', vScheme, '.', vTable, ' p',
' JOIN tmp.', vTableClone, ' c ON c.lft BETWEEN p.lft AND p.rgt',
' WHERE p.id = ', vParentFk,
' ORDER BY c.lft',
' DESC LIMIT 1'
));
END IF;
CALL util.exec(CONCAT(
'UPDATE ', vScheme, '.', vTable, ' SET rgt = rgt + 2',
' WHERE rgt > @vLeft',
' ORDER BY rgt DESC'
));
CALL util.exec(CONCAT(
'UPDATE ', vScheme, '.', vTable, ' SET lft = lft + 2',
' WHERE lft > @vLeft',
' ORDER BY lft DESC'
));
SET vChild = REPLACE(vChild, "'", "\\'");
CALL util.exec(CONCAT(
'INSERT INTO ', vScheme, '.', vTable, ' (name, lft, rgt)',
' VALUES ("', vChild, '", @vLeft + 1, @vLeft + 2)'
));
CALL util.exec(CONCAT(
'SELECT id, name, lft, rgt, depth, sons',
' FROM ', vScheme, '.', vTable,
' WHERE id = LAST_INSERT_ID()'
));
CALL util.exec(CONCAT('DROP TEMPORARY TABLE tmp.', vTableClone));
END$$
DELIMITER ;

View File

@ -0,0 +1,34 @@
DROP procedure IF EXISTS `nst`.`nodeDelete`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `nst`.`nodeDelete`(IN `vScheme` VARCHAR(45), IN `vTable` VARCHAR(45), IN `vNodeId` INT)
BEGIN
DECLARE vMyRight INT;
DECLARE vMyLeft INT;
DECLARE vMyWidth INT;
CALL util.exec(CONCAT(
'SELECT t.rgt, t.lft, t.rgt - t.lft + 1',
' INTO @vMyRight, @vMyLeft, @vMyWidth',
' FROM ', vScheme, '.', vTable, ' t',
' WHERE t.id = ', vNodeId
));
CALL util.exec(CONCAT(
'DELETE FROM ', vScheme, '.', vTable,
' WHERE lft BETWEEN @vMyLeft AND @vMyRight'
));
CALL util.exec(CONCAT(
'UPDATE ', vScheme, '.', vTable, ' SET rgt = rgt - @vMyWidth'
' WHERE rgt > @vMyRight ORDER BY rgt'
));
CALL util.exec(CONCAT(
'UPDATE ', vScheme, '.', vTable, ' SET lft = lft - @vMyWidth'
' WHERE lft > @vMyRight ORDER BY lft'
));
END$$
DELIMITER ;

View File

@ -0,0 +1,23 @@
DROP procedure IF EXISTS `nst`.`nodeRecalc`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `nst`.`nodeRecalc`(IN `vScheme` VARCHAR(45), IN `vTable` VARCHAR(45))
BEGIN
CALL util.exec(CONCAT (
'UPDATE ', vScheme, '.', vTable, ' d',
' JOIN (SELECT',
' node.id,',
' COUNT(parent.id) - 1 as depth,',
' cast((node.rgt - node.lft - 1) / 2 as DECIMAL) as sons',
' FROM ',
' ', vScheme, '.', vTable, ' AS node,',
' ', vScheme, '.', vTable, ' AS parent',
' WHERE node.lft BETWEEN parent.lft AND parent.rgt',
' GROUP BY node.id',
' ORDER BY node.lft) n ON n.id = d.id ',
' SET d.`depth` = n.depth, d.sons = n.sons'
));
END$$
DELIMITER ;

View File

@ -3,7 +3,7 @@ import Component from '../../lib/component';
import './style.scss'; import './style.scss';
/** /**
* Calendar. * Flat calendar.
* *
*/ */
export default class Calendar extends Component { export default class Calendar extends Component {

View File

@ -1,18 +1,17 @@
<ul ng-if="::$ctrl.items"> <ul ng-if="::$ctrl.items">
<li ng-repeat="item in $ctrl.items" <li ng-repeat="item in $ctrl.items"
ng-class="{ ng-class="{
'expanded': item.active, 'expanded': item.active,
'collapsed': !item.active, 'collapsed': !item.active,
'included': item.selected == 1, 'included': item.selected == 1,
'excluded': item.selected == 0 'excluded': item.selected == 0
}" vn-draggable vn-droppable on-drop="$ctrl.onDrop(item, dragged, dropped)"> }" vn-draggable="{{::$ctrl.draggable}}" vn-droppable="{{::$ctrl.droppable}}" on-drop="$ctrl.onDrop(item, dragged, dropped)">
<vn-horizontal> <vn-horizontal>
<vn-auto class="actions"> <vn-auto class="actions">
<vn-icon icon="keyboard_arrow_down" title="{{'Toggle' | translate}}" <vn-icon icon="keyboard_arrow_down" title="{{'Toggle' | translate}}"
ng-click="$ctrl.toggle(item, $event)"> ng-click="$ctrl.toggle(item, $event)">
</vn-icon> </vn-icon>
</vn-auto> </vn-auto>
<vn-one class="description">
<vn-check vn-auto vn-acl="{{$ctrl.aclRole}}" <vn-check vn-auto vn-acl="{{$ctrl.aclRole}}"
ng-if="$ctrl.selectable" ng-if="$ctrl.selectable"
field="item.selected" field="item.selected"
@ -20,35 +19,37 @@
on-change="$ctrl.select(item, value)" on-change="$ctrl.select(item, value)"
triple-state="true"> triple-state="true">
</vn-check> </vn-check>
{{::item.name}} <vn-one class="description">{{::item.name}}</vn-one>
</vn-one> <vn-auto>
<vn-auto> <vn-icon-button icon="{{icon.icon}}"
<vn-icon-button icon="{{icon.icon}}" ng-repeat="icon in $ctrl.icons"
ng-repeat="icon in $ctrl.icons" ng-click="$ctrl.onIconClick(icon, item, $ctrl.parent, $parent.$index)"
ng-click="$ctrl.onIconClick(icon, item, $ctrl.parent, $parent.$index)" vn-acl="{{$ctrl.aclRole}}" vn-acl-action="remove">
vn-acl="{{$ctrl.aclRole}}" vn-acl-action="remove"> </vn-icon-button>
</vn-icon-button> </vn-auto>
</vn-auto> </vn-horizontal>
</vn-horizontal> <vn-treeview-child items="item.childs" parent="item"
<vn-treeview-child items="item.childs" parent="item" selectable="$ctrl.selectable"
selectable="$ctrl.selectable" disabled="$ctrl.disabled"
disabled="$ctrl.disabled" editable="$ctrl.editable"
editable="$ctrl.editable" draggable="::$ctrl.draggable"
icons="$ctrl.icons" droppable="::$ctrl.droppable"
acl-role="$ctrl.aclRole"> icons="::$ctrl.icons"
</vn-treeview-child> parent-scope="::$ctrl.parentScope"
</li> acl-role="$ctrl.aclRole">
<li ng-if="$ctrl.isInsertable && $ctrl.editable" </vn-treeview-child>
ng-click="$ctrl.onCreate($ctrl.parent)" </li>
vn-acl="{{$ctrl.aclRole}}" <li ng-if="$ctrl.isInsertable && $ctrl.editable"
vn-acl-action="remove"> ng-click="$ctrl.onCreate($ctrl.parent)"
<vn-horizontal> vn-acl="{{$ctrl.aclRole}}"
<vn-auto> vn-acl-action="remove">
<vn-icon-button icon="add_circle"></vn-icon-button> <vn-horizontal>
</vn-auto> <vn-auto>
<div class="description" translate> <vn-icon-button icon="add_circle"></vn-icon-button>
Create new one </vn-auto>
</div> <div class="description" translate>
</vn-horizontal> Create new one
</li> </div>
</ul> </vn-horizontal>
</li>
</ul>

View File

@ -16,8 +16,7 @@ class Controller extends Component {
} }
onIconClick(icon, item, parent, index) { onIconClick(icon, item, parent, index) {
let parentScope = this.$scope.$parent.$parent; let parentController = this.parentScope.$ctrl;
let parentController = parentScope.$ctrl;
icon.callback.call(parentController, item, parent, index); icon.callback.call(parentController, item, parent, index);
} }
@ -44,7 +43,10 @@ ngModule.component('vnTreeviewChild', {
disabled: '<?', disabled: '<?',
selectable: '<?', selectable: '<?',
editable: '<?', editable: '<?',
draggable: '<?',
droppable: '<?',
aclRole: '<?', aclRole: '<?',
parentScope: '<'
}, },
require: { require: {
treeview: '^vnTreeview' treeview: '^vnTreeview'

View File

@ -1,10 +1,12 @@
<vn-treeview-child <vn-treeview-child acl-role="$ctrl.aclRole"
items="$ctrl.data" items="$ctrl.data"
parent="$ctrl.data" parent="$ctrl.data"
selectable="$ctrl.selectable" selectable="$ctrl.selectable"
editable="$ctrl.editable" editable="$ctrl.editable"
disabled="$ctrl.disabled" disabled="$ctrl.disabled"
icons="$ctrl.icons" icons="$ctrl.icons"
acl-role="$ctrl.aclRole" parent-scope="$ctrl.$scope.$parent"
vn-droppable> draggable="$ctrl.draggable"
droppable="$ctrl.droppable"
vn-droppable="{{$ctrl.droppable}}">
</vn-treeview-child> </vn-treeview-child>

View File

@ -3,13 +3,14 @@ import Component from '../../lib/component';
import './style.scss'; import './style.scss';
/** /**
* A simple tooltip. * Treeview
* *
* @property {String} position The relative position to the parent * @property {String} position The relative position to the parent
*/ */
export default class Treeview extends Component { export default class Treeview extends Component {
constructor($element, $scope) { constructor($element, $scope) {
super($element, $scope); super($element, $scope);
this.$scope = $scope;
this.data = []; this.data = [];
} }
@ -86,6 +87,8 @@ ngModule.component('vnTreeview', {
disabled: '<?', disabled: '<?',
selectable: '<?', selectable: '<?',
editable: '<?', editable: '<?',
draggable: '<?',
droppable: '<?',
aclRole: '@?' aclRole: '@?'
} }
}); });

View File

@ -24,10 +24,6 @@ vn-treeview {
} }
} }
li[vn-draggable] {
cursor: move
}
li vn-icon { li vn-icon {
cursor: pointer; cursor: pointer;
} }
@ -58,19 +54,22 @@ vn-treeview {
& > vn-horizontal > .description { & > vn-horizontal > .description {
color: $color-notice; color: $color-notice;
font-weight: bold; font-weight: bold;
& > vn-check .md-icon {
background-color: $color-notice
}
} }
& > vn-horizontal > vn-check .md-icon {
background-color: $color-notice
}
} }
li.excluded { li.excluded {
& > vn-horizontal > .description { & > vn-horizontal > .description {
color: $color-alert; color: $color-alert;
font-weight: bold; font-weight: bold;
}
& > vn-horizontal > vn-check .md-icon {
background-color: $color-alert;
border-color: transparent
} }
} }
} }

View File

@ -8,8 +8,15 @@ import ngModule from '../module';
export function directive() { export function directive() {
return { return {
restrict: 'A', restrict: 'A',
link: function($scope, $element) { link: function($scope, $element, $attrs) {
const element = $element[0]; const element = $element[0];
const isDraggable = $attrs.vnDraggable === 'true';
if (!isDraggable) return;
// Set draggable style properties
element.style.cursor = 'move';
// Enable as draggable element // Enable as draggable element
element.setAttribute('draggable', true); element.setAttribute('draggable', true);

View File

@ -7,6 +7,9 @@ export function directive($parse) {
link: function($scope, $element, $attrs) { link: function($scope, $element, $attrs) {
const element = $element[0]; const element = $element[0];
const onDropEvent = $parse($attrs.onDrop); const onDropEvent = $parse($attrs.onDrop);
const isDroppable = $attrs.vnDroppable === 'true';
if (!isDroppable) return;
/** /**
* Captures current dragging element * Captures current dragging element

View File

@ -12,8 +12,9 @@
on-search="$ctrl.onSearch()" on-search="$ctrl.onSearch()"
vn-focus> vn-focus>
</vn-searchbar> </vn-searchbar>
<vn-treeview vn-id="treeview" model="model" selectable="true" acl-role="deliveryBoss" <vn-treeview vn-id="treeview" model="model" acl-role="deliveryBoss"
on-selection="$ctrl.onSelection(item, value)"> on-selection="$ctrl.onSelection(item, value)"
selectable="true">
</vn-treeview> </vn-treeview>
</vn-card> </vn-card>
<vn-side-menu side="right"> <vn-side-menu side="right">

View File

@ -29,7 +29,7 @@ module.exports = Self => {
let stmts = []; let stmts = [];
let conn = Self.dataSource.connector; let conn = Self.dataSource.connector;
let nodeIndex = stmts.push(new ParameterizedSQL( let nodeIndex = stmts.push(new ParameterizedSQL(
`CALL nst.NodeAdd('vn', 'department', ?, ?)`, [parentFk, name])) - 1; `CALL nst.nodeAdd('vn', 'department', ?, ?)`, [parentFk, name])) - 1;
stmts.push(`CALL nst.nodeRecalc('vn', 'department')`); stmts.push(`CALL nst.nodeRecalc('vn', 'department')`);

View File

@ -8,10 +8,6 @@ module.exports = Self => {
Self.rewriteDbError(function(err) { Self.rewriteDbError(function(err) {
if (err.code === 'ER_ROW_IS_REFERENCED_2') if (err.code === 'ER_ROW_IS_REFERENCED_2')
return new UserError(`You cannot remove this department`); return new UserError(`You cannot remove this department`);
return err;
});
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY') if (err.code === 'ER_DUP_ENTRY')
return new UserError(`The department name can't be repeated`); return new UserError(`The department name can't be repeated`);
return err; return err;

View File

@ -12,7 +12,9 @@
on-selection="$ctrl.onSelection(item, value)" on-selection="$ctrl.onSelection(item, value)"
on-create="$ctrl.onCreate(parent)" on-create="$ctrl.onCreate(parent)"
on-drop="$ctrl.onDrop(item, dragged, dropped)" on-drop="$ctrl.onDrop(item, dragged, dropped)"
icons="$ctrl.icons" editable="true" acl-role="hr"> icons="$ctrl.icons"
draggable="true" droppable="true"
acl-role="hr" editable="true">
</vn-treeview> </vn-treeview>
</vn-card> </vn-card>
</div> </div>