From 1a98fca1cb6c1204e07e2aa244451e6980dd489d Mon Sep 17 00:00:00 2001 From: Felix Eggmann Date: Wed, 28 Feb 2018 20:38:28 +0100 Subject: [PATCH] fix(ui): WIP enhance tree icons, enhance sorting visual feedback --- code/GridFieldPageSectionsExtension.php | 6 +- css/GridFieldPageSectionsExtension.css | 162 ++++++++++++------- javascript/GridFieldPageSectionsExtension.js | 34 ++-- templates/GridFieldPageElement.ss | 7 +- 4 files changed, 134 insertions(+), 75 deletions(-) diff --git a/code/GridFieldPageSectionsExtension.php b/code/GridFieldPageSectionsExtension.php index 7dacf4e..899d449 100644 --- a/code/GridFieldPageSectionsExtension.php +++ b/code/GridFieldPageSectionsExtension.php @@ -158,10 +158,10 @@ public function getColumnContent($gridField, $record, $columnName) { $field = null; if ($record->Children() && $record->Children()->Count() > 0) { - $icon = ($open === true ? '' - : ''); + $icon = ($open === true ? '' + : ''); } else { - $icon = ''; + $icon = ''; } $field = GridField_FormAction::create( diff --git a/css/GridFieldPageSectionsExtension.css b/css/GridFieldPageSectionsExtension.css index a031998..6e4334c 100644 --- a/css/GridFieldPageSectionsExtension.css +++ b/css/GridFieldPageSectionsExtension.css @@ -40,92 +40,103 @@ border-top: 1px solid #CCC; } - -.ss-gridfield-pagesections .col-treenav { +/* hierarchical gridfield */ +.cms table.ss-gridfield-table tr { height: 100%; - padding: 0 !important; } -.ss-gridfield-pagesections .col-treenav > button { - //width: 100% !important; - height: 100% !important; - font-weight: bold !important; - /*font-size: 150% !important;*/ - color: black !important; +.cms table.ss-gridfield-table tbody td.col-treenav { + padding: 0; + height: 100%; + vertical-align: middle; } -.ss-gridfield-pagesections .col-treenav > button, .ss-gridfield-pagesections .col-treenav > button > span { - padding: 0 !important; - margin: 0 !important; - text-align: left !important; +.cms table.ss-gridfield-table tbody td.col-treenav .col-treenav__inner { + display: flex; + height: 100%; + flex-flow: row nowrap; + justify-content: flex-start; + align-items: center; } -.ss-gridfield-pagesections .col-treenav > button:focus { - background: none !important; - box-shadow: none!important; - border: none !important; - background-color: none !important; +.cms table.ss-gridfield-table tbody td.col-treenav button { + width: 2em; + height: 100%; + display: block; + float: left; + margin: 0 0.5em 0 0; + padding: 0; + border-radius: 0; + position: relative; } -.ss-gridfield-pagesections .col-treenav > button > span > span.is-closed{ - - font-size: 100%; +.cms table.ss-gridfield-table tbody td.col-treenav button svg { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); } -.ss-gridfield-pagesections .col-treenav > button > span > span.is-open{ - font-size: 96%; - margin-left: -0.1em; +.cms table.ss-gridfield-table tbody td.col-treenav button.level1 { + margin-left: 2em; } -.ss-gridfield-pagesections .col-treenav > button > span > span.is-end{ - font-size: 110%; - margin-left: -0.1em; +.cms table.ss-gridfield-table tbody td.col-treenav button.level2 { + margin-left: 4em; } -.ss-gridfield-pagesections .col-treenav > button > span > span { - margin-right: 1em; - text-transform: capitalize; - vertical-align: middle; +.cms table.ss-gridfield-table tbody td.col-treenav button.level3 { + margin-left: 6em; } -.ss-gridfield-pagesections .col-treenav > button > span { - margin-right: 30px !important; - text-overflow: ellipsis; - white-space: nowrap; - overflow-x: hidden; +.cms table.ss-gridfield-table tbody td.col-treenav button.level4 { + margin-left: 8em; } -.ss-gridfield-pagesections .col-treenav > button.level0 > span { - margin-left: 1em !important; -} -.ss-gridfield-pagesections .col-treenav > button.level1 > span { - margin-left: 2em !important; +.cms table.ss-gridfield-table tbody td.col-treenav button.level5 { + margin-left: 10em; } -.ss-gridfield-pagesections .col-treenav > button.level2 > span { - margin-left: 4em !important; -} -.ss-gridfield-pagesections .col-treenav > button.level3 > span { - margin-left: 6em !important; -} -.ss-gridfield-pagesections .col-treenav > button.level4 > span { - margin-left: 8em !important; +.cms table.ss-gridfield-table tbody td.col-treenav button.level6 { + margin-left: 12em; } - /** * Orderable rows */ +.col-treenav__draggable { + z-index: 300; + background: #f6f7f8; + padding: 2px 4px; + border-radius: 2px; + box-shadow: 0 0 1px #ccc; +} + +.col-treenav__draggable:before { + position: absolute; + content: ""; + left: -19px; + top: -19px; + width: 8px; + height: 8px; + border: 3px solid #4a4a4a; + border-radius: 50%; + box-sizing: border-box; +} + +.col-treenav__draggable.state-hover { + background: #A8CB7F; +} .ss-gridfield-pagesections thead tr th.col-Reorder span { padding: 0 !important; margin-left: 8px; } -.ss-gridfield-pagesections .col-reorder { +.cms .ss-gridfield-pagesections table.ss-gridfield-table tr td.col-reorder { position: relative; - padding: 0 !important; - width: 16px !important; + padding: 0; + width: 16px; } .ss-gridfield-pagesections .col-reorder .handle { @@ -150,26 +161,63 @@ .ss-gridfield-pagesections .col-reorder .ui-droppable { position: absolute; - left: 0; - width: 100%; + left: 100%; + width: 500%; z-index: 100; display: none; } +.ss-gridfield-pagesections .col-reorder .ui-droppable svg { + position: absolute; + left: 0; + top: 50%; + z-index: 100; + transform: translate(0, -50%); +} + +.ss-gridfield-pagesections .col-reorder .ui-droppable svg path { + fill: #A8CB7F; +} + .ss-gridfield-pagesections .col-reorder .ui-droppable.before { top: 0; height: 25%; background-color: rgba(0, 100, 0, 0.4); } +.ss-gridfield-pagesections .col-reorder .ui-droppable.before svg { + top: 0; +} + .ss-gridfield-pagesections .col-reorder .ui-droppable.middle { - top: 25%; - height: 50%; + left: auto; + right: 0; + top: 0; + height: 100%; background-color: rgba(0, 0, 100, 0.4); } +.ss-gridfield-pagesections .col-reorder .ui-droppable.middle svg { + left: auto; + right: 0; + transform: scale(-1) translate(0, 50%); +} + .ss-gridfield-pagesections .col-reorder .ui-droppable.after { bottom: 0; height: 25%; background-color: rgba(0, 100, 0, 0.4); } + +.ss-gridfield-pagesections .col-reorder .ui-droppable.after svg { + top: 100%; +} + +.ss-gridfield-pagesections .col-reorder .ui-droppable.state-active { + background: pink !important; + z-index: 200; +} + +.ss-gridfield-pagesections .col-reorder .ui-droppable.state-active svg path { + fill: #417505; +} diff --git a/javascript/GridFieldPageSectionsExtension.js b/javascript/GridFieldPageSectionsExtension.js index dbf35aa..8ff542c 100644 --- a/javascript/GridFieldPageSectionsExtension.js +++ b/javascript/GridFieldPageSectionsExtension.js @@ -50,7 +50,7 @@ var grid = this.getGridField(); var id = grid.data("id"); var rowId = $target.parents(".ss-gridfield-item").data("id"); - var $treeNav = $target.hasClass("col-treenav") ? $target : + var $treeNav = $target.hasClass("col-treenav") ? $target : $target.parents(".col-treenav").first(); // If we don't have a col-treenav the user clicked on another column @@ -63,7 +63,7 @@ if (level > 0) { // Go up through the rows and find the first row with lower level (=parent) $parent = $treeNav.parents(".ss-gridfield-item").prev(); - while ($parent.length > 0 && + while ($parent.length > 0 && $parent.find(".col-treenav").data("level") >= level) { $parent = $parent.prev(); } @@ -91,7 +91,7 @@ $menu.append("
  • " + value + "
  • "); }); $menu.append("
  • Options
  • "); - $menu.append("
  • Remove from " + + $menu.append("
  • Remove from " + (parentId ? parentName : "page") + "
  • "); $menu.append("
  • Delete
  • "); $menu.show(); @@ -133,11 +133,13 @@ $("tr.ss-gridfield-item").each(function() { var $this = $(this); + var icon = "" $col = $this.find(".col-reorder"); - $col.append("
    "); + $col.append("
    " + icon + "
    " + icon + "
    " + icon + "
    "); $col.find("div").each(function() { $(this).droppable({ + hoverClass: "state-active", tolerance: "pointer", drop: function(event, ui) { $drop = $(this); @@ -155,12 +157,12 @@ // If the current element is open, then dragging the other element to the // "after" slot means it becomes a child of this element, otherwise it // has to actually go after this element. - if ($treenav.find("button").hasClass("is-open")) { - type = "child"; - childOrder = -1000000; - } else { - type = "after"; - } + if ($treenav.find("button").hasClass("is-open")) { + type = "child"; + childOrder = -1000000; + } else { + type = "after"; + } } var id = ui.draggable.data("id"); @@ -195,13 +197,17 @@ $this.draggable({ revert: "invalid", + cursor: "crosshair", + cursorAt: { top: -15, left: -15 }, + activeClass: "state-hover", helper: function() { - var clone = $this.clone().css("z-index", 200).find(".ui-droppable").remove().end(); + var $helper = $("
    " + $this.find(".col-treenav__title").text() + "
    ") + //var clone = $this.clone().css("z-index", 200).find(".ui-droppable").remove().end(); // Timeout is needed otherwise the draggable position is messed up setTimeout(function() { hideRow($this); }, 1); - return clone; + return $helper; }, start: function() { var element = $this.data("class"); @@ -212,10 +218,10 @@ // Check if we're allowed to drop the element on the specified drop point. // Depending on where we drop it (before, middle or after) we have to either // check our allowed children, or the allowed children of our parent row. - if ($drop.hasClass("before") || + if ($drop.hasClass("before") || ($drop.hasClass("after") && !$treenav.find("button").hasClass("is-open"))) { - var $parent = $treenav.parent().siblings("[data-id=" + + var $parent = $treenav.parent().siblings("[data-id=" + $treenav.data("parent") + "]").first(); var allowed = $parent.find(".col-treenav").data("allowed-elements"); diff --git a/templates/GridFieldPageElement.ss b/templates/GridFieldPageElement.ss index 471c3b8..5035369 100644 --- a/templates/GridFieldPageElement.ss +++ b/templates/GridFieldPageElement.ss @@ -1 +1,6 @@ -$ButtonField $Title +
    + $ButtonField + + $Title + +