Skip to content

Commit

Permalink
Web: Migrate metrics_view to explore resources (#5724)
Browse files Browse the repository at this point in the history
* Refactor StateManagers to use explore

* Replace useMetricsView - Pass 1

* Use explore in state defaults

* Add basic explore editor

* Replace metricViewName with exploreName where applicable in rill dev

* Update bookmarks

* Fix navigation on cloud

* Fix alerts and reports

* Migrate Public URLs

* Redirect old Explore URLs to `.../explore/[name]`

* Migrate embeds

* Fix syncDimensions

* Fix eslint

* Fix `svelte-check`

* `metricViewName` -> `metricsViewName`

* `useMetricsView` -> `useMetricsViewValidSpec`

* `useDashboard` -> `useMetricsView`

* `useDashboardStore` -> `useExploreStore`

* `useMetaMeasure` -> `useMetricsViewSpecMeasure`

* Add two `+page.ts` files to `tsc` whitelist

* Fix "Function called outside component initialization"

* Add Metrics View icon

* `MetricsExplorerIcon` -> `ExploreIcon`

* Fix unit tests - Pass 1

* Fix unit tests - Pass 2

* Fix unit tests - Pass 3

* Fix tsc

* Revise new files from "Add" button

* Better organization of `features/explores`, `features/metrics-views`

* Refactor `new-files.ts` to account for files bootstrapped from another resource

* Add "Create Explore dashboard" button to Metrics Workspace

* Nits

* "Generate dashboard" -> "Generate metrics"

* "DashboardMenuItems" -> "MetricsViewMenuItems"

* `useValidExplore` -> `useExploreValidSpec`

* `useValidDashboards` -> `useValidExplores`

* Add YAML syntax highlighting to `ExploreEditor`

* Partially fix Preview mode's Explore CTAs

* Explore E2E pass 1 - Fix model and explore editing

* Explore E2E pass 2 - Fix metrics editing in tests

* Explore E2E pass 3 - Fix metrics editor experience

* Fix eslint

* Explore E2E pass 3 - Fix incorrect test migration

* Avoid using useMetricsView

* Fix resource->resource navigation buttons

* Use the right icons

* Update e2e tests

* Fix missing icon

* Fix navigation through top nav bar

* Restore migration for billing table

---------

Co-authored-by: Eric P Green <[email protected]>
  • Loading branch information
AdityaHegde and ericpgreen2 authored Oct 1, 2024
1 parent 4fb0701 commit de4dcb8
Show file tree
Hide file tree
Showing 196 changed files with 3,611 additions and 2,652 deletions.
2 changes: 1 addition & 1 deletion admin/database/postgres/migrations/0045.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ CREATE TABLE billing_issues (
created_on TIMESTAMPTZ NOT NULL DEFAULT now(),
FOREIGN KEY (org_id) REFERENCES orgs (id) ON DELETE CASCADE,
CONSTRAINT billing_issues_org_id_type_unique UNIQUE (org_id, type)
);
);
2 changes: 1 addition & 1 deletion admin/database/postgres/migrations/0046.sql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ALTER TABLE magic_auth_tokens ADD COLUMN title TEXT NOT NULL DEFAULT '';
ALTER TABLE magic_auth_tokens ADD COLUMN title TEXT NOT NULL DEFAULT '';
12 changes: 6 additions & 6 deletions admin/database/postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -2163,16 +2163,16 @@ func (c *connection) decryptMap(m map[string]string, encKeyID string) (map[strin
// magicAuthTokenDTO wraps database.MagicAuthToken, using the pgtype package to handly types that pgx can't read directly into their native Go types.
type magicAuthTokenDTO struct {
*database.MagicAuthToken
Attributes pgtype.JSON `db:"attributes"`
MetricsViewFields pgtype.TextArray `db:"metrics_view_fields"`
Attributes pgtype.JSON `db:"attributes"`
Fields pgtype.TextArray `db:"fields"`
}

func (c *connection) magicAuthTokenFromDTO(dto *magicAuthTokenDTO, fetchSecret bool) (*database.MagicAuthToken, error) {
err := dto.Attributes.AssignTo(&dto.MagicAuthToken.Attributes)
if err != nil {
return nil, err
}
err = dto.MetricsViewFields.AssignTo(&dto.MagicAuthToken.Fields)
err = dto.Fields.AssignTo(&dto.MagicAuthToken.Fields)
if err != nil {
return nil, err
}
Expand All @@ -2193,16 +2193,16 @@ func (c *connection) magicAuthTokenFromDTO(dto *magicAuthTokenDTO, fetchSecret b
// magicAuthTokenWithUserDTO wraps database.MagicAuthTokenWithUser, using the pgtype package to handly types that pgx can't read directly into their native Go types.
type magicAuthTokenWithUserDTO struct {
*database.MagicAuthTokenWithUser
Attributes pgtype.JSON `db:"attributes"`
MetricsViewFields pgtype.TextArray `db:"metrics_view_fields"`
Attributes pgtype.JSON `db:"attributes"`
Fields pgtype.TextArray `db:"fields"`
}

func (c *connection) magicAuthTokenWithUserFromDTO(dto *magicAuthTokenWithUserDTO) (*database.MagicAuthTokenWithUser, error) {
err := dto.Attributes.AssignTo(&dto.MagicAuthTokenWithUser.Attributes)
if err != nil {
return nil, err
}
err = dto.MetricsViewFields.AssignTo(&dto.MagicAuthToken.Fields)
err = dto.Fields.AssignTo(&dto.MagicAuthToken.Fields)
if err != nil {
return nil, err
}
Expand Down
6 changes: 4 additions & 2 deletions scripts/tsc-with-whitelist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ web-admin/src/features/scheduled-reports/selectors.ts: error TS2345
web-admin/src/features/view-as-user/clearViewedAsUser.ts: error TS18047
web-admin/src/features/view-as-user/clearViewedAsUser.ts: error TS2322
web-admin/src/features/view-as-user/setViewedAsUser.ts: error TS2322
web-admin/src/routes/[organization]/[project]/-/dashboards/+page.ts: error TS2307
web-admin/src/features/projects/github/GithubData.ts: error TS2769
web-admin/src/routes/[organization]/[project]/[dashboard]/+page.ts: error TS2307
web-admin/src/routes/[organization]/[project]/-/dashboards/+page.ts: error TS2307
web-common/src/components/button-group/ButtonGroup.spec.ts: error TS2345
web-common/src/components/data-graphic/actions/mouse-position-to-domain-action-factory.ts: error TS2322
web-common/src/components/data-graphic/actions/outline.ts: error TS18047
Expand Down Expand Up @@ -97,7 +98,7 @@ web-common/src/features/metrics-views/errors.ts: error TS2322
web-common/src/features/metrics-views/errors.ts: error TS2345
web-common/src/features/metrics-views/metrics-internal-store.ts: error TS18048
web-common/src/features/metrics-views/metrics-internal-store.ts: error TS2345
web-common/src/features/metrics-views/workspace/editor/create-placeholder.ts: error TS2322
web-common/src/features/metrics-views/editor/create-placeholder.ts: error TS2322
web-common/src/features/models/selectors.ts: error TS18048
web-common/src/features/models/selectors.ts: error TS2345
web-common/src/features/models/utils/embedded.ts: error TS18048
Expand Down Expand Up @@ -142,6 +143,7 @@ web-common/src/runtime-client/invalidation.ts: error TS18048
web-common/src/runtime-client/invalidation.ts: error TS2345
web-common/src/runtime-client/watch-request-client.ts: error TS2322
web-common/vite.config.ts: error TS2339
web-local/src/routes//dashboard/[name]/+page.ts: error TS2307
"

# Run TypeScript compiler and find all distinct error per file
Expand Down
19 changes: 11 additions & 8 deletions web-admin/src/features/alerts/CreateAlert.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<script lang="ts">
import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte";
import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte";
import { useMetricsView } from "@rilldata/web-common/features/dashboards/selectors";
import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
import { Button } from "@rilldata/web-common/components/button";
import { BellPlusIcon } from "lucide-svelte";
import CreateAlertForm from "@rilldata/web-common/features/alerts/CreateAlertForm.svelte";
import GuardedDialog from "@rilldata/web-common/components/dialog-v2/GuardedDialog.svelte";
import {
DialogContent,
DialogTrigger,
} from "@rilldata/web-common/components/dialog-v2/index";
import GuardedDialog from "@rilldata/web-common/components/dialog-v2/GuardedDialog.svelte";
import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte";
import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte";
import CreateAlertForm from "@rilldata/web-common/features/alerts/CreateAlertForm.svelte";
import { useMetricsViewValidSpec } from "@rilldata/web-common/features/dashboards/selectors";
import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
import { BellPlusIcon } from "lucide-svelte";
const {
selectors: {
Expand All @@ -20,7 +20,10 @@
metricsViewName,
} = getStateManagers();
$: metricsView = useMetricsView($runtime?.instanceId, $metricsViewName);
$: metricsView = useMetricsViewValidSpec(
$runtime?.instanceId,
$metricsViewName,
);
$: hasTimeDimension = !!$metricsView?.data?.timeDimension;
let open = false;
Expand Down
12 changes: 6 additions & 6 deletions web-admin/src/features/alerts/metadata/AlertFilters.svelte
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<script lang="ts">
import MetadataLabel from "@rilldata/web-admin/features/scheduled-reports/metadata/MetadataLabel.svelte";
import TimeRangeReadOnly from "@rilldata/web-common/features/dashboards/filters/TimeRangeReadOnly.svelte";
import DimensionFilterReadOnlyChip from "@rilldata/web-common/features/dashboards/filters/dimension-filters/DimensionFilterReadOnlyChip.svelte";
import MeasureFilterReadOnlyChip from "@rilldata/web-common/features/dashboards/filters/measure-filters/MeasureFilterReadOnlyChip.svelte";
import { splitWhereFilter } from "@rilldata/web-common/features/dashboards/filters/measure-filters/measure-filter-utils";
import { useDashboard } from "@rilldata/web-common/features/dashboards/selectors";
import { useMetricsView } from "@rilldata/web-common/features/dashboards/selectors";
import { getDimensionFilters } from "@rilldata/web-common/features/dashboards/state-managers/selectors/dimension-filters";
import { getMeasureFilters } from "@rilldata/web-common/features/dashboards/state-managers/selectors/measure-filters";
import type { DimensionThresholdFilter } from "@rilldata/web-common/features/dashboards/stores/metrics-explorer-entity";
Expand All @@ -14,8 +16,6 @@
import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
import { flip } from "svelte/animate";
import { fly } from "svelte/transition";
import TimeRangeReadOnly from "@rilldata/web-common/features/dashboards/filters/TimeRangeReadOnly.svelte";
import MeasureFilterReadOnlyChip from "@rilldata/web-common/features/dashboards/filters/measure-filters/MeasureFilterReadOnlyChip.svelte";
export let metricsViewName: string;
export let filters: V1Expression | undefined;
Expand All @@ -36,13 +36,13 @@
havingFilter = dimensionThresholdFilters;
}
$: dashboard = useDashboard($runtime.instanceId, metricsViewName);
$: metricsView = useMetricsView($runtime.instanceId, metricsViewName);
$: dimensionIdMap = getMapFromArray(
$dashboard.data?.metricsView?.state?.validSpec?.dimensions ?? [],
$metricsView.data?.metricsView?.state?.validSpec?.dimensions ?? [],
(dimension) => dimension.name,
);
$: measureIdMap = getMapFromArray(
$dashboard.data?.metricsView?.state?.validSpec?.measures ?? [],
$metricsView.data?.metricsView?.state?.validSpec?.measures ?? [],
(measure) => measure.name,
);
Expand Down
16 changes: 9 additions & 7 deletions web-admin/src/features/alerts/metadata/AlertMetadata.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import ThreeDot from "@rilldata/web-common/components/icons/ThreeDot.svelte";
import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte";
import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte";
import { useDashboard } from "@rilldata/web-common/features/dashboards/selectors";
import { useExploreValidSpec } from "@rilldata/web-common/features/explores/selectors";
import {
getRuntimeServiceListResourcesQueryKey,
type V1MetricsViewAggregationRequest,
Expand All @@ -39,9 +39,9 @@
// Get dashboard
$: dashboardName = useAlertDashboardName($runtime.instanceId, alert);
$: dashboard = useDashboard($runtime.instanceId, $dashboardName.data);
$: dashboardTitle =
$dashboard.data?.metricsView.spec.title || $dashboardName.data;
$: dashboard = useExploreValidSpec($runtime.instanceId, $dashboardName.data);
$: metricsViewName = $dashboard.data?.explore?.metricsView;
$: dashboardTitle = $dashboard.data?.explore?.title || $dashboardName.data;
$: dashboardDoesNotExist = $dashboard.error?.response?.status === 404;
$: alertSpec = $alertQuery.data?.resource?.alert?.spec;
Expand Down Expand Up @@ -99,7 +99,7 @@
</h1>
<div class="grow" />
{#if !$isAlertCreatedByCode.data}
<EditAlert {alertSpec} metricsViewName={$dashboardName.data} />
<EditAlert {alertSpec} {metricsViewName} />
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<IconButton>
Expand Down Expand Up @@ -134,7 +134,9 @@
</Tooltip>
</div>
{:else}
<a href={`/${organization}/${project}/${$dashboardName.data}`}>
<a
href={`/${organization}/${project}/explore/${$dashboardName.data}`}
>
{dashboardTitle}
</a>
{/if}
Expand Down Expand Up @@ -170,7 +172,7 @@

<!-- Filters -->
<AlertFilters
metricsViewName={$dashboardName.data}
{metricsViewName}
filters={metricsViewAggregationRequest?.where}
timeRange={metricsViewAggregationRequest?.timeRange}
comparisonTimeRange={metricsViewAggregationRequest?.comparisonTimeRange}
Expand Down
11 changes: 9 additions & 2 deletions web-admin/src/features/alerts/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createAdminServiceSearchProjectUsers } from "@rilldata/web-admin/client";
import { getExploreName } from "@rilldata/web-admin/features/dashboards/query-mappers/utils";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors";
import {
createRuntimeServiceGetResource,
Expand Down Expand Up @@ -36,9 +37,15 @@ export function useAlertDashboardName(instanceId: string, name: string) {
{
query: {
select: (data) => {
const alertSpec = data.resource?.alert?.spec;
if (!alertSpec) return "";

if (alertSpec.annotations.web_open_path)
return getExploreName(alertSpec.annotations.web_open_path);

const queryArgsJson = JSON.parse(
data.resource.alert.spec.resolverProperties.query_args_json ||
data.resource.alert.spec.queryArgsJson ||
alertSpec.resolverProperties.query_args_json ||
alertSpec.queryArgsJson ||
"{}",
);

Expand Down
26 changes: 14 additions & 12 deletions web-admin/src/features/bookmarks/BaseBookmarkForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,38 @@
import type { BookmarkFormValues } from "@rilldata/web-admin/features/bookmarks/form-utils";
import { getPrettySelectedTimeRange } from "@rilldata/web-admin/features/bookmarks/selectors";
import ProjectAccessControls from "@rilldata/web-admin/features/projects/ProjectAccessControls.svelte";
import Select from "@rilldata/web-common/components/forms/Select.svelte";
import Input from "@rilldata/web-common/components/forms/Input.svelte";
import Label from "@rilldata/web-common/components/forms/Label.svelte";
import Select from "@rilldata/web-common/components/forms/Select.svelte";
import Switch from "@rilldata/web-common/components/forms/Switch.svelte";
import Input from "@rilldata/web-common/components/forms/Input.svelte";
import Tooltip from "@rilldata/web-common/components/tooltip/Tooltip.svelte";
import TooltipContent from "@rilldata/web-common/components/tooltip/TooltipContent.svelte";
import FilterChipsReadOnly from "@rilldata/web-common/features/dashboards/filters/FilterChipsReadOnly.svelte";
import { useDashboardStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { useExploreStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
import type { V1TimeRange } from "@rilldata/web-common/runtime-client";
import { runtime } from "@rilldata/web-common/runtime-client/runtime-store";
import type { createForm } from "svelte-forms-lib";
import { InfoIcon } from "lucide-svelte";
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
import type { createForm } from "svelte-forms-lib";
export let metricsViewName: string;
export let exploreName: string;
export let formState: ReturnType<typeof createForm<BookmarkFormValues>>;
$: dashboardStore = useDashboardStore(metricsViewName);
$: exploreStore = useExploreStore(exploreName);
let timeRange: V1TimeRange;
$: timeRange = {
isoDuration: $dashboardStore.selectedTimeRange?.name,
start: $dashboardStore.selectedTimeRange?.start?.toISOString() ?? "",
end: $dashboardStore.selectedTimeRange?.end?.toISOString() ?? "",
isoDuration: $exploreStore.selectedTimeRange?.name,
start: $exploreStore.selectedTimeRange?.start?.toISOString() ?? "",
end: $exploreStore.selectedTimeRange?.end?.toISOString() ?? "",
};
$: selectedTimeRange = getPrettySelectedTimeRange(
queryClient,
$runtime?.instanceId,
metricsViewName,
exploreName,
);
const { form, errors } = formState;
Expand Down Expand Up @@ -68,9 +70,9 @@ Managed bookmarks will be available to all viewers of this dashboard.`;
<div class="text-gray-500">Inherited from underlying dashboard view.</div>
</Label>
<FilterChipsReadOnly
dimensionThresholdFilters={$dashboardStore.dimensionThresholdFilters}
filters={$dashboardStore.whereFilter}
{metricsViewName}
dimensionThresholdFilters={$exploreStore.dimensionThresholdFilters}
filters={$exploreStore.whereFilter}
{exploreName}
{timeRange}
/>
</div>
Expand Down
39 changes: 20 additions & 19 deletions web-admin/src/features/bookmarks/BookmarkDialog.svelte
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
<script lang="ts">
import { page } from "$app/stores";
import BaseBookmarkForm from "@rilldata/web-admin/features/bookmarks/BaseBookmarkForm.svelte";
import type { BookmarkFormValues } from "@rilldata/web-admin/features/bookmarks/form-utils";
import { useProjectId } from "@rilldata/web-admin/features/projects/selectors";
import * as Dialog from "@rilldata/web-common/components/dialog-v2";
import {
createAdminServiceCreateBookmark,
createAdminServiceUpdateBookmark,
getAdminServiceListBookmarksQueryKey,
} from "@rilldata/web-admin/client";
import { Button } from "@rilldata/web-common/components/button";
import BaseBookmarkForm from "@rilldata/web-admin/features/bookmarks/BaseBookmarkForm.svelte";
import type { BookmarkFormValues } from "@rilldata/web-admin/features/bookmarks/form-utils";
import { getBookmarkDataForDashboard } from "@rilldata/web-admin/features/bookmarks/getBookmarkDataForDashboard";
import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus";
import { useDashboardStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors";
import type { BookmarkEntry } from "@rilldata/web-admin/features/bookmarks/selectors";
import { useProjectId } from "@rilldata/web-admin/features/projects/selectors";
import { Button } from "@rilldata/web-common/components/button";
import * as Dialog from "@rilldata/web-common/components/dialog-v2";
import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
import { useExploreStore } from "@rilldata/web-common/features/dashboards/stores/dashboard-stores";
import { useTimeControlStore } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store";
import { ResourceKind } from "@rilldata/web-common/features/entity-management/resource-selectors";
import { eventBus } from "@rilldata/web-common/lib/event-bus/event-bus";
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
import { createForm } from "svelte-forms-lib";
import * as yup from "yup";
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
import { useTimeControlStore } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store";
import { getStateManagers } from "@rilldata/web-common/features/dashboards/state-managers/state-managers";
export let metricsViewName: string;
export let exploreName: string;
export let bookmark: BookmarkEntry | null = null;
export let onClose = () => {};
Expand Down Expand Up @@ -52,7 +53,7 @@
description: values.description,
shared: values.shared === "true",
data: getBookmarkDataForDashboard(
$dashboardStore,
$exploreStore,
values.filtersOnly,
values.absoluteTimeRange,
$timeControlsStore,
Expand All @@ -65,11 +66,11 @@
displayName: values.displayName,
description: values.description,
projectId: $projectId.data ?? "",
resourceKind: ResourceKind.MetricsView,
resourceName: metricsViewName,
resourceKind: ResourceKind.Explore,
resourceName: exploreName,
shared: values.shared === "true",
data: getBookmarkDataForDashboard(
$dashboardStore,
$exploreStore,
values.filtersOnly,
values.absoluteTimeRange,
$timeControlsStore,
Expand All @@ -83,8 +84,8 @@
await queryClient.refetchQueries(
getAdminServiceListBookmarksQueryKey({
projectId: $projectId.data ?? "",
resourceKind: ResourceKind.MetricsView,
resourceName: metricsViewName,
resourceKind: ResourceKind.Explore,
resourceName: exploreName,
}),
);
eventBus.emit("notification", {
Expand All @@ -96,7 +97,7 @@
const { handleSubmit, handleReset } = formState;
$: ({ params } = $page);
$: dashboardStore = useDashboardStore(metricsViewName);
$: exploreStore = useExploreStore(exploreName);
$: projectId = useProjectId(params.organization, params.project);
</script>

Expand All @@ -113,7 +114,7 @@
</Dialog.Title>
</Dialog.Header>

<BaseBookmarkForm {formState} {metricsViewName} />
<BaseBookmarkForm {formState} {metricsViewName} {exploreName} />

<div class="flex flex-row mt-4 gap-2">
<div class="grow" />
Expand Down
Loading

0 comments on commit de4dcb8

Please sign in to comment.