Skip to content

Commit

Permalink
Resolves #242 partly, ability to reorder columns by drag and drop (#319)
Browse files Browse the repository at this point in the history
* Resolves #242 partly, alows to reorder columns by drag and drop

* Fixed glitching drag effects when mouse was hovering over grid title, added config option for choosing dbprovider

* Created seperate column builder method for rearangable view

* Cleanup, removed dead code

* Added documentation page

* Added method docs, and changed to do nothing on cur pos eq target pos

* Added terun type that indicates succes or failure

Co-authored-by: kus <kus@kus>
  • Loading branch information
k-u-s and kus authored Nov 16, 2021
1 parent 1039822 commit 0c32836
Show file tree
Hide file tree
Showing 30 changed files with 360 additions and 18 deletions.
3 changes: 3 additions & 0 deletions GridBlazor.Tests/Client/ClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ public void TestMainMethods()
_client.Groupable(false);
Assert.IsFalse(_client.Grid.ExtSortingEnabled);
Assert.IsFalse(_client.Grid.GroupingEnabled);

_client.RearrangeableColumns(true);
Assert.IsTrue(_client.Grid.RearrangeColumnEnabled);
}
}
}
22 changes: 22 additions & 0 deletions GridBlazor/CGrid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ private CGrid(HttpClient httpClient, string url,
public bool GroupingEnabled { get; set; }

public bool ClearFiltersButtonEnabled { get; set; } = false;

public bool RearrangeColumnEnabled { get; set; }

/// <summary>
/// Items, displaying in the grid view
Expand Down Expand Up @@ -595,6 +597,26 @@ public string[] GetPrimaryKeys()
return values.ToArray();
}

private static readonly Task<bool> InsertColumnSucceded = Task.FromResult(true);
private static readonly Task<bool> InsertColumnFailed = Task.FromResult(false);
/// <inheritdoc/>
public Task<bool> InsertColumn(IGridColumn targetColumn, IGridColumn insertingColumn)
{

var currentPossition = _columnsCollection.IndexOf(insertingColumn);
var targetPossition = _columnsCollection.IndexOf(targetColumn);
if (currentPossition == -1 || targetPossition == -1 || currentPossition == targetPossition)
return InsertColumnFailed;

var index = currentPossition > targetPossition ? targetPossition : targetPossition - 1;
var removed = _columnsCollection.Remove(insertingColumn);
if (!removed)
return InsertColumnFailed;

_columnsCollection.Insert(index, insertingColumn);
return InsertColumnSucceded;
}

/// <summary>
/// Fixed column values for the grid
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions GridBlazor/Client/GridClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,17 @@ public IGridClient<T> Groupable(bool enable)
return this;
}

public IGridClient<T> RearrangeableColumns()
{
return RearrangeableColumns(true);
}

public IGridClient<T> RearrangeableColumns(bool enable)
{
_source.RearrangeColumnEnabled = enable;
return this;
}

public IGridClient<T> ClearFiltersButton(bool enable)
{
_source.ClearFiltersButtonEnabled = enable;
Expand Down
10 changes: 10 additions & 0 deletions GridBlazor/Client/IGridClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ public interface IGridClient<T>
/// Enable or disable grouping
/// </summary>
IGridClient<T> Groupable(bool enable);

/// <summary>
/// Enable column rearrange
/// </summary>
IGridClient<T> RearrangeableColumns();

/// <summary>
/// Enable or disable column rearrange
/// </summary>
IGridClient<T> RearrangeableColumns(bool enable);

/// <summary>
/// Enable or disable visibility of ClearFiltersButton
Expand Down
13 changes: 13 additions & 0 deletions GridBlazor/ICGrid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public interface ICGrid : IGrid, IGridOptions
/// </summary>
bool SubGridsOpened { get; }

/// <summary>
/// Set or get default value of rearrange column
/// </summary>
public bool RearrangeColumnEnabled { get; set; }

Type Type { get; }

string Url { get; }
Expand Down Expand Up @@ -91,6 +96,14 @@ public interface ICGrid : IGrid, IGridOptions

Task DownloadExcel(IJSRuntime js, string filename);

/// <summary>
/// Changes postion of instertingColumn to appear before targetColumn
/// </summary>
/// <param name="targetColumn">Column which will be moved</param>
/// <param name="insertingColumn">Column before which it will be inserted</param>
/// <returns>Retruns true if column was sucessfully inserted before target otherwise false</returns>
Task<bool> InsertColumn(IGridColumn targetColumn, IGridColumn insertingColumn);

/// <summary>
/// Get and set export to an Excel file
/// </summary>
Expand Down
22 changes: 22 additions & 0 deletions GridBlazor/Pages/GridComponent.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,28 @@ protected virtual async Task OnAfterDeleteForm()
await AfterDeleteForm.Invoke(this, _item);
}
}

public async Task HandleColumnRearranged(GridHeaderComponent<T> gridHeaderComponent)
{
if (Payload == ColumnOrderValue.Null)
return;

var payload = Payload;
Payload = ColumnOrderValue.Null;
if (gridHeaderComponent.Column.Name == payload.ColumnName)
return;

var source = Grid.Columns.FirstOrDefault(c => c.Name == payload.ColumnName);
if (source is null)
return;

var updated = await Grid.InsertColumn(gridHeaderComponent.Column, source);
if (!updated)
return;

_shouldRender = true;
StateHasChanged();
}

public async Task ExcelHandler()
{
Expand Down
18 changes: 16 additions & 2 deletions GridBlazor/Pages/GridHeaderComponent.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@

@typeparam T

<th class="@_cssClass" style="@_cssStyles">
<th class="@_cssClass @_dropClass" style="@_cssStyles"
@ondragenter="HandleDragEnter"
@ondragleave="HandleDragLeave"
@ondrop="HandleDrop"
ondragover="event.preventDefault();"
>
<div class="grid-header-group">
@if (GridComponent.Grid.RearrangeColumnEnabled
&& !string.IsNullOrEmpty(_dropClass))
{
<div class="grid-column-rearrange-insert-placeholder">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-geo-fill" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M4 4a4 4 0 1 1 4.5 3.969V13.5a.5.5 0 0 1-1 0V7.97A4 4 0 0 1 4 3.999zm2.493 8.574a.5.5 0 0 1-.411.575c-.712.118-1.28.295-1.655.493a1.319 1.319 0 0 0-.37.265.301.301 0 0 0-.057.09V14l.002.008a.147.147 0 0 0 .016.033.617.617 0 0 0 .145.15c.165.13.435.27.813.395.751.25 1.82.414 3.024.414s2.273-.163 3.024-.414c.378-.126.648-.265.813-.395a.619.619 0 0 0 .146-.15.148.148 0 0 0 .015-.033L12 14v-.004a.301.301 0 0 0-.057-.09 1.318 1.318 0 0 0-.37-.264c-.376-.198-.943-.375-1.655-.493a.5.5 0 1 1 .164-.986c.77.127 1.452.328 1.957.594C12.5 13 13 13.4 13 14c0 .426-.26.752-.544.977-.29.228-.68.413-1.116.558-.878.293-2.059.465-3.34.465-1.281 0-2.462-.172-3.34-.465-.436-.145-.826-.33-1.116-.558C3.26 14.752 3 14.426 3 14c0-.599.5-1 .961-1.243.505-.266 1.187-.467 1.957-.594a.5.5 0 0 1 .575.411z"/>
</svg>
</div>
}
@if (Column.HeaderCheckbox)
{
<div class="grid-header-checkbox">
Expand All @@ -19,7 +33,7 @@
}
</div>
}
@if (Column.ParentGrid.ExtSortingEnabled)
@if (Column.ParentGrid.ExtSortingEnabled || GridComponent.Grid.RearrangeColumnEnabled)
{
<div class="grid-extsort-draggable @_cssSortingClass" draggable="true" data-column="@Column.Name" @ondragstart="() => HandleDragStart()" @onmouseover="DisplayTooltip" @onmouseout="HideTooltip">
@if (Column.SortEnabled)
Expand Down
34 changes: 34 additions & 0 deletions GridBlazor/Pages/GridHeaderComponent.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using GridShared.Sorting;
using GridShared.Utility;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -36,6 +37,8 @@ public partial class GridHeaderComponent<T>
private bool? _allChecked = null;
private bool _showAllChecked = false;

protected string _dropClass = "";

protected string _cssStyles;
protected string _cssClass;
protected string _cssFilterClass;
Expand Down Expand Up @@ -276,6 +279,37 @@ protected void HandleDragStart()
_shouldRender = true;
}

protected void HandleDragEnter()
{
if (!GridComponent.Grid.RearrangeColumnEnabled)
return;

_dropClass = "grid-header-drag-over";
_shouldRender = true;
Console.WriteLine("DragEnter");
}

protected void HandleDragLeave()
{
if (!GridComponent.Grid.RearrangeColumnEnabled)
return;

_dropClass = "";
_shouldRender = true;
Console.WriteLine("DragLeave");
}

protected async Task HandleDrop()
{
if (!GridComponent.Grid.RearrangeColumnEnabled)
return;

_dropClass = "";
_shouldRender = true;

await GridComponent.HandleColumnRearranged(this);
}

private void HideFilter()
{
if (_isFilterVisible)
Expand Down
30 changes: 27 additions & 3 deletions GridBlazor/wwwroot/css/gridblazor.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,21 @@ table.grid-table { margin: 0; }
table.grid-table .grid-header > .grid-header-group > .grid-header-title > button { font-weight: bold; color: #007bff; background-color: white; border: none }
table.grid-table .grid-header > .grid-header-group > .grid-header-title > button:hover { color: #0056b3; text-decoration: underline }
table.grid-table .grid-header > .grid-header-group > .grid-header-title > button:focus { outline: 0; }


/* Grid header drag over */
table.grid-table .grid-header.grid-header-drag-over {
border: 1px solid lightblue;
border-radius: 16px;
}

table.grid-table .grid-header.grid-header-drag-over * {
pointer-events: none;
}

table.grid-table .grid-header > .grid-header-group .grid-column-rearrange-insert-placeholder {
margin-left: -12px;
}

/* Grid body */
table.grid-table tr.grid-row-selected td { background: #4888C2 !important; color: white; }
table.grid-table tr.grid-row-selected a { color: white; }
Expand Down Expand Up @@ -201,10 +215,20 @@ div[dir="rtl"] button.grid-button-component { margin-left: 5px; margin-right: 0;
.grid-header-checkbox-input { opacity: 0; }
.grid-header-checkbox-input ~ .null-checkbox::before { position: absolute; top: 1rem; display: block; width: .9rem; height: .9rem; pointer-events: none; content: ""; border: 0.5px solid #666; border-radius: 3px; background-color: #ccc; }

div[dir="rtl"] label { display: flex; }
div[dir="rtl"] label {
display: flex;
}

/* The switch - the box around the slider */
.grid-switch { position: relative; display: inline-block; width: 50px; height: 24px; margin-left: 16px; margin-right: 16px; margin-bottom: -8px; }
.grid-switch {
position: relative;
display: inline-block;
width: 50px;
height: 24px;
margin-left: 16px;
margin-right: 16px;
margin-bottom: -8px;
}

/* Hide default HTML checkbox */
.grid-switch input { display: none; }
Expand Down
2 changes: 1 addition & 1 deletion GridBlazor/wwwroot/css/gridblazor.min.css

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions GridBlazorClientSide.Client/ColumnCollections/ColumnCollections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,38 @@ public class ColumnCollections
.RenderValueAs(o => o.Customer.IsVip ? Strings.BoolTrueLabel : Strings.BoolFalseLabel);
};

public static Action<IGridColumnCollection<Order>> OrderColumnsRearrangeable = c =>
{
/* Adding "OrderID" column: */
c.Add(o => o.OrderID).Titled(SharedResource.Number).SetWidth(100);

/* Adding "OrderDate" column: */
c.Add(o => o.OrderDate, "OrderCustomDate").Titled(SharedResource.OrderCustomDate)
.SetWidth(120).RenderComponentAs<TooltipCell>();

/* Adding "CompanyName" column: */
c.Add(o => o.Customer.CompanyName).Titled(SharedResource.CompanyName)
.ThenSortBy(o => o.ShipVia)
.ThenSortByDescending(o => o.Freight)
.SetWidth(250);

/* Adding "ContactName" column: */
c.Add(o => o.Customer.ContactName).Titled(SharedResource.ContactName);

/* Adding "ShipVia" column: */
c.Add(o => o.ShipVia).Titled("Via");

/* Adding "Freight" column: */
c.Add(o => o.Freight)
.Titled(SharedResource.Freight)
.SetWidth(150)
.Format("{0:F}");

/* Adding "Vip customer" column: */
c.Add(o => o.Customer.IsVip).Titled(SharedResource.IsVip).SetWidth(90).Css("hidden-xs") //hide on phones
.RenderValueAs(o => o.Customer.IsVip ? Strings.BoolTrueLabel : Strings.BoolFalseLabel);
};

public static Action<IGridColumnCollection<Order>, IList<Func<object, Task>>, object>
OrderColumnsWithEdit = (c, functions, obj) =>
{
Expand Down
58 changes: 58 additions & 0 deletions GridBlazorClientSide.Client/Pages/RearrangeableColumns.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
@page "/rearrangeable"
@using GridBlazorClientSide.Client.ColumnCollections
@using GridBlazorClientSide.Shared.Models
@using Microsoft.Extensions.Primitives
@using System.Globalization
@using System.Threading.Tasks
@inject NavigationManager NavigationManager
@inject HttpClient HttpClient

<h1>Rearrangeable Grid</h1>

<p>
This page contains a grid with grid clomuns rearrange. Column titles can be dragged and dropped on each other to change order.
</p>

<p>
This component demonstrates a GridBlazor client-side grid. For more information, please see: <a href="https://github.com/gustavnavar/Grid.Blazor">https://github.com/gustavnavar/Grid.Blazor</a>
</p>

@if (_task.IsCompleted)
{
<div class="row">
<div class="col-md-12">
<GridComponent T="Order" Grid="@_grid"></GridComponent>
</div>
</div>
}
else
{
<p><em>Loading...</em></p>
}

@code
{
private CGrid<Order> _grid;
private Task _task;

protected override async Task OnParametersSetAsync()
{
var locale = CultureInfo.CurrentCulture;

var query = new QueryDictionary<StringValues>();
string url = NavigationManager.BaseUri + "api/SampleData/GetOrdersGridRearrangeableColumns";
var client = new GridClient<Order>(HttpClient, url, query, false, "ordersGrid",
ColumnCollections.OrderColumnsRearrangeable, locale)
.Sortable()
.Filterable()
.SetStriped(true)
.WithMultipleFilters()
.WithGridItemsCount()
.RearrangeableColumns(true);

_grid = client.Grid;
// Set new items to grid
_task = client.UpdateGrid();
await _task;
}
}
5 changes: 5 additions & 0 deletions GridBlazorClientSide.Client/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
<span class="oi oi-list-rich" aria-hidden="true"></span> Groupable
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="rearrangeable">
<span class="oi oi-list-rich" aria-hidden="true"></span> Rearrangeable
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="editrows">
<span class="oi oi-list-rich" aria-hidden="true"></span> Edit rows
Expand Down
Loading

0 comments on commit 0c32836

Please sign in to comment.