Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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.

104 changes: 23 additions & 81 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 @@ -43,6 +36,7 @@
} from "@rilldata/web-common/features/dashboards/providers/DashboardConfigProvider.svelte.ts";
import { onDestroy } from "svelte";
import { syncStoreWithSource } from "@rilldata/web-common/lib/store-utils/url-params-store-sync.svelte.ts";
import { TimeFilterManager } from "@rilldata/web-common/features/dashboards/time-controls/TimeFilterManager.svelte.ts";

let {
organization,
Expand Down Expand Up @@ -72,11 +66,11 @@
resourceKind === ResourceKind.Canvas
? new CanvasDashboardConfigProvider(runtimeClient, resourceName)
: new ExploreDashboardConfigProvider(runtimeClient, resourceName);

const expressionFilterManager = new ExpressionFilterManager(
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.
syncStoreWithSource(
Expand All @@ -85,6 +79,22 @@
() => dashboardConfigProvider.metricsViewsProvider.ready,
);

const timeFilterManager = new TimeFilterManager(
runtimeClient,
dashboardConfigProvider.metricsViewsProvider,
dashboardConfigProvider.yamlConfigProvider,
true,
);
// 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.
syncStoreWithSource(
timeFilterManager,
async (newUrlParams) => timeFilterManager.setUrlParams(newUrlParams),
() =>
timeFilterManager.ready &&
dashboardConfigProvider.metricsViewsProvider.ready,
);

let timeFilterState = $state<
| {
queryTimeStart: string;
Expand All @@ -96,70 +106,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 @@ -286,14 +232,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
33 changes: 23 additions & 10 deletions web-admin/src/features/public-urls/CreatePublicURLForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
} from "@rilldata/web-common/features/dashboards/providers/DashboardConfigProvider.svelte.ts";
import { onDestroy } from "svelte";
import { syncStoreWithSource } from "@rilldata/web-common/lib/store-utils/url-params-store-sync.svelte.ts";
import { TimeFilterManager } from "@rilldata/web-common/features/dashboards/time-controls/TimeFilterManager.svelte.ts";

let {
dashboardResource,
Expand All @@ -62,11 +63,11 @@
const dashboardConfigProvider = isExplore
? new ExploreDashboardConfigProvider(runtimeClient, dashboardName)
: new CanvasDashboardConfigProvider(runtimeClient, dashboardName);

const expressionFilterManager = new ExpressionFilterManager(
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.
syncStoreWithSource(
Expand All @@ -75,20 +76,32 @@
() => dashboardConfigProvider.metricsViewsProvider.ready,
);

const timeFilterManager = new TimeFilterManager(
runtimeClient,
dashboardConfigProvider.metricsViewsProvider,
dashboardConfigProvider.yamlConfigProvider,
true,
);
// 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.
syncStoreWithSource(
timeFilterManager,
async (newUrlParams) => timeFilterManager.setUrlParams(newUrlParams),
() =>
timeFilterManager.ready &&
dashboardConfigProvider.metricsViewsProvider.ready,
);

const exprByMetricsView = $derived(expressionFilterManager.exprByMetricsView);
const hasSomeFilter = $derived(Object.keys(exprByMetricsView).length > 0);

const sanitisedFilterState = createFieldsAndStateForKind(
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 @@ -250,8 +263,8 @@
<div class="flex flex-col gap-2 my-2">
<ReadonlyExpressionFilters
{expressionFilterManager}
{queryTimeStart}
{queryTimeEnd}
{timeFilterManager}
hideTimePills
/>
</div>
</div>
Expand Down
45 changes: 18 additions & 27 deletions web-common/src/features/alerts/AlertForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
isSomeFieldTainted,
} from "@rilldata/web-common/features/alerts/utils.ts";
import { getProtoFromDashboardState } from "@rilldata/web-common/features/dashboards/proto-state/toProto.ts";
import { useMetricsViewTimeRange } from "@rilldata/web-common/features/dashboards/selectors.ts";
import { useExploreState } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores.ts";
import type { ExploreState } from "@rilldata/web-common/features/dashboards/stores/explore-state.ts";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors.ts";
Expand All @@ -63,8 +62,8 @@
import { defaults, superForm } from "sveltekit-superforms";
import Button from "web-common/src/components/button/Button.svelte";
import type { ExpressionFilterManager } from "@rilldata/web-common/features/dashboards/filters/ExpressionFilterManager.svelte.ts";
import type { TimeControls } from "@rilldata/web-common/features/dashboards/stores/TimeControls.ts";
import { onDestroy } from "svelte";
import type { TimeFilterManager } from "@rilldata/web-common/features/dashboards/time-controls/TimeFilterManager.svelte.ts";

export let onClose: () => void;
export let onCancel: () => void;
Expand All @@ -90,13 +89,6 @@
$: exploreSpec = $validExploreSpec.data?.explore ?? {};
$: metricsViewName = exploreSpec.metricsView ?? "";

$: allTimeRangeResp = useMetricsViewTimeRange(
runtimeClient,
metricsViewName,
undefined,
queryClient,
);

const exploreState =
props.mode === "create"
? useExploreState(props.exploreName)
Expand All @@ -107,34 +99,26 @@
? createAdminServiceCreateAlert()
: createAdminServiceEditAlert();

let filters: ExpressionFilterManager;
let timeControls: TimeControls;
let expressionFilterManager: ExpressionFilterManager;
let timeFilterManager: TimeFilterManager;
let cleanup: (() => void) | undefined = undefined;
$: {
cleanup?.();
({ filters, timeControls, cleanup } =
({ expressionFilterManager, timeFilterManager, cleanup } =
props.mode === "create"
? getNewAlertInitialFiltersFormValues(
runtimeClient,
metricsViewName,
exploreName,
$exploreState!,
)
? getNewAlertInitialFiltersFormValues(runtimeClient, metricsViewName)
: getFiltersAndTimeControlsFromAggregationRequest(
runtimeClient,
metricsViewName,
exploreName,
JSON.parse(
props.alertSpec.queryArgsJson ||
(props.alertSpec.resolverProperties?.query_args_json as
| string
| undefined) ||
"{}",
),
$allTimeRangeResp.data?.timeRangeSummary,
));
}
$: ({ selectedComparisonTimeRange } = timeControls);

const superFormInstance = superForm(
defaults(initialValues, alertFormValidationSchema),
Expand Down Expand Up @@ -194,9 +178,8 @@
queryArgsJson: JSON.stringify(
getAlertQueryArgsFromFormValues(
values,
filters.topLevelJoiner.expr[metricsViewName],
timeControls.toState(),
exploreSpec,
expressionFilterManager.topLevelJoiner.expr[metricsViewName],
timeFilterManager,
),
),
metricsViewName: values.metricsViewName,
Expand Down Expand Up @@ -283,7 +266,7 @@
// if the user came to the delivery tab and name was not changed then auto generate it
const name = generateAlertName(
$form,
$selectedComparisonTimeRange,
timeFilterManager.comparisonTimeRange,
metricsViewSpec,
);
if (!name) return;
Expand Down Expand Up @@ -324,10 +307,18 @@
</DialogTabs.List>
<div class="p-3 bg-surface-subtle h-[600px] overflow-auto">
<DialogTabs.Content {currentTabIndex} tabIndex={0} value={tabs[0]}>
<AlertDialogDataTab {superFormInstance} {filters} {timeControls} />
<AlertDialogDataTab
{superFormInstance}
{expressionFilterManager}
{timeFilterManager}
/>
</DialogTabs.Content>
<DialogTabs.Content {currentTabIndex} tabIndex={1} value={tabs[1]}>
<AlertDialogCriteriaTab {superFormInstance} {filters} {timeControls} />
<AlertDialogCriteriaTab
{superFormInstance}
{expressionFilterManager}
{timeFilterManager}
/>
</DialogTabs.Content>
<DialogTabs.Content {currentTabIndex} tabIndex={2} value={tabs[2]}>
<AlertDialogDeliveryTab {superFormInstance} {exploreName} />
Expand Down
Loading
Loading