Enhance drag&drop in the tree view

The style is not final, of course..
This commit is contained in:
Johannes Meyer 2018-12-21 13:58:45 +01:00
parent c804177ca4
commit eac7f3e76f
3 changed files with 111 additions and 42 deletions

View file

@ -21,9 +21,10 @@ class TreeRenderer extends Renderer
'div',
[
'id' => $bp->getHtmlId(),
'class' => ['bp', 'sortable'],
'class' => ['tree', 'sortable'],
'data-sortable-disabled' => $this->isLocked(),
'data-sortable-data-id-attr' => 'id',
'data-sortable-filter' => '.placeholder',
'data-sortable-direction' => 'vertical',
'data-csrf-token' => CsrfToken::generate(),
'data-action-url' => $this->getUrl()->getAbsoluteUrl()
@ -47,6 +48,7 @@ class TreeRenderer extends Renderer
$nodes = $this->parent->getChildren();
}
$html[] = Html::tag('div', ['class' => 'placeholder']);
foreach ($nodes as $name => $node) {
$html[] = $this->renderNode($bp, $node);
}
@ -107,10 +109,10 @@ class TreeRenderer extends Renderer
public function renderNode(BpConfig $bp, Node $node, $path = array())
{
$table = Html::tag(
'table',
'div',
[
'id' => $this->getId($node, $path),
'class' => ['bp', $node->getObjectClassName()],
'class' => ['bp', 'movable', $node->getObjectClassName()],
'data-node-name' => $node->getName()
]
);
@ -125,30 +127,16 @@ class TreeRenderer extends Renderer
$attributes->add('class', 'node');
}
$tbody = Html::tag('tbody', [
'class' => 'sortable',
'data-sortable-disabled' => $this->isLocked(),
'data-sortable-data-id-attr' => 'id',
'data-sortable-draggable' => '.movable',
'data-sortable-direction' => 'vertical',
'data-csrf-token' => CsrfToken::generate(),
'data-action-url' => $this->getUrl()
->overwriteParams(['node' => (string) $node])
->getAbsoluteUrl()
]);
$table->add($tbody);
$tr = Html::tag('tr');
$tbody->add($tr);
if ($node instanceof BpNode) {
$tr->add(Html::tag(
'th',
['rowspan' => $node->countChildren() + 1 + ($this->isLocked() ? 0 : 1)],
$table->add(Html::tag(
'div',
null,
Html::tag('span', ['class' => 'op'], $node->operatorHtml())
));
}
$td = Html::tag('td');
$tr->add($td);
$td = Html::tag('div');
$table->add($td);
if ($node instanceof BpNode && $node->hasInfoUrl()) {
$td->add($this->createInfoAction($node));
@ -175,38 +163,82 @@ class TreeRenderer extends Renderer
$td->add($link);
$tbody = Html::tag('ul', [
'class' => 'sortable',
'data-sortable-disabled' => $this->isLocked(),
'data-sortable-data-id-attr' => 'id',
'data-sortable-draggable' => '.movable',
'data-sortable-direction' => 'vertical',
'data-csrf-token' => CsrfToken::generate(),
'data-action-url' => $this->getUrl()
->overwriteParams(['node' => (string) $node])
->getAbsoluteUrl()
]);
$table->add($tbody);
$path[] = (string) $node;
foreach ($node->getChildren() as $name => $child) {
$tbody->add(Html::tag(
'tr',
[
'class' => 'movable',
'id' => $this->getId($child, $path),
'data-node-name' => $name
],
Html::tag(
'td',
null,
if ($child->hasChildren()) {
$tbody->add(Html::tag(
'li',
[
'class' => 'movable',
'id' => $this->getId($child, $path),
'data-node-name' => $name
],
$this->renderNode($bp, $child, $this->getCurrentPath())
)
));
));
} else {
$this->renderChild($bp, $tbody, $child, $path);
}
}
if (! $this->isLocked() && $node instanceof BpNode && $bp->getMetadata()->canModify()) {
$tbody->add(Html::tag(
'tr',
'li',
null,
Html::tag(
'td',
null,
$this->renderAddNewNode($node)
)
$this->renderAddNewNode($node)
));
}
return $table;
}
protected function renderChild($bp, BaseHtmlElement $ul, $node, $path = null)
{
$li = Html::tag('li', [
'class' => 'movable',
'id' => $this->getId($node, $path ?: []),
'data-node-name' => (string) $node
]);
$ul->add($li);
if ($node instanceof BpNode && $node->hasInfoUrl()) {
$li->add($this->createInfoAction($node));
}
if (! $this->isLocked()) {
$li->add($this->getActionIcons($bp, $node));
}
$link = $node->getLink();
$link->getAttributes()->set('data-base-target', '_next');
$link->add($this->getNodeIcons($node));
if ($node->hasChildren()) {
$link->add($this->renderStateBadges($node->getStateSummary()));
}
if ($time = $node->getLastStateChange()) {
$since = $this->timeSince($time)->prepend(
sprintf(' (%s ', $node->getStateName())
)->add(')');
$link->add($since);
}
$li->add($link);
}
protected function getActionIcons(BpConfig $bp, Node $node)
{
if ($node instanceof BpNode) {

View file

@ -33,6 +33,38 @@ div.bp.sortable > .sortable-ghost {
background: white;
}
/* New tree stuff START */
div.tree {
padding: 1em;
div.placeholder {
// Helps to assist Sortable.js/the browser to properly place items at the top
height: 1em;
}
> div.process,
ul.sortable li {
border: .2em solid @gray;
margin-bottom: .2em;
padding-left: .2em;
&.sortable-ghost {
border: .2em dashed @gray-light;
}
}
ul {
list-style-type: none;
}
}
/* New tree stuff END */
table.bp {
/* Business process table styling starts here */
width: 100%;

View file

@ -36,7 +36,7 @@
this.module.on('click', 'div.tiles > div', this.tileClick);
this.module.on('click', '.dashboard-tile', this.dashboardTileClick);
this.module.on('end', 'div.tiles.sortable', this.tileDropped);
this.module.on('end', 'div.bp.sortable, table.bp tbody.sortable', this.rowDropped);
this.module.on('end', 'div.tree.sortable, ul.sortable', this.rowDropped);
this.module.icinga.logger.debug('BP module initialized');
},
@ -126,6 +126,11 @@
movenode: $(evt.item).data('nodeName')
});
if ($('.placeholder', $target).length) {
evt.oldIndex -= 1;
evt.newIndex -= 1;
}
var data = {
csrfToken: $target.data('csrfToken'),
movenode: 'movenode', // That's the submit button..