Changed up results configuration layout.

Removed dropdown portion.

Added buttons to change sort order.

Visual indicator for disabling changes to sort order list.

Renamed a namespace.
This commit is contained in:
Harrison Deng 2021-05-10 00:30:40 -05:00
parent 9dc8917aa5
commit 99656133c9
11 changed files with 84 additions and 136 deletions

@ -1 +1 @@
Subproject commit f275ff330db936d7eabc6dc435952ec0752edbc9 Subproject commit 3049cccc3efa3323a85f1ae591969b8f5d35be5d

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using MultiShop.ShopFramework; using MultiShop.ShopFramework;
namespace MultiShop.SearchStructures namespace MultiShop.DataStructures
{ {
public class ProductListingInfo public class ProductListingInfo
{ {

View File

@ -2,7 +2,7 @@ using System;
using System.ComponentModel; using System.ComponentModel;
using MultiShop.ShopFramework; using MultiShop.ShopFramework;
namespace MultiShop.SearchStructures namespace MultiShop.DataStructures
{ {
public static class ResultCategoryExtensions public static class ResultCategoryExtensions
{ {

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace MultiShop.SearchStructures namespace MultiShop.DataStructures
{ {
public class ResultsProfile public class ResultsProfile
{ {

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using MultiShop.ShopFramework; using MultiShop.ShopFramework;
namespace MultiShop.SearchStructures namespace MultiShop.DataStructures
{ {
public class SearchProfile public class SearchProfile
{ {

View File

@ -2,12 +2,12 @@
@using Microsoft.Extensions.Configuration @using Microsoft.Extensions.Configuration
@using ShopFramework @using ShopFramework
@using SimpleLogger @using SimpleLogger
@using SearchStructures @using DataStructures
@inject HttpClient Http @inject HttpClient Http
@inject IConfiguration Configuration @inject IConfiguration Configuration
@inject IJSRuntime js @inject IJSRuntime js
@* TODO: Finish sorting, move things to individual components where possible, key search results. *@ @* TODO: Add buttons for the order changing. Add main page. *@
<div class="my-2"> <div class="my-2">
<div class="input-group my-2"> <div class="input-group my-2">
@ -178,7 +178,28 @@
</div> </div>
<div class="my-3 py-2"> <div class="my-3 py-2">
<div class="d-flex flex-wrap justify-content-between" style="width: 100%; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: lightgray;"> <div class="d-inline-flex" style="width: 100%; border-bottom-style: solid; border-bottom-width: 1px; border-color: lightgray;">
<button type="button" class=@ToggleResultsConfigurationcss @onclick="@(() => showResultsConfiguration = !showResultsConfiguration)"><span class="oi oi-sort-descending"></span></button>
</div>
@if (showResultsConfiguration)
{
<div style="border-color: lightgray;" class="p-1">
<div class="card m-2" style="max-width: 23em;">
<div class="card-body">
<h5 class="card-title">Results Order</h5>
<h6 class="card-subtitle mb-2 text-muted">What's important to you?</h6>
<p class="card-text">The results will be sorted by the top category. If the compared results are equal or don't have a value for that category, the next category on the list will be used and so on.</p>
<DragAndDropList Items="@(activeResultsProfile.Order)" Context="item" AdditionalListClasses="mx-auto" OnOrderChange="@(async () => await Organize(activeResultsProfile.Order))">
<DraggableItem>
@(item.FriendlyName())
</DraggableItem>
</DragAndDropList>
</div>
</div>
</div>
}
<div class="d-flex flex-wrap" style="width: 100%; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: lightgray;">
<div class="align-self-end"> <div class="align-self-end">
@if (searching) @if (searching)
{ {
@ -220,19 +241,6 @@
<span class="text-muted">Search for something to see the results!</span> <span class="text-muted">Search for something to see the results!</span>
} }
</div> </div>
<CustomDropdown AdditionalButtonClasses="btn-outline-secondary btn-tab" Justify="right">
<ButtonContent>
<span class="oi oi-sort-descending"></span>
</ButtonContent>
<DropdownContent>
<DragAndDropList Items="@(activeResultsProfile.Order)" Context="item" AdditionalListClasses="list-group-empty-top-left" OnOrderChange="@(async () => await Organize(activeResultsProfile.Order))">
<DraggableItem>
@(item.FriendlyName())
</DraggableItem>
</DragAndDropList>
</DropdownContent>
</CustomDropdown>
</div> </div>
<div> <div>
<ListingTableView Products="@listings" /> <ListingTableView Products="@listings" />
@ -251,11 +259,17 @@
private ResultsProfile activeResultsProfile = new ResultsProfile(); private ResultsProfile activeResultsProfile = new ResultsProfile();
private bool showSearchConfiguration = false; private bool showSearchConfiguration = false;
private bool showResultsConfiguration = false;
private string ToggleSearchConfigButtonCss private string ToggleSearchConfigButtonCss
{ {
get => "btn btn-outline-secondary" + (showSearchConfiguration ? " active" : ""); get => "btn btn-outline-secondary" + (showSearchConfiguration ? " active" : "");
} }
private string ToggleResultsConfigurationcss {
get => "btn btn-outline-secondary btn-tab" + (showResultsConfiguration ? " active" : "");
}
private bool searched = false; private bool searched = false;
private bool searching = false; private bool searching = false;
private bool organizing = false; private bool organizing = false;
@ -306,7 +320,8 @@
await foreach (ProductListing listing in Shops[shopName]) await foreach (ProductListing listing in Shops[shopName])
{ {
resultsChecked += 1; resultsChecked += 1;
if (resultsChecked % 50 == 0) { if (resultsChecked % 50 == 0)
{
StateHasChanged(); StateHasChanged();
await Task.Yield(); await Task.Yield();
} }
@ -373,7 +388,8 @@
organizing = true; organizing = true;
StateHasChanged(); StateHasChanged();
List<ProductListingInfo> sortedResults = await Task.Run<List<ProductListingInfo>>(() => { List<ProductListingInfo> sortedResults = await Task.Run<List<ProductListingInfo>>(() =>
{
List<ProductListingInfo> sorted = new List<ProductListingInfo>(listings); List<ProductListingInfo> sorted = new List<ProductListingInfo>(listings);
sorted.Sort((a, b) => sorted.Sort((a, b) =>
{ {

View File

@ -1,45 +0,0 @@
@inject IJSRuntime JS
<div style="position: relative;" @ref="dropdown">
<button type="button" class=@ButtonCss>@ButtonContent</button>
<div class="invisible" style="position: absolute;" tabindex="0">
@DropdownContent
</div>
</div>
@code {
[Parameter]
public RenderFragment ButtonContent { get; set; }
[Parameter]
public RenderFragment DropdownContent { get; set; }
[Parameter]
public string AdditionalButtonClasses { get; set; }
[Parameter]
public string Justify { get; set; }
private ElementReference dropdown;
private string ButtonCss
{
get => "btn " + AdditionalButtonClasses;
}
protected override async Task OnParametersSetAsync()
{
AdditionalButtonClasses = AdditionalButtonClasses ?? "";
Justify = Justify ?? "center";
await base.OnParametersSetAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JS.InvokeVoidAsync("customDropdown", dropdown, Justify);
}
await base.OnAfterRenderAsync(firstRender);
}
}

View File

@ -5,9 +5,16 @@
<ul class=@ListGroupCss style="width: max-content;" @ref="dragAndDrop"> <ul class=@ListGroupCss style="width: max-content;" @ref="dragAndDrop">
@foreach (TItem item in Items) @foreach (TItem item in Items)
{ {
<li class="list-group-item list-group-item-hover" draggable="true" @ondragstart="@(() => itemDraggedIndex = Items.IndexOf(item))" @ondrop="@(async () => await OnDrop(item))"> <li class="list-group-item" draggable=@((!processingDropChange).ToString()) @ondragstart="@(() => itemDraggedIndex = Items.IndexOf(item))" @ondrop="@(async () => await OnDrop(item))">
<span class="mx-1 oi oi-elevator"></span> <div class="d-inline-flex">
<div class="mr-3">
<button class="btn" type="button" style="padding: 0px;" @onclick="@(() => OnButtonClickMove(Items.IndexOf(item), true))" disabled="@(processingDropChange || Items.IndexOf(item) <= 0)"><span class="oi oi-caret-top"></span></button>
<button class="btn" type="button" style="padding: 0px;" @onclick="@(() => OnButtonClickMove(Items.IndexOf(item), false))" disabled="@(processingDropChange || Items.IndexOf(item) >= Items.Count - 1)"><span class="oi oi-caret-bottom"></span></button>
</div>
<div>
@DraggableItem(item) @DraggableItem(item)
</div>
</div>
</li> </li>
} }
</ul> </ul>
@ -29,6 +36,7 @@
private ElementReference dragAndDrop; private ElementReference dragAndDrop;
private int itemDraggedIndex = -1; private int itemDraggedIndex = -1;
private bool processingDropChange = false;
private string ListGroupCss private string ListGroupCss
@ -54,12 +62,28 @@
private async Task OnDrop(TItem dropped) private async Task OnDrop(TItem dropped)
{ {
TItem item = Items[itemDraggedIndex]; int dragIndex = itemDraggedIndex;
if (item.Equals(dropped)) return;
int indexOfDrop = Items.IndexOf(dropped);
Items.RemoveAt(itemDraggedIndex);
Items.Insert(indexOfDrop, item);
itemDraggedIndex = -1; itemDraggedIndex = -1;
await MoveOrder(dragIndex, Items.IndexOf(dropped));
}
private async Task OnButtonClickMove(int index, bool up) {
if (up) {
await MoveOrder(index, index - 1);
} else {
await MoveOrder(index, index + 1);
}
}
private async Task MoveOrder(int from, int to)
{
Logger.Log($"Attempting to move from {from} to {to}.", LogLevel.Debug);
if (from == to || from >= Items.Count || from < 0 || to > Items.Count || to < 0) return;
TItem item = Items[from];
Items.RemoveAt(from);
Items.Insert(to, item);
processingDropChange = true;
await OnOrderChange.InvokeAsync(); await OnOrderChange.InvokeAsync();
processingDropChange = false;
} }
} }

View File

@ -1,5 +1,4 @@
@using ShopFramework @using DataStructures
@using SearchStructures
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-top-borderless"> <table class="table table-top-borderless">

View File

@ -1,44 +1,3 @@
function customDropdown(elem, justify) {
let btn = elem.querySelector("button");
let dropdown = elem.querySelector("div");
if (justify.toLowerCase() == "left") {
dropdown.style.left = "0px";
} else if (justify.toLowerCase() == "center") {
dropdown.style.left = "50%";
} else if (justify.toLowerCase() == "right") {
dropdown.style.right = "0px";
}
let openFunc = () => {
btn.classList.add("active");
dropdown.classList.remove("invisible");
dropdown.focus();
}
let closeFunc = () => {
btn.classList.remove("active");
dropdown.classList.add("invisible");
}
btn.addEventListener("click", () => {
if (!btn.classList.contains("active")) {
openFunc();
} else {
closeFunc();
}
});
dropdown.addEventListener("focusout", (e) => {
if (e.relatedTarget != btn) {
closeFunc();
}
});
dropdown.addEventListener("keyup", (e) => {
if (e.code == "Escape") {
dropdown.blur();
}
});
}
function dragAndDropList(elem) { function dragAndDropList(elem) {
elem.addEventListener("dragover", (e) => { elem.addEventListener("dragover", (e) => {
e.preventDefault(); e.preventDefault();
@ -49,21 +8,16 @@ function dragAndDropList(elem) {
e.addEventListener("dragstart", () => { e.addEventListener("dragstart", () => {
itemDragged = e; itemDragged = e;
e.classList.add("list-group-item-secondary"); e.classList.add("list-group-item-secondary");
e.classList.remove("list-group-item-hover");
}); });
e.addEventListener("dragenter", () => { e.addEventListener("dragenter", () => {
e.classList.add("list-group-item-primary"); e.classList.add("list-group-item-primary");
e.classList.remove("list-group-item-hover");
}); });
e.addEventListener("dragleave", () => { e.addEventListener("dragleave", () => {
e.classList.remove("list-group-item-primary"); e.classList.remove("list-group-item-primary");
e.classList.add("list-group-item-hover");
}); });
e.addEventListener("drop", () => { e.addEventListener("drop", () => {
e.classList.add("list-group-item-hover");
e.classList.remove("list-group-item-primary"); e.classList.remove("list-group-item-primary");
itemDragged.classList.remove("list-group-item-secondary"); itemDragged.classList.remove("list-group-item-secondary");
itemDragged.classList.add("list-group-item-hover");
}); });
} }
} }