From d3756863f952bafe5bef5afac8bc4f57e9b7144e Mon Sep 17 00:00:00 2001 From: Arman Date: Thu, 13 Mar 2025 17:05:26 +0100 Subject: [PATCH] WIP: fixes to tags --- .../bottom-sheet/SheetMenuBlock.svelte | 6 +- .../bottom-sheet/bottomSheetMenu.svelte | 7 +- src/lib/components/bottom-sheet/index.ts | 1 + src/lib/components/filters/content.svelte | 53 ++--- .../components/filters/customFilters.svelte | 5 +- .../components/filters/filtersModal.svelte | 197 ++++++++++++++---- .../components/filters/quickFilters.svelte | 82 +++++++- src/lib/components/filters/setFilters.ts | 6 +- src/lib/components/filters/store.ts | 42 ++-- src/lib/components/filters/tagList.svelte | 43 ++-- src/lib/components/menu/menu.svelte | 2 +- 11 files changed, 320 insertions(+), 124 deletions(-) diff --git a/src/lib/components/bottom-sheet/SheetMenuBlock.svelte b/src/lib/components/bottom-sheet/SheetMenuBlock.svelte index 8a408eeb7..2a54fcc35 100644 --- a/src/lib/components/bottom-sheet/SheetMenuBlock.svelte +++ b/src/lib/components/bottom-sheet/SheetMenuBlock.svelte @@ -7,7 +7,7 @@ export let navigateSubMenu: (menu: SheetMenu) => void; -{#if menu.title} +{#if menu?.title} {menu.title} {/if} @@ -33,7 +33,9 @@ navigateSubMenu(menuItem.subMenu); } else if (menuItem.onClick !== undefined) { menuItem.onClick(); - isOpen = false; + if (menuItem.closeOnClick !== false) { + isOpen = false; + } } }}> {menuItem.name} diff --git a/src/lib/components/bottom-sheet/bottomSheetMenu.svelte b/src/lib/components/bottom-sheet/bottomSheetMenu.svelte index 8934de273..a9a7bdd57 100644 --- a/src/lib/components/bottom-sheet/bottomSheetMenu.svelte +++ b/src/lib/components/bottom-sheet/bottomSheetMenu.svelte @@ -40,11 +40,14 @@ -
+
+ +
{#if activeMenu.bottom}{/if} + bind:isOpen /> + {/if}
diff --git a/src/lib/components/bottom-sheet/index.ts b/src/lib/components/bottom-sheet/index.ts index 80cb607e4..a2a266a60 100644 --- a/src/lib/components/bottom-sheet/index.ts +++ b/src/lib/components/bottom-sheet/index.ts @@ -19,6 +19,7 @@ type MenuItem = { trailingIcon?: ComponentType; onClick?: () => void; href?: string; + closeOnClick?: boolean; subMenu?: { top: SubMenu; bottom: SubMenu }; }; diff --git a/src/lib/components/filters/content.svelte b/src/lib/components/filters/content.svelte index fc5aec366..c9f77e498 100644 --- a/src/lib/components/filters/content.svelte +++ b/src/lib/components/filters/content.svelte @@ -5,12 +5,11 @@ InputSelect, InputText, InputTags, - FormList, InputSelectCheckbox, InputDateTime } from '$lib/elements/forms'; import { createEventDispatcher, onMount } from 'svelte'; - import { tags, operators, addFilter, queries } from './store'; + import { operators, addFilter, queries, type TagValue } from './store'; import type { Column } from '$lib/helpers/types'; import type { Writable } from 'svelte/store'; import { TagList } from '.'; @@ -43,6 +42,8 @@ $: isDisabled = !operator; + let localTags: TagValue[] = []; + onMount(() => { value = column?.array ? [] : null; if (column?.type === 'datetime') { @@ -66,7 +67,7 @@ clear: void; apply: { applied: number }; }>(); - dispatch('apply', { applied: $tags.length }); + dispatch('apply', { applied: localTags.length });
@@ -91,27 +92,24 @@ {#if column && operator && !operator?.hideInput} {#if column?.array} - - {#if column.format === 'enum'} - ({ - label: e?.label ?? e, - value: e?.value ?? e, - checked: arrayValues.includes(e?.value ?? e) - }))}> - - {:else} - - {/if} - + {#if column.format === 'enum'} + ({ + label: e?.label ?? e, + value: e?.value ?? e, + checked: arrayValues.includes(e?.value ?? e) + }))}> + + {:else} + + {/if} {:else}
    {#if column.format === 'enum'} @@ -155,7 +153,12 @@ {#if !singleCondition}
      - + { + queries.removeFilter(e.detail); + queries.apply(); + }} />
    {/if}
diff --git a/src/lib/components/filters/customFilters.svelte b/src/lib/components/filters/customFilters.svelte index 3b4a1d751..09ff475fb 100644 --- a/src/lib/components/filters/customFilters.svelte +++ b/src/lib/components/filters/customFilters.svelte @@ -9,7 +9,10 @@ - (show = true)}>Custom filters + { + show = true; + }}>Custom filters {#if show} diff --git a/src/lib/components/filters/filtersModal.svelte b/src/lib/components/filters/filtersModal.svelte index 816187d28..a25291de0 100644 --- a/src/lib/components/filters/filtersModal.svelte +++ b/src/lib/components/filters/filtersModal.svelte @@ -1,11 +1,21 @@ Apply filter rules to refine the table view - (applied = 0)} /> + + + c.filter !== false) + .map((c) => ({ + label: c.title, + value: c.id + }))} + placeholder="Select column" + bind:value={selectedColumn} /> + + + {#if column && operatorKey} + {#if column?.array} + {#if column.format === 'enum'} + ({ + label: e?.label ?? e, + value: e?.value ?? e, + checked: arrayValues.includes(e?.value ?? e) + }))}> + + {:else} + + {/if} + {:else if column.format === 'enum'} + ({ + label: e?.label ?? e, + value: e?.value ?? e + }))} /> + {:else if column.type === 'integer' || column.type === 'double'} + + {:else if column.type === 'boolean'} + + {:else if column.type === 'datetime'} + {#key value} + + {/key} + {:else} + + {/if} + {/if} +
+ +
+
+ {#if localTags?.length} + + removeCondition(e.detail)} /> + + {/if} + - - + {#if localTags?.length} + + {:else} + + {/if} +
diff --git a/src/lib/components/filters/quickFilters.svelte b/src/lib/components/filters/quickFilters.svelte index d57939731..a0e51d9b0 100644 --- a/src/lib/components/filters/quickFilters.svelte +++ b/src/lib/components/filters/quickFilters.svelte @@ -5,16 +5,24 @@ import { type Writable } from 'svelte/store'; import { CustomFilters } from '$lib/components/filters'; import { addFilterAndApply, buildFilterCol } from './quickFilters'; - import { parsedTags, setFiltersOnNavigate } from './setFilters'; + import { parsedTags, setFilters } from './setFilters'; import Menu from '../menu/menu.svelte'; import { Button } from '$lib/elements/forms'; import { Icon } from '@appwrite.io/pink-svelte'; - import { IconFilterLine } from '@appwrite.io/pink-icons-svelte'; + import { + IconChevronLeft, + IconChevronRight, + IconFilterLine + } from '@appwrite.io/pink-icons-svelte'; import QuickfiltersSubMenu from './quickfiltersSubMenu.svelte'; + import { isSmallViewport } from '$lib/stores/viewport'; + import { BottomSheet } from '..'; + import { capitalize } from '$lib/helpers/string'; export let columns: Writable; export let analyticsSource: string; + let openBottomSheet = false; let filterCols = $columns .map((col) => (col.filter !== false ? buildFilterCol(col) : null)) .filter((f) => f?.options); @@ -23,20 +31,78 @@ const paramQueries = p.to.url.searchParams.get('query'); const localQueries = queryParamToMap(paramQueries || '[]'); const localTags = Array.from(localQueries.keys()); - - setFiltersOnNavigate(localTags, filterCols, $columns); + console.log(paramQueries, localQueries, localTags); + setFilters(localTags, filterCols, $columns); filterCols = filterCols; }); + + const subSheets = filterCols.map((col) => { + return { + title: col.title, + top: { + title: col.title, + trailingIcon: IconChevronRight, + items: col.options.map((o) => { + return { + title: capitalize(o.label), + name: capitalize(o.label), + closeOnClick: false, + onClick: () => { + addFilterAndApply( + col.id, + col.title, + col.operator, + o.value, + col.array ? [o.value] : [], + $columns, + analyticsSource + ); + } + }; + }) + }, + bottom: { + name: 'Back', + items: [ + { + name: 'Back', + leadingIcon: IconChevronLeft, + onClick: () => { + // navigate to the previous menu + } + } + ] + } + }; + }); + + $: organizationsBottomSheet = { + top: { + title: 'Filters', + items: filterCols.map((col) => { + return { + name: col.title, + onClick: () => + console.log(subSheets.find((sheet) => sheet?.title === col?.title)), + subMenu: subSheets.find((sheet) => sheet?.title === col?.title), + trailingIcon: IconChevronRight + }; + }) + } + }; {#if $parsedTags?.length} - {:else} - @@ -81,3 +147,7 @@ + + diff --git a/src/lib/components/filters/setFilters.ts b/src/lib/components/filters/setFilters.ts index cea0ba2ba..3d3f60ac7 100644 --- a/src/lib/components/filters/setFilters.ts +++ b/src/lib/components/filters/setFilters.ts @@ -5,11 +5,7 @@ import { tags, type TagValue } from './store'; export const parsedTags = writable([]); -export function setFiltersOnNavigate( - localTags: TagValue[], - filterCols: FilterData[], - $columns: Column[] -) { +export function setFilters(localTags: TagValue[], filterCols: FilterData[], $columns: Column[]) { if (!localTags?.length) { filterCols.forEach((filter) => { resetOptions(filter); diff --git a/src/lib/components/filters/store.ts b/src/lib/components/filters/store.ts index bf8400910..6be45f6a0 100644 --- a/src/lib/components/filters/store.ts +++ b/src/lib/components/filters/store.ts @@ -244,30 +244,13 @@ function formatArray(array: string[]) { } } -function generateDefaultOperators() { +export function generateDefaultOperators() { const operators: Record = {}; operatorsDefault.forEach((operator, operatorName) => { operators[operatorName] = { toQuery: operator.query, toTag: (attribute, input = null, type = null) => { - if (input === null) { - return { - value: '', - tag: `**${attribute}** ${operatorName}` - }; - } else if (Array.isArray(input) && input.length > 2) { - return { - value: input, - tag: `**${attribute}** ${operatorName} **${formatArray(input)}** ` - }; - } else if (type === ValidTypes.Datetime) { - return { - value: input, - tag: `**${attribute}** ${operatorName} **${toLocaleDateTime(input.toString())}**` - }; - } else { - return { value: input, tag: `**${attribute}** ${operatorName} **${input}**` }; - } + return generateTag(attribute, operatorName, input, type); }, types: operator.types, hideInput: operator.hideInput @@ -276,6 +259,27 @@ function generateDefaultOperators() { return operators; } +export function generateTag(attribute: string, operatorName: string, input = null, type = null) { + if (input === null) { + return { + value: '', + tag: `**${attribute}** ${operatorName}` + }; + } else if (Array.isArray(input) && input.length > 2) { + return { + value: input, + tag: `**${attribute}** ${operatorName} **${formatArray(input)}** ` + }; + } else if (type === ValidTypes.Datetime) { + return { + value: input, + tag: `**${attribute}** ${operatorName} **${toLocaleDateTime(input.toString())}**` + }; + } else { + return { value: input, tag: `**${attribute}** ${operatorName} **${input}**` }; + } +} + export const operators = generateDefaultOperators(); export function tagFormat(node: HTMLElement) { diff --git a/src/lib/components/filters/tagList.svelte b/src/lib/components/filters/tagList.svelte index 6e7f2a5d5..33389514b 100644 --- a/src/lib/components/filters/tagList.svelte +++ b/src/lib/components/filters/tagList.svelte @@ -1,22 +1,29 @@ -{#each $tags as tag (tag)} - - - {tag?.value?.toString()} - +{#each tags as tag (tag)} + + + { + dispatch('remove', tag); + }}> + {#key tag.tag} + {tag.tag} + {/key} + + + {tag?.value?.toString()} + + {/each} diff --git a/src/lib/components/menu/menu.svelte b/src/lib/components/menu/menu.svelte index 28e674e9e..9f3c89060 100644 --- a/src/lib/components/menu/menu.svelte +++ b/src/lib/components/menu/menu.svelte @@ -31,7 +31,7 @@ {#if $$slots.end}
- + {/if}