Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeywordList search attribute support #2420

Merged
merged 9 commits into from
Nov 20, 2024
12 changes: 10 additions & 2 deletions src/lib/components/schedule/schedule-search-attributes.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import Accordion from '$lib/holocene/accordion/accordion.svelte';
import { translate } from '$lib/i18n/translate';
import type { SearchAttribute } from '$lib/types';
import type { Payload, SearchAttribute } from '$lib/types';
import { decodePayloadAttributes } from '$lib/utilities/decode-payload';
import { pluralize } from '$lib/utilities/pluralize';
Expand All @@ -11,6 +11,13 @@
$: indexedFields =
decodedSearchAttributes?.searchAttributes.indexedFields ?? {};
$: searchAttributeCount = Object.keys(indexedFields).length;
const formatValue = (value: Payload) => {
laurakwhit marked this conversation as resolved.
Show resolved Hide resolved
if (Array.isArray(value)) {
return value.join(', ');
}
return value;
};
</script>

<Accordion
Expand All @@ -23,12 +30,13 @@
{#if searchAttributeCount}
<ul class="w-full">
{#each Object.entries(indexedFields) as [searchAttrName, searchAttrValue]}
{@const value = formatValue(searchAttrValue)}
<li
class="flex flex-wrap items-center gap-2 border-b py-2 last-of-type:border-b-0"
>
<span class="break-all">{searchAttrName}</span>
<span class="surface-subtle select-all rounded-sm p-1 leading-4"
>{searchAttrValue}</span
>{value}</span
>
</li>
{/each}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,7 @@

<div class="flex flex-wrap gap-2" class:pt-2={visibleFilters.length}>
{#each visibleFilters as workflowFilter, i (`${workflowFilter.attribute}-${i}`)}
{@const { attribute, type, value, conditional, customDate } =
workflowFilter}
{@const { attribute, value, conditional, customDate } = workflowFilter}
{#if attribute}
<div in:fade data-testid="{workflowFilter.attribute}-{i}">
<Chip
Expand Down Expand Up @@ -119,7 +118,7 @@
{#if isNullConditional(conditional)}
{conditional}
{value}
{:else if isDateTimeFilter({ attribute, type })}
{:else if isDateTimeFilter(workflowFilter)}
{#if customDate}
{formatDateTimeRange(value, $timeFormat, $relativeTime)}
{:else}
Expand All @@ -133,7 +132,7 @@
{isStartsWith(conditional)
? translate('common.starts-with').toLocaleLowerCase()
: conditional}
{isTextFilter({ attribute, type }) ? `"${value}"` : value}
{isTextFilter(workflowFilter) ? `"${value}"` : value}
{/if}
</span>
{/if}
Expand Down
34 changes: 18 additions & 16 deletions src/lib/components/search-attribute-filter/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
isBooleanFilter,
isDateTimeFilter,
isDurationFilter,
isListFilter,
isNumberFilter,
isStatusFilter,
isTextFilter,
Expand All @@ -45,6 +46,7 @@
import DateTimeFilter from './datetime-filter.svelte';
import DurationFilter from './duration-filter.svelte';
import FilterList from './filter-list.svelte';
import ListFilter from './list-filter.svelte';
import NumberFilter from './number-filter.svelte';
import SearchAttributeMenu from './search-attribute-menu.svelte';
import StatusFilter from './status-filter.svelte';
Expand All @@ -59,9 +61,8 @@
const activeQueryIndex = writable<number>(null);
const focusedElementId = writable<string>('');

$: ({ attribute, type } = $filter);
$: searchParamQuery = $page.url.searchParams.get('query');
$: showClearAllButton = showFilter && filters.length && !attribute;
$: showClearAllButton = showFilter && filters.length && !$filter.attribute;

setContext<FilterContext>(FILTER_CONTEXT, {
filter,
Expand Down Expand Up @@ -105,7 +106,7 @@

function updateFocusedElementId() {
if ($activeQueryIndex !== null) {
$focusedElementId = getFocusedElementId({ attribute, type });
$focusedElementId = getFocusedElementId($filter);
}
}

Expand Down Expand Up @@ -134,7 +135,7 @@
}

function handleKeyUp(event: KeyboardEvent) {
if (event.key === 'Escape' && !isTextFilter({ attribute, type })) {
if (event.key === 'Escape' && !isTextFilter($filter)) {
resetFilter();
}
}
Expand All @@ -145,56 +146,57 @@
<slot />
{#if showFilter}
<div
class="flex items-center"
class="flex"
class:filter={!showClearAllButton}
on:keyup={handleKeyUp}
role="none"
>
{#if isStatusFilter(attribute)}
{#if isStatusFilter($filter)}
<StatusFilter bind:filters />
{:else}
<SearchAttributeMenu {filters} {options} />
{/if}

{#if attribute}
{#if isTextFilter({ attribute, type })}
{#if $filter.attribute}
{#if isTextFilter($filter)}
<div
class="flex w-full items-center"
in:fly={{ x: -100, duration: 150 }}
>
<TextFilter />
<CloseFilter />
</div>
<!-- TODO: Add KeywordList support -->
<!-- {:else if isListFilter(attribute)}
{:else if isListFilter($filter)}
<div class="w-full" in:fly={{ x: -100, duration: 150 }}>
<ListFilter />
</div> -->
{:else if isDurationFilter(attribute)}
<ListFilter>
<CloseFilter />
</ListFilter>
</div>
{:else if isDurationFilter($filter)}
<div
class="flex w-full items-center"
in:fly={{ x: -100, duration: 150 }}
>
<DurationFilter />
<CloseFilter />
</div>
{:else if isNumberFilter({ attribute, type })}
{:else if isNumberFilter($filter)}
<div
class="flex w-full items-center"
in:fly={{ x: -100, duration: 150 }}
>
<NumberFilter />
<CloseFilter />
</div>
{:else if isDateTimeFilter({ attribute, type })}
{:else if isDateTimeFilter($filter)}
<div
class="flex w-full items-center"
in:fly={{ x: -100, duration: 150 }}
>
<DateTimeFilter />
<CloseFilter />
</div>
{:else if isBooleanFilter({ attribute, type })}
{:else if isBooleanFilter($filter)}
<div
class="flex w-full items-center"
in:fly={{ x: -100, duration: 150 }}
Expand Down
39 changes: 29 additions & 10 deletions src/lib/components/search-attribute-filter/list-filter.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { getContext } from 'svelte';
import { getContext, onMount } from 'svelte';

import Button from '$lib/holocene/button.svelte';
import ChipInput from '$lib/holocene/input/chip-input.svelte';
Expand All @@ -11,6 +11,18 @@

let list: string[] = [];

onMount(() => {
laurakwhit marked this conversation as resolved.
Show resolved Hide resolved
const { value } = $filter;
const initialList =
value.length > 0
? value
.slice(1, -1)
.split(', ')
.map((v) => v.slice(1, -1))
: [];
list = initialList;
});

function onSubmit() {
$filter.conditional = 'IN';
list = list.map((item) => `"${item}"`);
Expand All @@ -19,21 +31,28 @@
}
</script>

<div class="flex">
<form class="flex grow" on:submit|preventDefault={onSubmit}>
<ChipInput
label={$filter.attribute}
labelHidden
id="list-filter"
bind:chips={list}
class="w-full rounded-none"
class="w-full"
removeChipButtonLabel={(chip) =>
translate('workflows.remove-keyword-label', { keyword: chip })}
placeholder="{translate('common.type-or-paste-in')} {$filter.attribute}"
unroundLeft
unroundRight
external
/>
<Button
variant="secondary"
borderRadiusModifier="square-left"
disabled={!list.length}
on:click={onSubmit}>{translate('common.submit')}</Button
>
</div>
<div class="flex h-fit items-center">
<Button
borderRadiusModifier="square-left"
disabled={!list.length}
type="submit"
>
{translate('common.search')}
</Button>
<slot />
</div>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
import type { SearchAttributeFilter } from '$lib/models/search-attribute-filters';
import type { SearchAttributeOption } from '$lib/stores/search-attributes';
import type { SearchAttributeType } from '$lib/types/workflows';
import {
getFocusedElementId,
isListFilter,
} from '$lib/utilities/query/search-attribute-filter';
import { getFocusedElementId } from '$lib/utilities/query/search-attribute-filter';
import { emptyFilter } from '$lib/utilities/query/to-list-workflow-filters';

import { FILTER_CONTEXT, type FilterContext } from './index.svelte';
Expand All @@ -38,18 +35,14 @@
function handleNewQuery(value: string, type: SearchAttributeType) {
searchAttributeValue = '';
filter.set({ ...emptyFilter(), attribute: value, conditional: '=', type });
$focusedElementId = getFocusedElementId({ attribute: value, type });
$focusedElementId = getFocusedElementId($filter);
}

let searchAttributeValue = '';
// TODO: Add KeywordList support
$: _options = options.filter(
({ value, type }) => !isListFilter({ attribute: value, type }),
);

$: filteredOptions = !searchAttributeValue
? _options
: _options.filter((option) =>
? options
: options.filter((option) =>
option.value.toLowerCase().includes(searchAttributeValue.toLowerCase()),
);
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
const { filter, resetFilter } = getContext<FilterContext>(FILTER_CONTEXT);
const open = writable(true);
$: _filters = [...filters];
$: statusFilters = _filters.filter((filter) =>
isStatusFilter(filter.attribute),
);
$: statusFilters = _filters.filter((filter) => isStatusFilter(filter));

function apply() {
filters = _filters;
Expand Down Expand Up @@ -61,9 +59,7 @@
if (status === 'All') {
_filters = filters.filter((f) => f.attribute !== 'ExecutionStatus');
} else if (statusFilters.find((s) => s.value === status)) {
const nonStatusFilters = filters.filter(
(f) => !isStatusFilter(f.attribute),
);
const nonStatusFilters = filters.filter((f) => !isStatusFilter(f));
_filters = [
...nonStatusFilters,
...mapStatusesToFilters(
Expand All @@ -74,9 +70,7 @@
if (!statusFilters.length) {
_filters = [..._filters, mapStatusToFilter(status)];
} else {
const nonStatusFilters = _filters.filter(
(f) => !isStatusFilter(f.attribute),
);
const nonStatusFilters = _filters.filter((f) => !isStatusFilter(f));
_filters = [
...nonStatusFilters,
...mapStatusesToFilters([
Expand Down
8 changes: 6 additions & 2 deletions src/lib/components/workflow/add-search-attributes.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@
on:click={addSearchAttribute}
disabled={!searchAttributes.length ||
attributesToAdd.length === searchAttributes.length ||
attributesToAdd.filter((a) => a.value === '' || a.value === null).length >
0}>{translate('workflows.add-search-attribute')}</Button
attributesToAdd.filter(
(a) =>
a.value === '' ||
a.value === null ||
(Array.isArray(a.value) && a.value.length === 0),
).length > 0}>{translate('workflows.add-search-attribute')}</Button
>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
let second = '';
onMount(() => {
if (value) {
if (value && (typeof value === 'string' || typeof value === 'number')) {
const datetime = new Date(value);
const utcDate = new Date(
datetime.getUTCFullYear(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
} from '$lib/types/workflows';

import DatetimeInput from './datetime-input.svelte';
import ListInput from './list-input.svelte';
import NumberInput from './number-input.svelte';
import TextInput from './text-input.svelte';

Expand All @@ -22,9 +23,9 @@
export let onRemove: (attribute: string) => void;

$: type = searchAttributes[attribute.attribute];
$: searchAttributesOptions = [...Object.entries(searchAttributes)]
.map(([key, value]) => ({ label: key, value: key, type: value }))
.filter(({ type }) => type !== 'KeywordList');
$: searchAttributesOptions = [...Object.entries(searchAttributes)].map(
laurakwhit marked this conversation as resolved.
Show resolved Hide resolved
([key, value]) => ({ label: key, value: key, type: value }),
);

$: isDisabled = (value: string) => {
return !!attributesToAdd.find((a) => a.attribute === value);
Expand All @@ -37,7 +38,7 @@
};
</script>

<div class="flex items-start gap-2">
<div class="flex items-end gap-2">
<div class="min-w-fit">
<Select
id="search-attribute"
Expand Down Expand Up @@ -67,6 +68,8 @@
<DatetimeInput bind:value={attribute.value} />
{:else if type === SEARCH_ATTRIBUTE_TYPE.INT || type === SEARCH_ATTRIBUTE_TYPE.DOUBLE}
<NumberInput bind:value={attribute.value} />
{:else if type === SEARCH_ATTRIBUTE_TYPE.KEYWORDLIST}
<ListInput bind:value={attribute.value} />
{:else}
<TextInput bind:value={attribute.value} />
{/if}
Expand Down
Loading
Loading