-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #490 from appwrite/filtering
Filtering
- Loading branch information
Showing
13 changed files
with
484 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
189 changes: 189 additions & 0 deletions
189
...-[project]/databases/database-[database]/collection-[collection]/(filters)/content.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
<script lang="ts"> | ||
import { Button, InputNumber } from '$lib/elements/forms'; | ||
import InputSelect from '$lib/elements/forms/inputSelect.svelte'; | ||
import InputText from '$lib/elements/forms/inputText.svelte'; | ||
import { Query } from '@appwrite.io/console'; | ||
import { createEventDispatcher } from 'svelte'; | ||
import { columns } from '../store'; | ||
import { tags, type Column, type Operator, queries } from './store'; | ||
const dispatch = createEventDispatcher<{ | ||
clear: void; | ||
apply: { applied: number }; | ||
}>(); | ||
let columnId: string | null = null; | ||
$: column = $columns.find((c) => c.id === columnId) as Column; | ||
dispatch('apply', { applied: $tags.length }); | ||
const operators: Record<string, Operator> = { | ||
'starts with': { | ||
toQuery: Query.startsWith, | ||
toTag: (attribute, input) => `**${attribute}** starts with **${input}**`, | ||
types: ['string'] | ||
}, | ||
'ends with': { | ||
toQuery: Query.endsWith, | ||
toTag: (attribute, input) => `**${attribute}** ends with **${input}**`, | ||
types: ['string'] | ||
}, | ||
'greater than': { | ||
toQuery: (attr, input) => Query.greaterThan(attr, Number(input)), | ||
toTag: (attribute, input) => `**${attribute}** greater than **${input}**`, | ||
types: ['integer', 'double'] | ||
}, | ||
'greater than or equal to': { | ||
toQuery: (attr, input) => Query.greaterThanEqual(attr, Number(input)), | ||
toTag: (attribute, input) => `**${attribute}** greater than or equal to **${input}**`, | ||
types: ['integer', 'double'] | ||
}, | ||
'less than': { | ||
toQuery: Query.lessThan, | ||
toTag: (attribute, input) => `**${attribute}** less than **${input}**`, | ||
types: ['integer', 'double'] | ||
}, | ||
'less than or equal to': { | ||
toQuery: Query.lessThanEqual, | ||
toTag: (attribute, input) => `**${attribute}** less than or equal to **${input}**`, | ||
types: ['integer', 'double'] | ||
}, | ||
equal: { | ||
toQuery: Query.equal, | ||
toTag: (attribute, input) => `**${attribute}** equal to **${input}**`, | ||
types: ['string', 'integer', 'double'] | ||
}, | ||
'not null': { | ||
toQuery: Query.isNotNull, | ||
toTag: (attribute) => `**${attribute}** is not null`, | ||
types: ['string', 'integer', 'double', 'boolean', 'datetime', 'relationship'], | ||
hideInput: true | ||
}, | ||
null: { | ||
toQuery: Query.isNull, | ||
toTag: (attribute) => `**${attribute}** is null`, | ||
types: ['string', 'integer', 'double', 'boolean', 'datetime', 'relationship'], | ||
hideInput: true | ||
} | ||
}; | ||
$: operatorsForColumn = Object.entries(operators) | ||
.filter(([_, v]) => v.types.includes(column?.type)) | ||
.map(([k]) => ({ | ||
label: k, | ||
value: k | ||
})); | ||
let operatorKey: string | null = null; | ||
$: operator = operatorKey ? operators[operatorKey] : null; | ||
$: { | ||
columnId; | ||
operatorKey = null; | ||
} | ||
// We cast to any to not cause type errors in the input components | ||
let value: any = null; | ||
$: { | ||
columnId; | ||
value = null; | ||
} | ||
// This Map is keyed by tags, and has a query as the value | ||
function addFilter() { | ||
if (column && operator) { | ||
queries.addFilter({ column, operator, value }); | ||
value = null; | ||
} | ||
} | ||
function tagFormat(node: HTMLElement) { | ||
node.innerHTML = node.innerHTML.replace(/\*\*(.*?)\*\*/g, '<b>$1</b>'); | ||
} | ||
$: isDisabled = (function getDisabled() { | ||
return !operator || (!operator?.hideInput && !value); | ||
})(); | ||
</script> | ||
|
||
<div> | ||
<form on:submit|preventDefault={addFilter}> | ||
<div class="selects u-flex u-gap-12 u-margin-block-start-16"> | ||
<InputSelect | ||
id="column" | ||
options={$columns.map((c) => ({ | ||
label: c.title, | ||
value: c.id | ||
}))} | ||
placeholder="Select column" | ||
bind:value={columnId} /> | ||
<InputSelect | ||
id="operator" | ||
disabled={!column} | ||
options={operatorsForColumn} | ||
placeholder="Select operator" | ||
bind:value={operatorKey} /> | ||
</div> | ||
{#if column && operator && !operator?.hideInput} | ||
<div class="u-margin-block-start-16"> | ||
{#if column.type === 'integer' || column.type === 'double'} | ||
<InputNumber id="value" bind:value placeholder="Enter value" /> | ||
{:else} | ||
<InputText id="value" bind:value placeholder="Enter value" /> | ||
{/if} | ||
</div> | ||
{/if} | ||
<Button text disabled={isDisabled} class="u-margin-block-start-12" submit> | ||
<i class="icon-plus" /> | ||
Add filter | ||
</Button> | ||
</form> | ||
|
||
<ul class="u-flex u-flex-wrap u-cross-center u-gap-8 u-margin-block-start-16 tags"> | ||
{#each $tags as tag (tag)} | ||
<button | ||
class="tag" | ||
on:click={() => { | ||
queries.removeFilter(tag); | ||
}}> | ||
<span class="text" use:tagFormat> | ||
{tag} | ||
</span> | ||
<i class="icon-x" /> | ||
</button> | ||
{/each} | ||
</ul> | ||
</div> | ||
|
||
<style lang="scss"> | ||
.dropped { | ||
border-radius: 0.5rem; | ||
box-shadow: 0px 16px 32px 0px rgba(55, 59, 77, 0.04); | ||
padding: 1rem; | ||
margin-top: 0.5rem; | ||
width: 37.5rem; | ||
} | ||
.selects { | ||
:global(> *) { | ||
flex: 1; | ||
} | ||
} | ||
.tags { | ||
:global(b) { | ||
font-weight: bold; | ||
} | ||
} | ||
hr { | ||
height: 1px; | ||
width: calc(100% + 2rem); | ||
background-color: hsl(var(--color-border)); | ||
margin-block-start: 1rem; | ||
margin-inline: -1rem; | ||
} | ||
</style> |
Oops, something went wrong.