Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 34 additions & 8 deletions web-admin/src/features/alerts/metadata/AlertFilters.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
import { YAMLConfigProvider } from "@rilldata/web-common/features/dashboards/providers/YAMLConfigProvider.svelte.ts";
import { MetricsViewsProvider } from "@rilldata/web-common/features/metrics-views/providers/MetricsViewsProvider.svelte.ts";
import ReadonlyExpressionFilters from "@rilldata/web-common/features/dashboards/filters/ReadonlyExpressionFilters.svelte";
import { onDestroy } from "svelte";
import { onDestroy, untrack } from "svelte";
import { TimeFilterManager } from "@rilldata/web-common/features/dashboards/time-controls/TimeFilterManager.svelte.ts";
import { ExploreStateURLParams } from "@rilldata/web-common/features/dashboards/url-state/url-params.ts";
import {
mapV1TimeRangeToComparisonTimeOption,
mapV1TimeRangeToRillTime,
} from "@rilldata/web-common/features/dashboards/time-controls/time-range-mappers.ts";

let {
metricsViewName,
Expand All @@ -31,6 +37,7 @@
const metricsViewProvider = new MetricsViewsProvider(runtimeClient, []);
$effect(() => metricsViewProvider.setMetricsViewNames([metricsViewName]));
const yamlConfigProvider = new YAMLConfigProvider();

const expressionFilterManager = new ExpressionFilterManager(
metricsViewProvider,
yamlConfigProvider,
Expand All @@ -43,6 +50,31 @@
),
);

const timeFilterManager = new TimeFilterManager(
runtimeClient,
metricsViewProvider,
yamlConfigProvider,
);
$effect(() => {
if (!timeRange || !timeFilterManager.ready) return;
const urlParams = new URLSearchParams();
urlParams.set(
ExploreStateURLParams.TimeRange,
mapV1TimeRangeToRillTime(timeRange),
);

if (comparisonTimeRange) {
urlParams.set(
ExploreStateURLParams.ComparisonTimeRange,
mapV1TimeRangeToComparisonTimeOption(timeRange, comparisonTimeRange),
);
}

untrack(() => {
timeFilterManager.setUrlParams(urlParams);
});
});

// time range could be an empty object sometimes
let hasTimeRange = $derived(timeRange && Object.keys(timeRange).length > 0);
let filtersLength = $derived(
Expand All @@ -59,11 +91,5 @@
<MetadataLabel>
{m.alert_filters_label({ count: String(filtersLength) })}
</MetadataLabel>
<ReadonlyExpressionFilters
{expressionFilterManager}
displayTimeRange={timeRange}
displayComparisonTimeRange={comparisonTimeRange}
queryTimeStart={timeRange?.start}
queryTimeEnd={timeRange?.end}
/>
<ReadonlyExpressionFilters {expressionFilterManager} {timeFilterManager} />
</div>
94 changes: 14 additions & 80 deletions web-admin/src/features/bookmarks/BookmarksFormDialog.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import { invalidateBookmarkQueries } from "@rilldata/web-admin/features/bookmarks/selectors.ts";
import {
type BookmarkEntry,
formatTimeRange,
getBookmarkData,
} from "@rilldata/web-admin/features/bookmarks/utils.ts";
import ProjectAccessControls from "@rilldata/web-admin/features/projects/ProjectAccessControls.svelte";
Expand All @@ -20,16 +19,10 @@
import Switch from "@rilldata/web-common/components/forms/Switch.svelte";
import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte";
import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte";
import { deriveInterval } from "@rilldata/web-common/features/dashboards/time-controls/new-time-controls";
import { ExploreStateURLParams } from "@rilldata/web-common/features/dashboards/url-state/url-params";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors.ts";
import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus.ts";
import {
V1TimeGrain,
type V1TimeRange,
} from "@rilldata/web-common/runtime-client";
import { type V1TimeRange } from "@rilldata/web-common/runtime-client";
import { InfoIcon } from "lucide-svelte";
import type { Interval } from "luxon";
import { useRuntimeClient } from "@rilldata/web-common/runtime-client/v2";
import { defaults, superForm } from "sveltekit-superforms";
import { yup } from "sveltekit-superforms/adapters";
Expand All @@ -42,6 +35,7 @@
ExploreDashboardConfigProvider,
} from "@rilldata/web-common/features/dashboards/providers/DashboardConfigProvider.svelte.ts";
import { onDestroy } from "svelte";
import { TimeFilterManager } from "@rilldata/web-common/features/dashboards/time-controls/TimeFilterManager.svelte.ts";

let {
organization,
Expand Down Expand Up @@ -71,14 +65,22 @@
resourceKind === ResourceKind.Canvas
? new CanvasDashboardConfigProvider(runtimeClient, resourceName)
: new ExploreDashboardConfigProvider(runtimeClient, resourceName);

const expressionFilterManager = new ExpressionFilterManager(
dashboardConfigProvider.metricsViewsProvider,
dashboardConfigProvider.yamlConfigProvider,
);

const timeFilterManager = new TimeFilterManager(
runtimeClient,
dashboardConfigProvider.metricsViewsProvider,
dashboardConfigProvider.yamlConfigProvider,
);

// Always load from current url state. This is the only route to overwrite bookmark state.
// A future PR will improve this by adding `Replace` action, in that case this should only have bookmark's state.
expressionFilterManager.storeSync.setUrlParams(page.url.searchParams);
timeFilterManager.storeSync.setUrlParams(page.url.searchParams);

let timeFilterState = $state<
| {
Expand All @@ -91,70 +93,6 @@
>(undefined);

let curUrlParams = $derived(page.url.searchParams);
$effect(() => void processTimeFromUrl());
async function processTimeFromUrl() {
const searchParamsObj = new URLSearchParams(curUrlParams);
const rangeExpression = searchParamsObj.get(
ExploreStateURLParams.TimeRange,
);
const timeRange = <V1TimeRange>{
expression: rangeExpression || "",
};

const timeZone =
searchParamsObj.get(ExploreStateURLParams.TimeZone) || "UTC";

try {
const promises =
dashboardConfigProvider.metricsViewsProvider.metricsViewNames.map(
(mvName) =>
deriveInterval(
timeRange.expression || "",
runtimeClient,
mvName,
timeZone,
),
);

const intervals = await Promise.all(promises);
let intervalWithLatestEndPoint:
| {
interval: Interval;
grain?: V1TimeGrain | undefined;
error?: string;
}
| undefined;
intervals.forEach((response) => {
if (
!intervalWithLatestEndPoint ||
(response.interval.end && intervalWithLatestEndPoint.interval.end
? response.interval.end > intervalWithLatestEndPoint.interval.end
: false)
) {
intervalWithLatestEndPoint = response;
}
});

const start = intervalWithLatestEndPoint?.interval?.start?.toISO();
const end = intervalWithLatestEndPoint?.interval?.end?.toISO();

const grain =
(searchParamsObj.get(ExploreStateURLParams.TimeGrain) as V1TimeGrain) ||
intervalWithLatestEndPoint.grain ||
V1TimeGrain.TIME_GRAIN_MINUTE;

const selectedTimeRange = formatTimeRange(start, end, grain, timeZone);

timeFilterState = {
queryTimeStart: start,
queryTimeEnd: end,
displayTimeRange: timeRange,
selectedTimeRange,
};
} catch {
timeFilterState = undefined;
}
}

const bookmarkCreator = createAdminServiceCreateBookmark();
const bookmarkUpdater = createAdminServiceUpdateBookmark();
Expand Down Expand Up @@ -281,14 +219,10 @@
{m.bookmark_filters_inherited()}
</div>
</Label>
{#if timeFilterState}
<ReadonlyExpressionFilters
{expressionFilterManager}
displayTimeRange={timeFilterState.displayTimeRange}
queryTimeStart={timeFilterState.queryTimeStart}
queryTimeEnd={timeFilterState.queryTimeEnd}
/>
{/if}
<ReadonlyExpressionFilters
{expressionFilterManager}
{timeFilterManager}
/>
</div>
<ProjectAccessControls {organization} {project}>
<Select
Expand Down
23 changes: 14 additions & 9 deletions web-admin/src/features/public-urls/CreatePublicURLForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
ExploreDashboardConfigProvider,
} from "@rilldata/web-common/features/dashboards/providers/DashboardConfigProvider.svelte.ts";
import { onDestroy } from "svelte";
import { TimeFilterManager } from "@rilldata/web-common/features/dashboards/time-controls/TimeFilterManager.svelte.ts";
import { useCanvas } from "@rilldata/web-common/features/canvas/selector";
import { useVisibilityConditionsCheck } from "@rilldata/web-common/features/dashboards/granular-access-policies/useSecurityPolicyCheck";

Expand All @@ -63,14 +64,22 @@
const dashboardConfigProvider = isExplore
? new ExploreDashboardConfigProvider(runtimeClient, dashboardName)
: new CanvasDashboardConfigProvider(runtimeClient, dashboardName);

const expressionFilterManager = new ExpressionFilterManager(
dashboardConfigProvider.metricsViewsProvider,
dashboardConfigProvider.yamlConfigProvider,
);

const timeFilterManager = new TimeFilterManager(
runtimeClient,
dashboardConfigProvider.metricsViewsProvider,
dashboardConfigProvider.yamlConfigProvider,
);

// Always load from current state. This is the only route to overwrite bookmark state.
// A future PR will improve this by adding `Replace` action, in that case this should only have bookmark's state.
expressionFilterManager.storeSync.setUrlParams(page.url.searchParams);
timeFilterManager.storeSync.setUrlParams(page.url.searchParams);

// A public URL shows a canvas the way its creator sees it, so point out content that only some viewers see.
const canvasQuery = useCanvas(runtimeClient, dashboardName, {
Expand All @@ -91,13 +100,9 @@
dashboardKind,
expressionFilterManager,
);
let {
fields,
sanitizedState,
droppedEphemeralMeasures,
queryTimeStart,
queryTimeEnd,
} = $derived($sanitisedFilterState);
let { fields, sanitizedState, droppedEphemeralMeasures } = $derived(
$sanitisedFilterState,
);

const formId = "create-public-url-form";

Expand Down Expand Up @@ -259,8 +264,8 @@
<div class="flex flex-col gap-2 my-2">
<ReadonlyExpressionFilters
{expressionFilterManager}
{queryTimeStart}
{queryTimeEnd}
{timeFilterManager}
hideTimePills
/>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions web-admin/tests/bookmarks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

// Assert the selected filters
await expect(adminPage.getByLabel("Readonly Filter Chips")).toHaveText(
` Last 6 hours App Site Name FuboTV +1 other `,
/Last 6 hours\s+vs Previous period\s+App Site Name FuboTV\s+\+1 other/,
);
// Create a personal bookmark
await enterBookmarkDetails(
Expand Down Expand Up @@ -74,7 +74,7 @@
"Filter-Only Bookmark Entry",
);
// Verify that a home bookmark was created
await expect(filterOnlyBookmarkLocator).toHaveText(

Check failure on line 77 in web-admin/tests/bookmarks.spec.ts

View workflow job for this annotation

GitHub Actions / e2e (web-admin)

[e2e] › tests/bookmarks.spec.ts:63:7 › Bookmarks › Explore bookmarks › Filter-only explore bookmark › Applying filter-only bookmark should not change other settings

1) [e2e] › tests/bookmarks.spec.ts:63:7 › Bookmarks › Explore bookmarks › Filter-only explore bookmark › Applying filter-only bookmark should not change other settings Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toHaveText(expected) failed Locator: getByLabel('Filter-Only Bookmark Entry') Expected: "Filter-Only My filter-only bookmark." Error: strict mode violation: getByLabel('Filter-Only Bookmark Entry') resolved to 3 elements: 1) <div tabindex="-1" role="menuitem" aria-label="Filter-Only Bookmark Entry" class="flex justify-between gap-x-2 w-full">…</div> aka locator('#bits-c248').getByRole('menuitem', *** name: 'Filter-Only Bookmark Entry' ***) 2) <div tabindex="-1" role="menuitem" aria-label="Filter-Only Bookmark Entry" class="flex justify-between gap-x-2 w-full">…</div> aka locator('#bits-c249').getByRole('menuitem', *** name: 'Filter-Only Bookmark Entry' ***) 3) <div tabindex="-1" role="menuitem" aria-label="Filter-Only Bookmark Entry" class="flex justify-between gap-x-2 w-full">…</div> aka locator('#bits-c250').getByRole('menuitem', *** name: 'Filter-Only Bookmark Entry' ***) Call log: - Expect "toHaveText" with timeout 5000ms - waiting for getByLabel('Filter-Only Bookmark Entry') 75 | ); 76 | // Verify that a home bookmark was created > 77 | await expect(filterOnlyBookmarkLocator).toHaveText( | ^ 78 | "Filter-Only My filter-only bookmark.", 79 | ); 80 | // Verify that the bookmark has the correct icon at /home/runner/work/rill/rill/web-admin/tests/bookmarks.spec.ts:77:49

Check failure on line 77 in web-admin/tests/bookmarks.spec.ts

View workflow job for this annotation

GitHub Actions / e2e (web-admin)

[e2e] › tests/bookmarks.spec.ts:63:7 › Bookmarks › Explore bookmarks › Filter-only explore bookmark › Applying filter-only bookmark should not change other settings

1) [e2e] › tests/bookmarks.spec.ts:63:7 › Bookmarks › Explore bookmarks › Filter-only explore bookmark › Applying filter-only bookmark should not change other settings Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toHaveText(expected) failed Locator: getByLabel('Filter-Only Bookmark Entry') Expected: "Filter-Only My filter-only bookmark." Error: strict mode violation: getByLabel('Filter-Only Bookmark Entry') resolved to 2 elements: 1) <div tabindex="-1" role="menuitem" aria-label="Filter-Only Bookmark Entry" class="flex justify-between gap-x-2 w-full">…</div> aka locator('#bits-c248').getByRole('menuitem', *** name: 'Filter-Only Bookmark Entry' ***) 2) <div tabindex="-1" role="menuitem" aria-label="Filter-Only Bookmark Entry" class="flex justify-between gap-x-2 w-full">…</div> aka locator('#bits-c249').getByRole('menuitem', *** name: 'Filter-Only Bookmark Entry' ***) Call log: - Expect "toHaveText" with timeout 5000ms - waiting for getByLabel('Filter-Only Bookmark Entry') 75 | ); 76 | // Verify that a home bookmark was created > 77 | await expect(filterOnlyBookmarkLocator).toHaveText( | ^ 78 | "Filter-Only My filter-only bookmark.", 79 | ); 80 | // Verify that the bookmark has the correct icon at /home/runner/work/rill/rill/web-admin/tests/bookmarks.spec.ts:77:49
"Filter-Only My filter-only bookmark.",
);
// Verify that the bookmark has the correct icon
Expand All @@ -87,7 +87,7 @@
await expect(adminPage.getByText("Last 6 Hours")).toBeVisible();
await expect(
adminPage.getByText("App Site Name FuboTV +1 other"),
).toBeVisible();

Check failure on line 90 in web-admin/tests/bookmarks.spec.ts

View workflow job for this annotation

GitHub Actions / e2e (web-admin)

[e2e] › tests/bookmarks.spec.ts:63:7 › Bookmarks › Explore bookmarks › Filter-only explore bookmark › Applying filter-only bookmark should not change other settings

1) [e2e] › tests/bookmarks.spec.ts:63:7 › Bookmarks › Explore bookmarks › Filter-only explore bookmark › Applying filter-only bookmark should not change other settings Error: expect(locator).toBeVisible() failed Locator: getByText('App Site Name FuboTV +1 other') Expected: visible Timeout: 5000ms Error: element(s) not found Call log: - Expect "toBeVisible" with timeout 5000ms - waiting for getByText('App Site Name FuboTV +1 other') 88 | await expect( 89 | adminPage.getByText("App Site Name FuboTV +1 other"), > 90 | ).toBeVisible(); | ^ 91 | await expect( 92 | adminPage.getByLabel("requests Time Dimension Display"), 93 | ).toBeVisible(); at /home/runner/work/rill/rill/web-admin/tests/bookmarks.spec.ts:90:11
await expect(
adminPage.getByLabel("requests Time Dimension Display"),
).toBeVisible();
Expand Down Expand Up @@ -154,7 +154,7 @@

// Assert the selected filters
await expect(adminPage.getByLabel("Readonly Filter Chips")).toHaveText(
` Last 6 hours App Site Name FuboTV +1 other `,
/Last 6 hours\s+vs Previous period\s+App Site Name FuboTV\s+\+1 other/,
);
// Create a personal bookmark
await enterBookmarkDetails(
Expand Down Expand Up @@ -377,12 +377,12 @@

// Assert the selected filters
await expect(adminPage.getByLabel("Readonly Filter Chips")).toHaveText(
` Last 6 hours Advertiser Name Instacart +1 other `,
/Last 6 hours\s+vs Previous period\s+Advertiser Name Instacart\s+\+1 other/,
);
// Assert filters applied
await expect(
adminPage.getByLabel("overall_spend KPI data"),
).toContainText(

Check failure on line 385 in web-admin/tests/bookmarks.spec.ts

View workflow job for this annotation

GitHub Actions / e2e (web-admin)

[e2e] › tests/bookmarks.spec.ts:351:7 › Bookmarks › Canvas bookmarks › Complete canvas bookmarks › Create a complete canvas bookmark

2) [e2e] › tests/bookmarks.spec.ts:351:7 › Bookmarks › Canvas bookmarks › Complete canvas bookmarks › Create a complete canvas bookmark Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toContainText(expected) failed Locator: getByLabel('overall_spend KPI data') Expected pattern: /Advertising Spend Overall\s*\$448.22\s*-\$75.80\s*-15%\s*vs previous period/ Received string: "Advertising Spend Overall $829.75 -$21,281 -96% " Timeout: 5000ms Call log: - Expect "toContainText" with timeout 5000ms - waiting for getByLabel('overall_spend KPI data') 9 × locator resolved to <div tabindex="0" type="button" role="button" id="bits-c114" data-state="closed" data-tooltip-trigger="" data-delay-duration="700" aria-label="overall_spend KPI data" class="data-wrapper overflow-hidden cursor-pointer svelte-u803ot">…</div> - unexpected value "Advertising Spend Overall $829.75 -$21,281 -96% " 383 | await expect( 384 | adminPage.getByLabel("overall_spend KPI data"), > 385 | ).toContainText( | ^ 386 | /Advertising Spend Overall\s*\$448.22\s*-\$75.80\s*-15%\s*vs previous period/, 387 | ); 388 | at /home/runner/work/rill/rill/web-admin/tests/bookmarks.spec.ts:385:11

Check failure on line 385 in web-admin/tests/bookmarks.spec.ts

View workflow job for this annotation

GitHub Actions / e2e (web-admin)

[e2e] › tests/bookmarks.spec.ts:351:7 › Bookmarks › Canvas bookmarks › Complete canvas bookmarks › Create a complete canvas bookmark

2) [e2e] › tests/bookmarks.spec.ts:351:7 › Bookmarks › Canvas bookmarks › Complete canvas bookmarks › Create a complete canvas bookmark Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toContainText(expected) failed Locator: getByLabel('overall_spend KPI data') Expected pattern: /Advertising Spend Overall\s*\$448.22\s*-\$75.80\s*-15%\s*vs previous period/ Received string: "Advertising Spend Overall $829.75 -$21,281 -96% " Timeout: 5000ms Call log: - Expect "toContainText" with timeout 5000ms - waiting for getByLabel('overall_spend KPI data') 9 × locator resolved to <div tabindex="0" type="button" role="button" id="bits-c114" data-state="closed" data-tooltip-trigger="" data-delay-duration="700" aria-label="overall_spend KPI data" class="data-wrapper overflow-hidden cursor-pointer svelte-u803ot">…</div> - unexpected value "Advertising Spend Overall $829.75 -$21,281 -96% " 383 | await expect( 384 | adminPage.getByLabel("overall_spend KPI data"), > 385 | ).toContainText( | ^ 386 | /Advertising Spend Overall\s*\$448.22\s*-\$75.80\s*-15%\s*vs previous period/, 387 | ); 388 | at /home/runner/work/rill/rill/web-admin/tests/bookmarks.spec.ts:385:11

Check failure on line 385 in web-admin/tests/bookmarks.spec.ts

View workflow job for this annotation

GitHub Actions / e2e (web-admin)

[e2e] › tests/bookmarks.spec.ts:351:7 › Bookmarks › Canvas bookmarks › Complete canvas bookmarks › Create a complete canvas bookmark

2) [e2e] › tests/bookmarks.spec.ts:351:7 › Bookmarks › Canvas bookmarks › Complete canvas bookmarks › Create a complete canvas bookmark Error: expect(locator).toContainText(expected) failed Locator: getByLabel('overall_spend KPI data') Expected pattern: /Advertising Spend Overall\s*\$448.22\s*-\$75.80\s*-15%\s*vs previous period/ Received string: "Advertising Spend Overall $829.75 -$21,281 -96% " Timeout: 5000ms Call log: - Expect "toContainText" with timeout 5000ms - waiting for getByLabel('overall_spend KPI data') 9 × locator resolved to <div tabindex="0" type="button" role="button" id="bits-c114" data-state="closed" data-tooltip-trigger="" data-delay-duration="700" aria-label="overall_spend KPI data" class="data-wrapper overflow-hidden cursor-pointer svelte-u803ot">…</div> - unexpected value "Advertising Spend Overall $829.75 -$21,281 -96% " 383 | await expect( 384 | adminPage.getByLabel("overall_spend KPI data"), > 385 | ).toContainText( | ^ 386 | /Advertising Spend Overall\s*\$448.22\s*-\$75.80\s*-15%\s*vs previous period/, 387 | ); 388 | at /home/runner/work/rill/rill/web-admin/tests/bookmarks.spec.ts:385:11
/Advertising Spend Overall\s*\$448.22\s*-\$75.80\s*-15%\s*vs previous period/,
);

Expand Down Expand Up @@ -578,7 +578,7 @@
}) => {
// Add random params. Home bookmark shouldnt apply
await adminPage.goto(
"/e2e/openrtb/canvas/bids_canvas_bookmarks?compare_tr=rill-PW",
"/e2e/openrtb/canvas/bids_canvas_bookmarks?tr=24h+as+of+latest%2Fh%2B1h&compare_tr=rill-PW",
);
// Default time range is present
await expect(adminPage.getByText("Last 24 Hours")).toBeVisible();
Expand Down
Loading
Loading