diff --git a/packages/chart/src/ChartModelFactory.ts b/packages/chart/src/ChartModelFactory.ts index 635f68e0c5..cb61dcc7df 100644 --- a/packages/chart/src/ChartModelFactory.ts +++ b/packages/chart/src/ChartModelFactory.ts @@ -78,7 +78,7 @@ class ChartModelFactory { * This causes TS issues in 1 or 2 spots. Once this is TS it can be returned to just FigureChartModel */ static async makeModel( - settings: Record | undefined, + settings: ChartModelSettings | undefined, figure: Figure, theme = ChartTheme ): Promise { diff --git a/packages/chart/src/ChartUtils.ts b/packages/chart/src/ChartUtils.ts index eba256d192..00a178945a 100644 --- a/packages/chart/src/ChartUtils.ts +++ b/packages/chart/src/ChartUtils.ts @@ -38,9 +38,9 @@ import ChartTheme from './ChartTheme'; export interface ChartModelSettings { hiddenSeries?: string[]; - type: keyof SeriesPlotStyle; - series: string[]; - xAxis: string; + type?: keyof SeriesPlotStyle; + series?: string[]; + xAxis?: string; title?: string; } @@ -1805,10 +1805,13 @@ class ChartUtils { */ static hydrateSettings( settings: ChartModelSettings - ): Omit & { type: SeriesPlotStyle } { + ): Omit & { type?: SeriesPlotStyle } { return { ...settings, - type: dh.plot.SeriesPlotStyle[settings.type], + type: + settings.type != null + ? dh.plot.SeriesPlotStyle[settings.type] + : undefined, }; } @@ -1816,7 +1819,7 @@ class ChartUtils { const { series, xAxis, - title = `${series.join(', ')} by ${xAxis}`, + title = `${(series ?? []).join(', ')} by ${xAxis}`, } = settings; return title; @@ -1872,13 +1875,13 @@ class ChartUtils { { chartType: `${dh.plot.ChartType.XY}`, axes: [xAxis, yAxis], - series: series.map(name => ({ + series: (series ?? []).map(name => ({ plotStyle: `${type}`, name, dataSources: [ { type: `${dh.plot.SourceType.X}`, - columnName: settingsAxis, + columnName: settingsAxis ?? '', axis: xAxis, table, }, diff --git a/packages/code-studio/src/main/WidgetUtils.ts b/packages/code-studio/src/main/WidgetUtils.ts index 5fa9d4e9ee..4d0216e434 100644 --- a/packages/code-studio/src/main/WidgetUtils.ts +++ b/packages/code-studio/src/main/WidgetUtils.ts @@ -67,8 +67,7 @@ export const createChartModel = async ( }; const figure = await connection.getObject(definition); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return ChartModelFactory.makeModel(settings as any, figure); + return ChartModelFactory.makeModel(settings, figure); } const definition = { diff --git a/packages/code-studio/src/redux/selectors.ts b/packages/code-studio/src/redux/selectors.ts index a479237204..235e60fa39 100644 --- a/packages/code-studio/src/redux/selectors.ts +++ b/packages/code-studio/src/redux/selectors.ts @@ -1,4 +1,4 @@ -import { RootState, ServerConfigValues } from '@deephaven/redux'; +import { RootState } from '@deephaven/redux'; import LayoutStorage from '../storage/LayoutStorage'; /** @@ -6,13 +6,15 @@ import LayoutStorage from '../storage/LayoutStorage'; * @param store The redux store * @returns The layout storage instance */ -export const getLayoutStorage = (store: RootState): LayoutStorage => - store.layoutStorage as LayoutStorage; +export const getLayoutStorage = ( + store: State +): LayoutStorage => store.layoutStorage as LayoutStorage; /** * Get the configuration values of the server * @param store The redux store * @returns The layout storage instance */ -export const getServerConfigValues = (store: RootState): ServerConfigValues => - store.serverConfigValues; +export const getServerConfigValues = ( + store: State +): State['serverConfigValues'] => store.serverConfigValues; diff --git a/packages/code-studio/src/settings/ColumnSpecificSectionContent.tsx b/packages/code-studio/src/settings/ColumnSpecificSectionContent.tsx index 802e9e43de..bd77a070fa 100644 --- a/packages/code-studio/src/settings/ColumnSpecificSectionContent.tsx +++ b/packages/code-studio/src/settings/ColumnSpecificSectionContent.tsx @@ -248,8 +248,7 @@ export class ColumnSpecificSectionContent extends PureComponent< isNewRule: true, }; return { - formatSettings: - formatSettings != null ? [...formatSettings, newFormat] : [newFormat], + formatSettings: [...formatSettings, newFormat], formatRulesChanged: true, }; }); diff --git a/packages/code-studio/src/settings/FormattingSectionContent.tsx b/packages/code-studio/src/settings/FormattingSectionContent.tsx index 7ba47ec4ff..0aaef95a45 100644 --- a/packages/code-studio/src/settings/FormattingSectionContent.tsx +++ b/packages/code-studio/src/settings/FormattingSectionContent.tsx @@ -15,7 +15,6 @@ import { IntegerColumnFormatter, DecimalColumnFormatter, TableUtils, - FormattingRule, } from '@deephaven/jsapi-utils'; import Log from '@deephaven/log'; import { @@ -363,7 +362,7 @@ export class FormattingSectionContent extends PureComponent< const { settings, saveSettings } = this.props; const newSettings: WorkspaceSettings = { ...settings, - formatter: formatter as FormattingRule[], + formatter, defaultDateTimeFormat, showTimeZone, showTSeparator, diff --git a/packages/code-studio/src/settings/SettingsUtils.tsx b/packages/code-studio/src/settings/SettingsUtils.tsx index bb0a1c86de..db069bd9e1 100644 --- a/packages/code-studio/src/settings/SettingsUtils.tsx +++ b/packages/code-studio/src/settings/SettingsUtils.tsx @@ -4,6 +4,7 @@ import { IntegerColumnFormatter, DecimalColumnFormatter, TableColumnFormat, + FormattingRule, } from '@deephaven/jsapi-utils'; import Log from '@deephaven/log'; @@ -13,14 +14,15 @@ export type FormatOption = { defaultFormatString?: string; }; -export type FormatterItem = { - columnType: string; - columnName: string; - format: Partial; +export type ValidFormatterItem = FormattingRule & { id?: number; isNewRule?: boolean; }; +export type FormatterItem = Omit & { + format: Partial; +}; + function isFormatStringFormat( format: Partial ): format is Pick { @@ -92,13 +94,15 @@ export function isValidFormat( } export function removeFormatRuleExtraProps( - item: FormatterItem -): Omit { + item: ValidFormatterItem +): FormattingRule { const { id, isNewRule, ...rest } = item; return rest; } -export function isFormatRuleValidForSave(rule: FormatterItem): boolean { +export function isFormatRuleValidForSave( + rule: FormatterItem +): rule is ValidFormatterItem { return ( isValidColumnName(rule.columnName) && isValidFormat(rule.columnType, rule.format) diff --git a/packages/dashboard-core-plugins/src/ChartBuilderPlugin.tsx b/packages/dashboard-core-plugins/src/ChartBuilderPlugin.tsx index c3795edc2f..b08bccbda7 100644 --- a/packages/dashboard-core-plugins/src/ChartBuilderPlugin.tsx +++ b/packages/dashboard-core-plugins/src/ChartBuilderPlugin.tsx @@ -45,8 +45,7 @@ export function ChartBuilderPlugin( }) => { const { settings } = metadata; const makeModel = () => - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ChartModelFactory.makeModelFromSettings(settings as any, table); + ChartModelFactory.makeModelFromSettings(settings, table); const title = ChartUtils.titleFromSettings(settings); const config = { diff --git a/packages/dashboard/src/layout/LayoutUtils.ts b/packages/dashboard/src/layout/LayoutUtils.ts index 869881286f..b1382116c8 100644 --- a/packages/dashboard/src/layout/LayoutUtils.ts +++ b/packages/dashboard/src/layout/LayoutUtils.ts @@ -80,7 +80,10 @@ class LayoutUtils { * @param config Tab config to match * @returns True if the tab is active */ - static isActiveTab(root: ContentItem, config: Config): boolean { + static isActiveTab( + root: ContentItem, + config: Partial + ): boolean { const stack = LayoutUtils.getStackForRoot(root, config, false); if (!stack) { log.error('Could not find stack for config', config); diff --git a/packages/iris-grid/src/IrisGridUtils.ts b/packages/iris-grid/src/IrisGridUtils.ts index c99df84836..4c025e023e 100644 --- a/packages/iris-grid/src/IrisGridUtils.ts +++ b/packages/iris-grid/src/IrisGridUtils.ts @@ -110,6 +110,15 @@ export interface DehydratedSort { direction: SortDirection; } +export interface TableSettings { + quickFilters?: readonly DehydratedQuickFilter[]; + advancedFilters?: readonly DehydratedAdvancedFilter[]; + inputFilters?: readonly InputFilter[]; + sorts?: readonly (DehydratedSort | LegacyDehydratedSort)[]; + partition?: unknown; + partitionColumn?: ColumnName; +} + export interface DehydratedIrisGridState { advancedFilters: readonly DehydratedAdvancedFilter[]; aggregationSettings: AggregationSettings; @@ -876,14 +885,7 @@ class IrisGridUtils { */ static applyTableSettings( table: Table, - tableSettings: { - quickFilters?: readonly DehydratedQuickFilter[]; - advancedFilters?: readonly DehydratedAdvancedFilter[]; - inputFilters?: readonly InputFilter[]; - sorts?: readonly (DehydratedSort | LegacyDehydratedSort)[]; - partition?: unknown; - partitionColumn?: ColumnName; - }, + tableSettings: TableSettings, timeZone: string ): void { const { columns } = table; diff --git a/packages/jsapi-types/src/dh.types.ts b/packages/jsapi-types/src/dh.types.ts index cdedd286d5..de6b50669c 100644 --- a/packages/jsapi-types/src/dh.types.ts +++ b/packages/jsapi-types/src/dh.types.ts @@ -281,7 +281,7 @@ export interface Figure extends Evented { readonly EVENT_SERIES_ADDED: string; /** Given a client-created figure descriptor, generate a figure that can be subscribed to */ - create(figure: Partial): Figure; + create(figure: Partial): Promise
; readonly title: string; readonly titleFont: string; diff --git a/packages/redux/src/selectors.ts b/packages/redux/src/selectors.ts index 941b3ced64..1436d025b2 100644 --- a/packages/redux/src/selectors.ts +++ b/packages/redux/src/selectors.ts @@ -1,90 +1,113 @@ -import type { - RootState, - User, - Storage, - Workspace, - WorkspaceSettings, -} from './store'; +import type { RootState, Storage, WorkspaceSettings } from './store'; const EMPTY_OBJECT = Object.freeze({}); const EMPTY_MAP: ReadonlyMap = new Map(); -type Selector = (state: RootState) => R; - +export type Selector = (store: State) => R; // User -export const getUser: Selector = store => store.user; +export const getUser = ( + store: State +): State['user'] => store.user; -export const getUserName: Selector = store => getUser(store).name; +export const getUserName = ( + store: State +): State['user']['name'] => getUser(store).name; -export const getUserGroups: Selector = store => - getUser(store).groups; +export const getUserGroups = ( + store: State +): State['user']['groups'] => getUser(store).groups; // Storage -export const getStorage: Selector = store => store.storage; +export const getStorage = ( + store: State +): State['storage'] => store.storage; -export const getCommandHistoryStorage: Selector< - Storage['commandHistoryStorage'] -> = store => getStorage(store).commandHistoryStorage; +export const getCommandHistoryStorage = ( + store: State +): State['storage']['commandHistoryStorage'] => + getStorage(store).commandHistoryStorage; -export const getFileStorage: Selector = store => - getStorage(store).fileStorage; +export const getFileStorage = ( + store: State +): State['storage']['fileStorage'] => getStorage(store).fileStorage; -export const getWorkspaceStorage: Selector< - Storage['workspaceStorage'] -> = store => getStorage(store).workspaceStorage; +export const getWorkspaceStorage = ( + store: State +): Storage['workspaceStorage'] => getStorage(store).workspaceStorage; // Workspace -export const getWorkspace: Selector = store => store.workspace; +export const getWorkspace = ( + store: State +): RootState['workspace'] => store.workspace; // Settings -export const getSettings: Selector = store => +export const getSettings = ( + store: State +): RootState['workspace']['data']['settings'] => getWorkspace(store).data.settings; -export const getDefaultDateTimeFormat: Selector< - WorkspaceSettings['defaultDateTimeFormat'] -> = store => getSettings(store).defaultDateTimeFormat; - -export const getDefaultDecimalFormatOptions: Selector< - WorkspaceSettings['defaultDecimalFormatOptions'] -> = store => getSettings(store).defaultDecimalFormatOptions ?? EMPTY_OBJECT; - -export const getDefaultIntegerFormatOptions: Selector< - WorkspaceSettings['defaultIntegerFormatOptions'] -> = store => getSettings(store).defaultIntegerFormatOptions ?? EMPTY_OBJECT; - -export const getFormatter: Selector = store => - getSettings(store).formatter; - -export const getTimeZone: Selector = store => - getSettings(store).timeZone; - -export const getShowTimeZone: Selector< - WorkspaceSettings['showTimeZone'] -> = store => getSettings(store).showTimeZone; - -export const getShowTSeparator: Selector< - WorkspaceSettings['showTSeparator'] -> = store => getSettings(store).showTSeparator; - -export const getTruncateNumbersWithPound: Selector< - WorkspaceSettings['truncateNumbersWithPound'] -> = store => getSettings(store).truncateNumbersWithPound; - -export const getDisableMoveConfirmation: Selector< - WorkspaceSettings['disableMoveConfirmation'] -> = store => getSettings(store).disableMoveConfirmation || false; - -export const getShortcutOverrides: Selector< - WorkspaceSettings['shortcutOverrides'] -> = store => getSettings(store).shortcutOverrides; - -export const getDefaultNotebookSettings: Selector< - WorkspaceSettings['defaultNotebookSettings'] -> = store => getSettings(store).defaultNotebookSettings ?? EMPTY_OBJECT; - -export const getActiveTool: Selector = store => - store.activeTool; - -export const getPlugins: Selector = store => - store.plugins ?? EMPTY_MAP; +export const getDefaultDateTimeFormat = ( + store: State +): WorkspaceSettings['defaultDateTimeFormat'] => + getSettings(store).defaultDateTimeFormat; + +export const getDefaultDecimalFormatOptions = < + State extends RootState = RootState +>( + store: State +): WorkspaceSettings['defaultDecimalFormatOptions'] => + getSettings(store).defaultDecimalFormatOptions ?? EMPTY_OBJECT; + +export const getDefaultIntegerFormatOptions = < + State extends RootState = RootState +>( + store: State +): WorkspaceSettings['defaultIntegerFormatOptions'] => + getSettings(store).defaultIntegerFormatOptions ?? EMPTY_OBJECT; + +export const getFormatter = ( + store: State +): WorkspaceSettings['formatter'] => getSettings(store).formatter; + +export const getTimeZone = ( + store: State +): WorkspaceSettings['timeZone'] => getSettings(store).timeZone; + +export const getShowTimeZone = ( + store: State +): WorkspaceSettings['showTimeZone'] => getSettings(store).showTimeZone; + +export const getShowTSeparator = ( + store: State +): WorkspaceSettings['showTSeparator'] => getSettings(store).showTSeparator; + +export const getTruncateNumbersWithPound = < + State extends RootState = RootState +>( + store: State +): WorkspaceSettings['truncateNumbersWithPound'] => + getSettings(store).truncateNumbersWithPound; + +export const getDisableMoveConfirmation = ( + store: State +): WorkspaceSettings['disableMoveConfirmation'] => + getSettings(store).disableMoveConfirmation || false; + +export const getShortcutOverrides = ( + store: State +): WorkspaceSettings['shortcutOverrides'] => + getSettings(store).shortcutOverrides; + +export const getDefaultNotebookSettings = ( + store: State +): WorkspaceSettings['defaultNotebookSettings'] => + getSettings(store).defaultNotebookSettings ?? EMPTY_OBJECT; + +export const getActiveTool = ( + store: State +): RootState['activeTool'] => store.activeTool; + +export const getPlugins = ( + store: State +): RootState['plugins'] => store.plugins ?? EMPTY_MAP;