Skip to content

Commit

Permalink
Added drag functionality to update precendence for sort condition
Browse files Browse the repository at this point in the history
  • Loading branch information
Aniket Singh Rawat committed Nov 20, 2023
1 parent cf92053 commit 4da7831
Showing 1 changed file with 212 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script lang="ts">
import type { Writable } from 'svelte/store';
import { flip } from 'svelte/animate';
import { Icon, Button } from '@mathesar-component-library';
import {
getTabularDataStoreFromContext,
type Sorting,
Sorting,
} from '@mathesar/stores/table-data';
import { iconAddNew } from '@mathesar/icons';
import SortEntry from '@mathesar/components/sort-entry/SortEntry.svelte';
Expand Down Expand Up @@ -47,29 +48,185 @@
return newSort.with(newColumnId, sortDirection);
});
}
// Functionality for making sort entries draggable.
let sortEntries: any[];

Check warning on line 54 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

Unexpected any. Specify a different type
$: {
sortEntries = [...$sorting];
}
let sortContainer: HTMLDivElement;
let topPosition = 0;
let isDragging = false;
let dragSortEntry: HTMLElement;
let selectedSortEntry = -1;
let currentSlotIndex = -1;
function handleSortPointerDown(event: PointerEvent) {
if (selectedSortEntry != -1) {

Check failure on line 66 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

Expected '!==' and instead saw '!='
isDragging = true;
const containerRect = sortContainer.getBoundingClientRect();
const sortEntryRect = dragSortEntry.getBoundingClientRect();
// Calculate the new top position of the box within the container
topPosition = Math.max(
0,
Math.min(
containerRect.height - sortEntryRect.height,
event.clientY - containerRect.top - sortEntryRect.height / 2,
),
);
if (selectedSortEntry >= 0) {
// Initally the selectedSortEntry would be at it's slot.
currentSlotIndex = selectedSortEntry;
dragSortEntry.style.top = `${topPosition}px`;
dragSortEntry.style.width = `${containerRect.width}px`;
}
}
// Attach events to the body for global pointer move and up events
document.body.addEventListener('pointermove', handleSortPointerMove);

Check failure on line 89 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

'handleSortPointerMove' was used before it was defined
document.body.addEventListener('pointerup', handleSortPointerUp);

Check failure on line 90 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

'handleSortPointerUp' was used before it was defined
}
function handleSortPointerMove(event: PointerEvent) {
if (isDragging) {
const containerRect = sortContainer.getBoundingClientRect();
const sortEntryRect = dragSortEntry.getBoundingClientRect();
// Calculate the new top position of the box within the container
topPosition = Math.max(
0,
Math.min(
containerRect.height - sortEntryRect.height,
event.clientY - containerRect.top - sortEntryRect.height / 2,
),
);
// Get the slot on which the selected entry is hovering.
let slotHeight = sortEntryRect.height;

Check failure on line 108 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

'slotHeight' is never reassigned. Use 'const' instead
const nearestSlot = Math.round(topPosition / slotHeight) * slotHeight;
currentSlotIndex = Math.round(nearestSlot / slotHeight);
// Replace the Sort Entries
if (selectedSortEntry != currentSlotIndex) {

Check failure on line 113 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

Expected '!==' and instead saw '!='
move(selectedSortEntry, currentSlotIndex);

Check failure on line 114 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

'move' was used before it was defined
selectedSortEntry = currentSlotIndex;
}
// Update the styles directly within the function
if (selectedSortEntry >= 0) {
dragSortEntry.style.top = `${topPosition}px`;
dragSortEntry.style.width = `${containerRect.width}px`;
}
}
}
function handleSortPointerUp(event: PointerEvent) {

Check warning on line 125 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

'event' is defined but never used
if (isDragging) {
isDragging = false;
// Do not update if sortentries are unchanged
if (!arraysEqual(sortEntries, [...$sorting])) {

Check failure on line 130 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

'arraysEqual' was used before it was defined
// Update the new sort order in sorting store
sorting.update((s: Sorting) => {

Check warning on line 132 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

's' is defined but never used
let newSort = new Sorting(sortEntries);

Check failure on line 133 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

'newSort' is never reassigned. Use 'const' instead
return newSort;
});
}
// Detach the pointer move and up events
document.body.removeEventListener('pointermove', handleSortPointerMove);
document.body.removeEventListener('pointerup', handleSortPointerUp);
}
selectedSortEntry = -1;
currentSlotIndex = -1;
}
function move(i: number, j: number) {
let t = sortEntries[i];

Check failure on line 148 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

't' is never reassigned. Use 'const' instead
sortEntries[i] = sortEntries[j];
sortEntries[j] = t;
sortEntries = [...sortEntries];
}
function arraysEqual(a1: any[], a2: any[]) {

Check warning on line 153 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

Unexpected any. Specify a different type

Check warning on line 153 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

Unexpected any. Specify a different type
/* WARNING: arrays must not contain {objects} or behavior may be undefined */
return JSON.stringify(a1) == JSON.stringify(a2);

Check failure on line 155 in mathesar_ui/src/systems/table-view/actions-pane/record-operations/sort/Sort.svelte

View workflow job for this annotation

GitHub Actions / Run front end linter

Expected '===' and instead saw '=='
}
</script>

<div class="sorters">
<div class="header">Sort</div>
<div class="content">
{#each [...$sorting] as [columnId, sortDirection], index (columnId)}
<SortEntry
columns={$processedColumns}
columnsAllowedForSelection={availableColumnIds}
getColumnLabel={(processedColumn) => processedColumn?.column.name ?? ''}
getColumnConstraintType={(column) =>
getColumnConstraintTypeByColumnId(column.id, $processedColumns)}
columnIdentifier={columnId}
{sortDirection}
on:remove={() => removeSortColumn(columnId)}
disableColumnChange={index < $sorting.size - 1}
on:update={(e) =>
updateSortEntry(
columnId,
e.detail.columnIdentifier,
e.detail.sortDirection,
)}
/>

<div
class="content sort-container"
bind:this={sortContainer}
on:pointerdown={handleSortPointerDown}
on:pointermove={handleSortPointerMove}
on:pointerup={handleSortPointerUp}
>
{#if selectedSortEntry != -1}
<div bind:this={dragSortEntry} class="sort-entry selected-sort-entry">
<div class="grab grab-selected">
<svg
xmlns="http://www.w3.org/2000/svg"
height="1em"
viewBox="0 0 448 512"
><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path
d="M128 136c0-22.1-17.9-40-40-40L40 96C17.9 96 0 113.9 0 136l0 48c0 22.1 17.9 40 40 40H88c22.1 0 40-17.9 40-40l0-48zm0 192c0-22.1-17.9-40-40-40H40c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40H88c22.1 0 40-17.9 40-40V328zm32-192v48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V136c0-22.1-17.9-40-40-40l-48 0c-22.1 0-40 17.9-40 40zM288 328c0-22.1-17.9-40-40-40H200c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V328zm32-192v48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V136c0-22.1-17.9-40-40-40l-48 0c-22.1 0-40 17.9-40 40zM448 328c0-22.1-17.9-40-40-40H360c-22.1 0-40 17.9-40 40v48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V328z"
/></svg
>
</div>
<SortEntry
columns={$processedColumns}
columnsAllowedForSelection={availableColumnIds}
getColumnLabel={(processedColumn) =>
processedColumn?.column.name ?? ''}
getColumnConstraintType={(column) =>
getColumnConstraintTypeByColumnId(column.id, $processedColumns)}
columnIdentifier={sortEntries[selectedSortEntry][0]}
sortDirection={sortEntries[selectedSortEntry][1]}
on:remove={() => removeSortColumn(sortEntries[selectedSortEntry][0])}
disableColumnChange={false}
/>
</div>
{/if}
{#each sortEntries as [columnId, sortDirection], index (columnId)}
<div
class="sort-entry"
animate:flip={{ delay: 0, duration: 250 }}
class:ghost-entry={selectedSortEntry == index}
>
<div class="grab" on:pointerdown={() => (selectedSortEntry = index)}>
<svg
xmlns="http://www.w3.org/2000/svg"
height="1em"
viewBox="0 0 448 512"
><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path
d="M128 136c0-22.1-17.9-40-40-40L40 96C17.9 96 0 113.9 0 136l0 48c0 22.1 17.9 40 40 40H88c22.1 0 40-17.9 40-40l0-48zm0 192c0-22.1-17.9-40-40-40H40c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40H88c22.1 0 40-17.9 40-40V328zm32-192v48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V136c0-22.1-17.9-40-40-40l-48 0c-22.1 0-40 17.9-40 40zM288 328c0-22.1-17.9-40-40-40H200c-22.1 0-40 17.9-40 40l0 48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V328zm32-192v48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V136c0-22.1-17.9-40-40-40l-48 0c-22.1 0-40 17.9-40 40zM448 328c0-22.1-17.9-40-40-40H360c-22.1 0-40 17.9-40 40v48c0 22.1 17.9 40 40 40h48c22.1 0 40-17.9 40-40V328z"
/></svg
>
</div>
<SortEntry
columns={$processedColumns}
columnsAllowedForSelection={availableColumnIds}
getColumnLabel={(processedColumn) =>
processedColumn?.column.name ?? ''}
getColumnConstraintType={(column) =>
getColumnConstraintTypeByColumnId(column.id, $processedColumns)}
columnIdentifier={columnId}
{sortDirection}
on:remove={() => removeSortColumn(columnId)}
disableColumnChange={false}
on:update={(e) =>
updateSortEntry(
columnId,
e.detail.columnIdentifier,
e.detail.sortDirection,
)}
/>
</div>
{:else}
<span>No sorting condition has been added</span>
{/each}
Expand All @@ -85,6 +242,41 @@
</div>

<style lang="scss">
.grab {
margin-right: 5px;
cursor: grab;
}
.grab-selected {
background-color: white;
cursor: grabbing;
}
.sort-container {
position: relative;
user-select: none;
}
.sort-entry {
display: flex;
flex-direction: row;
align-items: center;
position: relative;
padding: 5px 0 5px 0;
}
.ghost-entry {
visibility: hidden;
}
.selected-sort-entry {
position: absolute;
background-color: transparent;
z-index: 2000;
width: 100%;
top: 30;
}
.sorters {
padding: 1rem;
display: flex;
Expand All @@ -106,10 +298,6 @@
:global(.select-sort-column) {
flex-grow: 1;
}
> :global(* + *) {
margin-top: 0.5rem;
}
}
.header {
Expand Down

0 comments on commit 4da7831

Please sign in to comment.