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

Canvas: activate comparison by default, use global time #6577

Merged
merged 2 commits into from
Feb 5, 2025
Merged
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
1 change: 0 additions & 1 deletion web-common/src/features/canvas/components/charts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ export class ChartComponent extends BaseCanvasComponent<ChartSpec> {
type: "quantitative",
field: measure,
},
time_range: "PT24H",
};
}
}
90 changes: 44 additions & 46 deletions web-common/src/features/canvas/components/kpi/KPI.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
export let rendererProperties: V1ComponentSpecRendererProperties;

const ctx = getCanvasStateManagers();
const { spec } = ctx.canvasEntity;
const {
spec,
timeControls: { showTimeComparison },
} = ctx.canvasEntity;

let containerWidth: number;
let containerHeight: number;
Expand All @@ -51,9 +54,9 @@
kpiProperties,
$schema.isValid,
);
$: showComparison = $showTimeComparison || comparisonTimeRange;

$: sparkline = useKPISparkline(ctx, kpiProperties, $schema.isValid);

$: sparkData = $sparkline?.data || [];
$: isEmptySparkline = sparkData.every((y) => y[measureName] === null);

Expand Down Expand Up @@ -84,7 +87,10 @@

$: sparklineHeight =
containerHeight -
(comparisonValue && $comparisonValue?.data === undefined ? 80 : 100);
(!showComparison ||
(comparisonValue && $comparisonValue?.data === undefined)
? 80
: 104);

function getFormattedDiff(comparisonValue) {
if (!$measureValue.data) return "";
Expand All @@ -102,53 +108,45 @@
>
<div class="measure-label">{$measure?.displayName || measureName}</div>
<div class="measure-value">{measureValueFormatted}</div>
<div class="flex items-center">
{#if $comparisonValue.data}
<div class="flex items-baseline gap-x-3 text-sm">
{#if showComparison && $comparisonValue.data}
<div class="flex items-baseline gap-x-3 text-sm">
<div
role="complementary"
class="w-fit max-w-full overflow-hidden text-ellipsis text-gray-500"
class:font-semibold={$measureValue.data && $measureValue.data >= 0}
>
{#if $comparisonValue.data != null}
{getFormattedDiff($comparisonValue.data)}
{:else}
<span class="ui-copy-disabled-faint italic" style:font-size=".9em"
>no change</span
>
{/if}
</div>
{#if comparisonPercChange != null && !measureIsPercentage}
<div
role="complementary"
class="w-fit max-w-full overflow-hidden text-ellipsis text-gray-500"
class:font-semibold={$measureValue.data &&
$measureValue.data >= 0}
class="w-fit font-semibold ui-copy-inactive"
class:text-red-500={$measureValue.data && $measureValue.data < 0}
>
{#if $comparisonValue.data != null}
{getFormattedDiff($comparisonValue.data)}
{:else}
<span
class="ui-copy-disabled-faint italic"
style:font-size=".9em">no change</span
>
{/if}
<PercentageChange
color="text-gray-500"
showPosSign
tabularNumber={false}
value={formatMeasurePercentageDifference(comparisonPercChange)}
/>
</div>
{#if comparisonPercChange != null && !measureIsPercentage}
<div
role="complementary"
class="w-fit font-semibold ui-copy-inactive"
class:text-red-500={$measureValue.data &&
$measureValue.data < 0}
>
<PercentageChange
color="text-gray-500"
showPosSign
tabularNumber={false}
value={formatMeasurePercentageDifference(
comparisonPercChange,
)}
/>
</div>
{/if}
{#if comparisonTimeRange}
<span class="comparison-range">
vs last {humaniseISODuration(
comparisonTimeRange?.toUpperCase(),
false,
)}
</span>
{/if}
</div>
{/if}
</div>

{/if}
{#if comparisonTimeRange}
<span class="comparison-range">
vs last {humaniseISODuration(
comparisonTimeRange?.toUpperCase(),
false,
)}
</span>
{/if}
</div>
{/if}
{#if containerHeight && containerWidth && showSparkline && sparkData.length && !isEmptySparkline}
<SimpleDataGraphic
height={sparklineHeight}
Expand Down
1 change: 0 additions & 1 deletion web-common/src/features/canvas/components/kpi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ export class KPIComponent extends BaseCanvasComponent<KPISpec> {
return {
metrics_view,
measure,
time_range: "PT24H",
sparkline: true,
};
}
Expand Down
1 change: 0 additions & 1 deletion web-common/src/features/canvas/components/table/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ export class TableCanvasComponent extends BaseCanvasComponent<TableSpec> {
metrics_view,
measures: [measure],
row_dimensions: [dimension],
time_range: "PT24H",
};
}
}
14 changes: 13 additions & 1 deletion web-common/src/features/canvas/inspector/ComponentsEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import VegaConfigInput from "@rilldata/web-common/features/canvas/inspector/VegaConfigInput.svelte";
import { getCanvasStateManagers } from "@rilldata/web-common/features/canvas/state-managers/state-managers";
import type { FileArtifact } from "@rilldata/web-common/features/entity-management/file-artifact";
import Spinner from "@rilldata/web-common/features/entity-management/Spinner.svelte";
import { EntityStatus } from "@rilldata/web-common/features/entity-management/types";
import SidebarWrapper from "@rilldata/web-common/features/visual-editing/SidebarWrapper.svelte";
import ComponentTabs from "./ComponentTabs.svelte";
import FiltersMapper from "./filters/FiltersMapper.svelte";
Expand Down Expand Up @@ -67,9 +69,19 @@
<VegaConfigInput {component} paramValues={rendererProperties} />
{/if}
{/key}
{:else if !renderer}
<div class="inspector-center">
<Spinner status={EntityStatus.Running} size="16px" />
</div>
{:else}
<div>
<div class="inspector-center">
Unknown Component {renderer}
</div>
{/if}
</SidebarWrapper>

<style lang="postcss">
.inspector-center {
@apply flex items-center justify-center h-full w-full;
}
</style>
30 changes: 27 additions & 3 deletions web-common/src/features/canvas/stores/canvas-time-control.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { CanvasResponse } from "@rilldata/web-common/features/canvas/selector";
import type { CanvasSpecResponseStore } from "@rilldata/web-common/features/canvas/types";
import { getTimeGrain } from "@rilldata/web-common/features/dashboards/time-controls/time-control-store";
import {
getComparisonTimeRange,
getTimeGrain,
} from "@rilldata/web-common/features/dashboards/time-controls/time-control-store";
import { queryClient } from "@rilldata/web-common/lib/svelte-query/globalQueryClient";
import { isoDurationToFullTimeRange } from "@rilldata/web-common/lib/time/ranges/iso-ranges";
import {
Expand All @@ -10,6 +13,7 @@ import {
} from "@rilldata/web-common/lib/time/types";
import {
createQueryServiceMetricsViewTimeRange,
V1ExploreComparisonMode,
V1TimeGrain,
type RpcStatus,
} from "@rilldata/web-common/runtime-client";
Expand Down Expand Up @@ -61,16 +65,22 @@ export class CanvasTimeControls {

setInitialState(validSpecStore: CanvasSpecResponseStore) {
this.timeRangeSummaryStore(runtime, validSpecStore);

const selectedTimezone = get(this.selectedTimezone);
const comparisonTimeRange = get(this.selectedComparisonTimeRange);

const store = derived(
[this.allTimeRange, validSpecStore],
([allTimeRange, validSpec]) => {
if (!validSpec.data) {
this.isReady.set(false);
}

const selectedTimezone = get(this.selectedTimezone);
const { defaultPreset } = validSpec.data?.canvas || {};
const timeRanges = validSpec?.data?.canvas?.timeRanges;

const defaultTimeRange = isoDurationToFullTimeRange(
validSpec.data?.canvas?.defaultPreset?.timeRange,
defaultPreset?.timeRange,
allTimeRange.start,
allTimeRange.end,
selectedTimezone,
Expand All @@ -88,6 +98,20 @@ export class CanvasTimeControls {
V1TimeGrain.TIME_GRAIN_UNSPECIFIED,
);

if (
defaultPreset?.comparisonMode ===
V1ExploreComparisonMode.EXPLORE_COMPARISON_MODE_TIME
) {
const newComparisonRange = getComparisonTimeRange(
timeRanges,
allTimeRange,
newTimeRange,
comparisonTimeRange,
);
this.selectedComparisonTimeRange.set(newComparisonRange);
this.showTimeComparison.set(true);
}

this.selectedTimeRange.set(newTimeRange);
this.isReady.set(true);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
} from "@rilldata/web-common/lib/time/types";
import {
type V1ExploreSpec,
type V1ExploreTimeRange,
type V1MetricsViewSpec,
type V1MetricsViewTimeRangeResponse,
V1TimeGrain,
Expand Down Expand Up @@ -264,7 +265,7 @@ function calculateComparisonTimeRangePartial(
timeRangeState: TimeRangeState,
): ComparisonTimeRangeState {
const selectedComparisonTimeRange = getComparisonTimeRange(
explore,
explore.timeRanges,
allTimeRange,
timeRangeState.selectedTimeRange,
metricsExplorer.selectedComparisonTimeRange,
Expand Down Expand Up @@ -393,19 +394,16 @@ export function getTimeGrain(
return timeGrain;
}

function getComparisonTimeRange(
explore: V1ExploreSpec,
allTimeRange: DashboardTimeControls | undefined,
export function getComparisonTimeRange(
timeRanges: V1ExploreTimeRange[] | undefined,
allTimeRange: TimeRange | undefined,
timeRange: DashboardTimeControls | undefined,
comparisonTimeRange: DashboardTimeControls | undefined,
) {
if (!timeRange || !timeRange.name || !allTimeRange) return undefined;

if (!comparisonTimeRange?.name) {
const comparisonOption = inferCompareTimeRange(
explore.timeRanges,
timeRange.name,
);
const comparisonOption = inferCompareTimeRange(timeRanges, timeRange.name);
const range = getTimeComparisonParametersForComponent(
comparisonOption,
allTimeRange.start,
Expand Down
8 changes: 7 additions & 1 deletion web-common/src/features/file-explorer/new-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,14 @@ vega_lite: |
}
}`;
case ResourceKind.Canvas:
return `type: canvas
return `# Explore YAML
# Reference documentation: https://docs.rilldata.com/reference/project-files/canvas-dashboards
type: canvas
title: "Canvas Dashboard"
defaults:
time_range: PT24H
comparison_mode: time
`;
case ResourceKind.Theme:
return `# Theme YAML
Expand Down
Loading