+
- {#if valuesToDisplay.length}
- {#each valuesToDisplay as value}
+ {#if allValues?.length}
+ {#each allValues.sort() as value}
diff --git a/web-common/src/components/icons/ChevronRight.svelte b/web-common/src/components/icons/ChevronRight.svelte
new file mode 100644
index 00000000000..2ea1015102b
--- /dev/null
+++ b/web-common/src/components/icons/ChevronRight.svelte
@@ -0,0 +1,19 @@
+
+
+
diff --git a/web-common/src/components/search/Search.svelte b/web-common/src/components/search/Search.svelte
index 1dc6de3b200..76637c22832 100644
--- a/web-common/src/components/search/Search.svelte
+++ b/web-common/src/components/search/Search.svelte
@@ -38,9 +38,8 @@
bind:this={ref}
type="text"
autocomplete="off"
- class="bg-white border border-gray-200 {showBorderOnFocus
- ? 'focus:border-blue-400'
- : ''} outline-none rounded-sm block w-full pl-8 p-1"
+ class:focus={showBorderOnFocus}
+ class="bg-slate-50 border border-gray-200 outline-none rounded-sm block w-full pl-8 p-1"
{placeholder}
bind:value
on:input
@@ -48,3 +47,9 @@
aria-label={label}
/>
+
+
diff --git a/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte b/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte
index fd1aabba432..9b27a5cced4 100644
--- a/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte
+++ b/web-common/src/components/searchable-filter-menu/SearchableFilterDropdown.svelte
@@ -1,7 +1,6 @@
+
+
+
+
+
+
+ Add filter
+
+
+ {
+ toggleFloatingElement();
+ toggleDimensionNameSelection(e.detail.name);
+ }}
+ />
+
+
+
diff --git a/web-common/src/features/dashboards/filters/Filters.svelte b/web-common/src/features/dashboards/filters/Filters.svelte
index a159fa90fdb..505edb3e07a 100644
--- a/web-common/src/features/dashboards/filters/Filters.svelte
+++ b/web-common/src/features/dashboards/filters/Filters.svelte
@@ -25,13 +25,18 @@ The main feature-set component for dashboard filters
import { getStateManagers } from "../state-managers/state-managers";
import {
clearAllFilters,
- clearFilterForDimension,
toggleDimensionValue,
toggleFilterMode,
} from "../actions";
+ import FilterButton from "./FilterButton.svelte";
const StateManagers = getStateManagers();
- const { dashboardStore } = StateManagers;
+ const {
+ dashboardStore,
+ actions: {
+ dimensionsFilter: { toggleDimensionNameSelection },
+ },
+ } = StateManagers;
/** the height of a row of chips */
const ROW_HEIGHT = "26px";
@@ -47,23 +52,25 @@ The main feature-set component for dashboard filters
}
let searchText = "";
- let searchedValues: string[] | null = null;
- let activeDimensionName;
+ let allValues: string[] | null = null;
+ let activeDimensionName: string;
+
$: activeColumn =
dimensions.find((d) => d.name === activeDimensionName)?.column ??
activeDimensionName;
let topListQuery: ReturnType | undefined;
- $: if (activeDimensionName)
+ $: if (activeDimensionName) {
topListQuery = getFilterSearchList(StateManagers, {
dimension: activeDimensionName,
searchText,
addNull: "null".includes(searchText),
});
+ }
- $: if (!$topListQuery?.isFetching && searchText != "") {
+ $: if (!$topListQuery?.isFetching) {
const topListData = $topListQuery?.data?.data ?? [];
- searchedValues = topListData.map((datum) => datum[activeColumn]) ?? [];
+ allValues = topListData.map((datum) => datum[activeColumn]) ?? [];
}
$: hasFilters = isFiltered($dashboardStore.filters);
@@ -120,7 +127,7 @@ The main feature-set component for dashboard filters
currentDimensionFilters.sort((a, b) => (a.name > b.name ? 1 : -1));
}
- function setActiveDimension(name, value) {
+ function setActiveDimension(name, value = "") {
activeDimensionName = name;
searchText = value;
}
@@ -144,31 +151,42 @@ The main feature-set component for dashboard filters
>
- {#if currentDimensionFilters.length > 0}
-
+
+
+ {#if !currentDimensionFilters.length}
+
+ No filters selected
+
+ {:else}
{#each currentDimensionFilters as { name, label, selectedValues, filterType } (name)}
{@const isInclude = filterType === "include"}
toggleFilterMode(StateManagers, name)}
- on:remove={() =>
- clearFilterForDimension(
- StateManagers,
- name,
- isInclude ? true : false
- )}
- on:apply={(event) =>
- toggleDimensionValue(StateManagers, name, event.detail)}
+ on:remove={() => toggleDimensionNameSelection(name)}
+ on:apply={(event) => {
+ toggleDimensionValue(StateManagers, name, event.detail);
+ }}
on:search={(event) => {
setActiveDimension(name, event.detail);
}}
+ on:click={() => {
+ setActiveDimension(name, "");
+ }}
+ on:mount={() => {
+ setActiveDimension(name);
+ }}
typeLabel="dimension"
name={isInclude ? label : `Exclude ${label}`}
excludeMode={isInclude ? false : true}
colors={getColorForChip(isInclude)}
label="View filter"
{selectedValues}
- {searchedValues}
+ {allValues}
>
Click to edit the the filters in this dimension
@@ -176,35 +194,26 @@ The main feature-set component for dashboard filters
{/each}
-
- {#if hasFilters}
-
- clearAllFilters(StateManagers)}
- >
-
-
-
- Clear filters
-
-
- {/if}
-
- {:else if currentDimensionFilters.length === 0}
-
- No filters selected
-
- {:else}
-
- {/if}
+ {#if hasFilters}
+
+ clearAllFilters(StateManagers)}
+ >
+
+
+
+ Clear filters
+
+
+ {/if}
+
diff --git a/web-common/src/features/dashboards/selectors/index.ts b/web-common/src/features/dashboards/selectors/index.ts
index dd9f11f8bd5..f448754a770 100644
--- a/web-common/src/features/dashboards/selectors/index.ts
+++ b/web-common/src/features/dashboards/selectors/index.ts
@@ -73,7 +73,7 @@ export const getFilterSearchList = (
measureNames: [metricsExplorer.leaderboardMeasureName],
timeStart: timeControls.timeStart,
timeEnd: timeControls.timeEnd,
- limit: "15",
+ limit: "100",
offset: "0",
sort: [],
filter: {
diff --git a/web-common/src/features/dashboards/state-managers/actions/dimension-filters.ts b/web-common/src/features/dashboards/state-managers/actions/dimension-filters.ts
index f163d81720f..2c56935608b 100644
--- a/web-common/src/features/dashboards/state-managers/actions/dimension-filters.ts
+++ b/web-common/src/features/dashboards/state-managers/actions/dimension-filters.ts
@@ -38,6 +38,34 @@ export function toggleDimensionValueSelection(
}
}
+export function toggleDimensionNameSelection(
+ { dashboard, cancelQueries }: DashboardMutables,
+ dimensionName: string
+) {
+ const filters = filtersForCurrentExcludeMode({ dashboard })(dimensionName);
+ // if there are no filters at this point we cannot update anything.
+ if (filters === undefined) {
+ return;
+ }
+
+ // if we are able to update the filters, we must cancel any queries
+ // that are currently running.
+ cancelQueries();
+
+ const filterIndex = filters.findIndex(
+ (filter) => filter.name === dimensionName
+ );
+
+ if (filterIndex === -1) {
+ filters.push({
+ name: dimensionName,
+ in: [],
+ });
+ } else {
+ filters.splice(filterIndex, 1);
+ }
+}
+
export const dimensionFilterActions = {
/**
* Toggles whether the given dimension value is selected in the
@@ -48,4 +76,5 @@ export const dimensionFilterActions = {
* the include/exclude mode is a toggle for the entire dimension.
*/
toggleDimensionValueSelection,
+ toggleDimensionNameSelection,
};
diff --git a/web-local/test/ui/dashboards.spec.ts b/web-local/test/ui/dashboards.spec.ts
index 3d10daf997b..79cd8bee52c 100644
--- a/web-local/test/ui/dashboards.spec.ts
+++ b/web-local/test/ui/dashboards.spec.ts
@@ -245,6 +245,8 @@ test.describe("dashboard", () => {
// Filter to Facebook via leaderboard
await page.getByRole("button", { name: "Facebook 19.3k" }).click();
+ await page.waitForSelector("text=Publisher Facebook");
+
// Change filter to excluded
await page.getByText("Publisher Facebook").click();
await page.getByRole("button", { name: "Exclude" }).click();