Skip to content

Commit

Permalink
feat: extend dash types to support nested layout
Browse files Browse the repository at this point in the history
JIRA: LX-588
risk: low
  • Loading branch information
ivan-nejezchleb committed Nov 4, 2024
1 parent d1a5e8c commit d9f4347
Show file tree
Hide file tree
Showing 16 changed files with 141 additions and 39 deletions.
8 changes: 7 additions & 1 deletion libs/sdk-model/api/sdk-model.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1341,6 +1341,12 @@ export interface IDashboardLayoutSizeByScreenSize {
xs?: IDashboardLayoutSize;
}

// @public
export interface IDashboardLayoutWidget extends IDashboardLayout<IDashboardWidget>, IBaseWidget, IDashboardObjectIdentity {
// (undocumented)
type: "IDashboardLayout";
}

// @public
export interface IDashboardMetadataObject extends IMetadataObject {
// (undocumented)
Expand Down Expand Up @@ -1386,7 +1392,7 @@ export interface IDashboardPluginLink {
}

// @public
export type IDashboardWidget = IWidget | IWidgetDefinition | IDashboardLayout<IDashboardWidget>;
export type IDashboardWidget = IWidget | IWidgetDefinition | IDashboardLayoutWidget;

// @public
export interface IDataColumn {
Expand Down
18 changes: 16 additions & 2 deletions libs/sdk-model/src/dashboard/layout.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// (C) 2019-2022 GoodData Corporation
// (C) 2019-2024 GoodData Corporation
import isEmpty from "lodash/isEmpty.js";
import isArray from "lodash/isArray.js";
import { IWidget, IWidgetDefinition, isWidget, isWidgetDefinition } from "./widget.js";
import { IDashboardObjectIdentity } from "./common.js";
import { IBaseWidget } from "./baseWidget.js";

/**
* Classification of the screen size according to its size with respect to the set breakpoints.
Expand All @@ -10,12 +12,24 @@ import { IWidget, IWidgetDefinition, isWidget, isWidgetDefinition } from "./widg
*/
export type ScreenSize = "xl" | "lg" | "md" | "sm" | "xs";

/**
* Widget representing nested layout
*
* @public
*/
export interface IDashboardLayoutWidget
extends IDashboardLayout<IDashboardWidget>,
IBaseWidget,
IDashboardObjectIdentity {
type: "IDashboardLayout";
}

/**
* Default dashboard widgets - kpi widget, insight widget, or nested layout.
*
* @public
*/
export type IDashboardWidget = IWidget | IWidgetDefinition | IDashboardLayout<IDashboardWidget>;
export type IDashboardWidget = IWidget | IWidgetDefinition | IDashboardLayoutWidget;

/**
* Type-guard testing whether the provided object is an instance of {@link IDashboardWidget}.
Expand Down
1 change: 1 addition & 0 deletions libs/sdk-model/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ export type {
IDashboardLayoutSize,
IDashboardLayoutSizeByScreenSize,
IDashboardLayoutItem,
IDashboardLayoutWidget,
ScreenSize,
} from "./dashboard/layout.js";
export {
Expand Down
25 changes: 18 additions & 7 deletions libs/sdk-ui-dashboard/api/sdk-ui-dashboard.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ import { DrillState as DrillState_2 } from './drillState.js';
import { EntityId } from '@reduxjs/toolkit';
import { EntityState } from '@reduxjs/toolkit';
import { ExplicitDrill } from '@gooddata/sdk-ui';
import { ExtendedDashboardWidget as ExtendedDashboardWidget_2 } from '../../index.js';
import { FilterContextItem } from '@gooddata/sdk-model';
import { FilterViewDialogMode as FilterViewDialogMode_2 } from './uiState.js';
import { GoodDataSdkError } from '@gooddata/sdk-ui';
Expand Down Expand Up @@ -3532,11 +3531,20 @@ export type ExtendedDashboardItemTypes<T extends ReadonlyArray<ExtendedDashboard
export type ExtendedDashboardLayoutSection = IDashboardLayoutSection<ExtendedDashboardWidget>;

// @public
export type ExtendedDashboardWidget = IWidget | ICustomWidget;
export interface ExtendedDashboardLayoutWidget extends IDashboardLayout<ExtendedDashboardWidget>, IBaseWidget, IDashboardObjectIdentity {
// (undocumented)
type: "IDashboardLayout";
}

// @public
export type ExtendedDashboardWidget = IWidget | ICustomWidget | ExtendedDashboardLayoutWidget;

// @internal
export function extendedWidgetDebugStr(widget: ExtendedDashboardWidget): string;

// @public
export type FilterableDashboardWidget = IWidget | ICustomWidget;

// @internal (undocumented)
export const FilterBar: (props: IFilterBarProps) => JSX.Element;

Expand Down Expand Up @@ -5491,6 +5499,9 @@ export function isDrillDownDefinition(obj: unknown): obj is IDrillDownDefinition
// @alpha
export const isDrillTargetsAdded: (obj: unknown) => obj is DrillTargetsAdded;

// @public
export function isExtendedDashboardLayoutWidget(obj: unknown): obj is ExtendedDashboardLayoutWidget;

// @beta (undocumented)
export interface IShareButtonProps {
// (undocumented)
Expand Down Expand Up @@ -5660,7 +5671,7 @@ export interface IUseDashboardScheduledEmailsFiltersProps {
// (undocumented)
scheduledExportToEdit?: IAutomationMetadataObject;
// (undocumented)
widget?: ExtendedDashboardWidget;
widget?: FilterableDashboardWidget;
}

// @alpha (undocumented)
Expand All @@ -5672,7 +5683,7 @@ export interface IUseFiltersForDashboardScheduledExportProps {
export interface IUseFiltersForWidgetScheduledExportProps {
insight?: IInsightDefinition;
scheduledExportToEdit?: IAutomationMetadataObjectDefinition;
widget?: ExtendedDashboardWidget;
widget?: FilterableDashboardWidget;
}

// @public
Expand Down Expand Up @@ -6167,7 +6178,7 @@ export type OptionalProvider<T> = T extends (...args: infer TArgs) => infer TRes
// @public (undocumented)
export type OptionalRichTextComponentProvider = OptionalProvider<RichTextComponentProvider>;

// @public (undocumented)
// @alpha (undocumented)
export type OptionalVisualizationSwitcherComponentProvider = OptionalProvider<VisualizationSwitcherComponentProvider>;

// @alpha (undocumented)
Expand Down Expand Up @@ -9054,7 +9065,7 @@ export const useDashboardScheduledEmails: () => {
automations: IAutomationMetadataObject[];
automationsCount: number;
numberOfAvailableDestinations: number;
widget: ExtendedDashboardWidget_2 | undefined;
widget: IWidget | undefined;
insight: IInsight | undefined;
automationsLoading: boolean;
automationsError: GoodDataSdkError | undefined;
Expand Down Expand Up @@ -9327,7 +9338,7 @@ export function useWidgetExecutionsHandler(widgetRef: ObjRef): {
};

// @public
export function useWidgetFilters(widget: ExtendedDashboardWidget | undefined | null, insight?: IInsightDefinition): QueryProcessingState<IFilter[]>;
export function useWidgetFilters(widget: FilterableDashboardWidget | undefined | null, insight?: IInsightDefinition): QueryProcessingState<IFilter[]>;

// @internal (undocumented)
export function useWidgetSelection(widgetRef?: ObjRef): IUseWidgetSelectionResult;
Expand Down
3 changes: 3 additions & 0 deletions libs/sdk-ui-dashboard/src/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export type {
RelativeIndex,
ExtendedDashboardItemType,
ExtendedDashboardItemTypes,
ExtendedDashboardLayoutWidget,
FilterableDashboardWidget,
} from "./types/layoutTypes.js";
export {
newCustomWidget,
Expand All @@ -50,6 +52,7 @@ export {
isCustomWidgetBase,
isCustomWidget,
extendedWidgetDebugStr,
isExtendedDashboardLayoutWidget,
} from "./types/layoutTypes.js";
export type {
FilterOp,
Expand Down
25 changes: 14 additions & 11 deletions libs/sdk-ui-dashboard/src/model/queryServices/queryWidgetFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ import {
IVisualizationSwitcherWidget,
} from "@gooddata/sdk-model";
import { QueryWidgetFilters } from "../queries/widgets.js";
import { selectAllFiltersForWidgetByRef, selectWidgetByRef } from "../store/layout/layoutSelectors.js";
import {
selectAllFiltersForWidgetByRef,
selectAnalyticalWidgetByRef,
} from "../store/layout/layoutSelectors.js";
import { selectInsightByRef } from "../store/insights/insightsSelectors.js";
import { invalidQueryArguments } from "../events/general.js";
import compact from "lodash/compact.js";
Expand All @@ -43,7 +46,7 @@ import { DashboardState } from "../store/types.js";
import { resolveDisplayFormMetadata } from "../utils/displayFormResolver.js";
import { invariant } from "ts-invariant";
import isEmpty from "lodash/isEmpty.js";
import { ExtendedDashboardWidget, ICustomWidget } from "../types/layoutTypes.js";
import { ICustomWidget, FilterableDashboardWidget } from "../types/layoutTypes.js";
import { selectSupportsMultipleDateFilters } from "../store/backendCapabilities/backendCapabilitiesSelectors.js";
import { selectAttributeFilterConfigsDisplayAsLabelMap } from "../store/attributeFilterConfigs/attributeFilterConfigsSelectors.js";

Expand Down Expand Up @@ -108,7 +111,7 @@ function selectDateDatasetsForDateFilters(

function* getResolvedInsightAttributeFilters(
ctx: DashboardContext,
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
dashboardAttributeFilters: IAttributeFilter[],
insightAttributeFilters: IAttributeFilter[],
): SagaIterator<IAttributeFilter[]> {
Expand All @@ -125,7 +128,7 @@ function* getResolvedInsightAttributeFilters(

function* getResolvedAttributeFilters(
ctx: DashboardContext,
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
attributeFilters: IAttributeFilter[],
): SagaIterator<IAttributeFilter[]> {
const attributeFilterDisplayFormPairs: SagaReturnType<typeof loadDisplayFormsForAttributeFilters> =
Expand All @@ -144,7 +147,7 @@ function* getResolvedAttributeFilters(
}

function resolveWidgetFilterIgnore(
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
dashboardNonDateFilterDisplayFormPairs: IFilterDisplayFormPair[],
displayAsLabelMap: Map<string, ObjRef>,
): IFilterDisplayFormPair[] {
Expand All @@ -166,7 +169,7 @@ function resolveWidgetFilterIgnore(

function selectResolvedInsightDateFilters(
state: DashboardState,
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
dashboardCommonDateFilters: IDateFilter[],
dashboardDateFiltersWithDimensions: IDateFilter[],
insightDateFilters: IDateFilter[],
Expand All @@ -190,7 +193,7 @@ function selectResolvedInsightDateFilters(

function selectResolveWidgetDateFilterIgnore(
state: DashboardState,
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
dashboardCommonDateFilters: IDateFilter[],
dashboardDateFiltersWithDimensions: IDateFilter[],
): IFilterDateDatasetPair[] {
Expand All @@ -211,7 +214,7 @@ function selectResolveWidgetDateFilterIgnore(
}

function resolveWidgetDateFilterIgnore(
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
commonDateFilterDateDatasetPairs: IFilterDateDatasetPair[],
widgetDateFilterDateDatasetPairs: IFilterDateDatasetPair[],
): IFilterDateDatasetPair[] {
Expand Down Expand Up @@ -240,7 +243,7 @@ function resolveWidgetDateFilterIgnore(

function selectResolvedDateFilters(
state: DashboardState,
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
dashboardCommonDateFilters: IDateFilter[],
dashboardDateFiltersWithDimensions: IDateFilter[],
supportsMultipleDateFilters: boolean,
Expand Down Expand Up @@ -288,7 +291,7 @@ function resolveDateFilters(

function* queryWithInsight(
ctx: DashboardContext,
widget: ExtendedDashboardWidget,
widget: FilterableDashboardWidget,
insight: IInsightDefinition,
): SagaIterator<IFilter[]> {
const widgetAwareDashboardFiltersSelector = selectAllFiltersForWidgetByRef(widget.ref);
Expand Down Expand Up @@ -378,7 +381,7 @@ function* queryService(ctx: DashboardContext, query: QueryWidgetFilters): SagaIt
payload: { widgetRef, insight },
correlationId,
} = query;
const widgetSelector = selectWidgetByRef(widgetRef);
const widgetSelector = selectAnalyticalWidgetByRef(widgetRef);
const widget: ReturnType<typeof widgetSelector> = yield select(widgetSelector);

if (!widget) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import {
selectIsScheduleEmailDialogOpen,
selectIsScheduleEmailDialogContext,
selectIsScheduleEmailManagementDialogOpen,
selectWidgetByRef,
selectInsightByWidgetRef,
selectNotificationChannelsCount,
selectNotificationChannels,
selectAutomationsIsInitialized,
selectAnalyticalWidgetByRef,
} from "../../store/index.js";
import { useDashboardSelector } from "../DashboardStoreProvider.js";

Expand Down Expand Up @@ -106,7 +106,7 @@ export const useDashboardScheduledEmailsData = ({
)?.widget;
const editWidgetRef = editWidgetId ? { identifier: editWidgetId } : undefined;
const widget = useDashboardSelector(
selectWidgetByRef(scheduleEmailingDialogContext?.widgetRef ?? editWidgetRef),
selectAnalyticalWidgetByRef(scheduleEmailingDialogContext?.widgetRef ?? editWidgetRef),
);
const insight = useDashboardSelector(selectInsightByWidgetRef(widget?.ref));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import { IAutomationMetadataObject, IInsight } from "@gooddata/sdk-model";
import { useFiltersForWidgetScheduledExport } from "./useFiltersForWidgetScheduledExport.js";
import { useFiltersForDashboardScheduledExport } from "./useFiltersForDashboardScheduledExport.js";
import { ExtendedDashboardWidget } from "../../../model/types/layoutTypes.js";
import { FilterableDashboardWidget } from "../../../model/types/layoutTypes.js";

/**
* @alpha
*/
export interface IUseDashboardScheduledEmailsFiltersProps {
scheduledExportToEdit?: IAutomationMetadataObject;
widget?: ExtendedDashboardWidget;
widget?: FilterableDashboardWidget;
insight?: IInsight;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "@gooddata/sdk-model";
import { useWidgetFilters } from "../useWidgetFilters.js";
import { getAutomationVisualizationFilters } from "../../../_staging/automation/index.js";
import { ExtendedDashboardWidget } from "../../types/layoutTypes.js";
import { FilterableDashboardWidget } from "../../types/layoutTypes.js";
import { QueryProcessingState } from "../useDashboardQueryProcessing.js";
import { useDashboardSelector } from "../DashboardStoreProvider.js";
import { selectCrossFilteringItems } from "../../store/drill/drillSelectors.js";
Expand All @@ -27,7 +27,7 @@ export interface IUseFiltersForWidgetScheduledExportProps {
/**
* Widget to get filters for.
*/
widget?: ExtendedDashboardWidget;
widget?: FilterableDashboardWidget;

/**
* Insight to get filters for.
Expand Down
6 changes: 3 additions & 3 deletions libs/sdk-ui-dashboard/src/model/react/useWidgetFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
selectCrossFilteringFiltersLocalIdentifiersByWidgetRef,
} from "../../model/store/index.js";
import { safeSerializeObjRef } from "../../_staging/metadata/safeSerializeObjRef.js";
import { ExtendedDashboardWidget } from "../types/layoutTypes.js";
import { FilterableDashboardWidget } from "../types/layoutTypes.js";
import {
QueryProcessingState,
QueryProcessingStatus,
Expand All @@ -44,7 +44,7 @@ import { useDashboardSelector } from "./DashboardStoreProvider.js";
* @public
*/
export function useWidgetFilters(
widget: ExtendedDashboardWidget | undefined | null,
widget: FilterableDashboardWidget | undefined | null,
insight?: IInsightDefinition,
): QueryProcessingState<IFilter[]> {
const [effectiveFiltersState, setEffectiveFiltersState] = useState<{
Expand Down Expand Up @@ -125,7 +125,7 @@ export function useWidgetFilters(
*
* @param widget - widget to get the non-ignored filters for
*/
function useNonIgnoredFilters(widget: ExtendedDashboardWidget | undefined | null) {
function useNonIgnoredFilters(widget: FilterableDashboardWidget | undefined | null) {
const dashboardFilters = useDashboardSelector(selectFilterContextFilters);
const crossFilteringLocalIdentifiersForThisWidget = useDashboardSelector(
selectCrossFilteringFiltersLocalIdentifiersByWidgetRef(widget?.ref),
Expand Down
14 changes: 11 additions & 3 deletions libs/sdk-ui-dashboard/src/model/store/layout/layoutSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ import partition from "lodash/partition.js";
import isEmpty from "lodash/isEmpty.js";

import { DashboardSelector, DashboardState } from "../types.js";
import { ExtendedDashboardWidget, isCustomWidget } from "../../types/layoutTypes.js";
import {
ExtendedDashboardWidget,
isCustomWidget,
isExtendedDashboardLayoutWidget,
} from "../../types/layoutTypes.js";
import { UndoableCommand, createUndoableCommandsMapping } from "../_infra/undoEnhancer.js";
import { ObjRefMap, newMapForObjectWithIdentity } from "../../../_staging/metadata/objRefMap.js";
import { selectFilterContextFilters } from "../filterContext/filterContextSelectors.js";
Expand Down Expand Up @@ -196,7 +200,7 @@ export const selectWidgetByRef: (

/**
* Selects analytical widget by its ref. This selector will return undefined if the provided
* widget ref is for a custom widget.
* widget ref is not analytical widget, eg. custom widget or nested layout.
*
* @remarks
* To include custom widgets as well, use {@link selectWidgetByRef}.
Expand All @@ -213,7 +217,7 @@ export const selectAnalyticalWidgetByRef: (

const widget = widgetMap.get(ref);

if (!widget || isCustomWidget(widget)) {
if (!widget || isCustomWidget(widget) || isExtendedDashboardLayoutWidget(widget)) {
return undefined;
}

Expand Down Expand Up @@ -270,6 +274,10 @@ export const selectAllFiltersForWidgetByRef: (
) => {
invariant(widget, `widget with ref ${objRefToString(ref)} does not exist in the state`);

if (isExtendedDashboardLayoutWidget(widget)) {
return [[], []];
}

// Widget is the source of cross-filtering, so filtering out the cross-filtering filters
const filtersWithoutCrossFilteringFilters = dashboardFilters.filter((f) => {
if (isDashboardAttributeFilter(f)) {
Expand Down
Loading

0 comments on commit d9f4347

Please sign in to comment.