diff --git a/src/Classes/settingsClass.ts b/src/Classes/settingsClass.ts index 6967793..3489299 100644 --- a/src/Classes/settingsClass.ts +++ b/src/Classes/settingsClass.ts @@ -7,10 +7,10 @@ type VisualObjectInstance = powerbi.default.VisualObjectInstance; type VisualObjectInstanceContainer = powerbi.default.VisualObjectInstanceContainer; import { dataViewWildcard } from "powerbi-visuals-utils-dataviewutils"; import { extractConditionalFormatting } from "../Functions"; -import { default as defaultSettings, settingsPaneGroupings, settingsPaneToggles } from "../defaultSettings"; +import { default as defaultSettings, type settingsValueTypes, settingsPaneGroupings, settingsPaneToggles } from "../defaultSettings"; import derivedSettingsClass from "./derivedSettingsClass"; -export type defaultSettingsType = typeof defaultSettings; +export type defaultSettingsType = settingsValueTypes; export type defaultSettingsKey = keyof defaultSettingsType; export type settingsScalarTypes = number | string | boolean; @@ -42,7 +42,7 @@ export default class settingsClass { // use those to extract and update the relevant values const settingNames: string[] = Object.keys(this.settings[settingGroup]); settingNames.forEach(settingName => { - this.settings[settingGroup][settingName] = condFormatting ? condFormatting[settingName] : defaultSettings[settingGroup][settingName] + this.settings[settingGroup][settingName] = condFormatting ? condFormatting[settingName] : defaultSettings[settingGroup][settingName]["default"] }) }) @@ -63,12 +63,12 @@ export default class settingsClass { const paneGroupings: Record = settingsGrouped ? JSON.parse(JSON.stringify(settingsPaneGroupings[settingGroupName])) : { "all": settingNames }; - + if (Object.keys(settingsPaneToggles).includes(settingGroupName)) { const toggledSettings: Record> = settingsGrouped ? settingsPaneToggles[settingGroupName] : { "all": settingsPaneToggles[settingGroupName]}; - + Object.keys(toggledSettings).forEach(toggleGroup => { const possibleSettings: string[] = paneGroupings[toggleGroup]; let settingsToRemove: string[] = new Array(); @@ -80,7 +80,7 @@ export default class settingsClass { paneGroupings[toggleGroup] = possibleSettings.filter(setting => !settingsToRemove.includes(setting)) }) } - + const rtnInstances = new Array(); const rtnContainers = new Array(); @@ -105,7 +105,10 @@ export default class settingsClass { objectName: settingGroupName, properties: props, propertyInstanceKind: Object.fromEntries(propertyKinds), - selector: dataViewWildcard.createDataViewWildcardSelector(dataViewWildcard.DataViewWildcardMatchingOption.InstancesAndTotals) + selector: dataViewWildcard.createDataViewWildcardSelector(dataViewWildcard.DataViewWildcardMatchingOption.InstancesAndTotals), + validValues: Object.fromEntries(Object.keys(defaultSettings[settingGroupName]).map((settingName) => { + return [settingName, defaultSettings[settingGroupName][settingName]?.["valid"]] + })) }) if (currKey !== "all") { @@ -118,7 +121,11 @@ export default class settingsClass { } constructor() { - this.settings = JSON.parse(JSON.stringify(defaultSettings)); + this.settings = Object.fromEntries(Object.keys(defaultSettings).map((settingGroupName) => { + return [settingGroupName, Object.fromEntries(Object.keys(defaultSettings[settingGroupName]).map((settingName) => { + return [settingName, defaultSettings[settingGroupName][settingName]]; + }))]; + })) as settingsValueTypes; this.derivedSettings = new derivedSettingsClass(); } } diff --git a/src/Functions/extractConditionalFormatting.ts b/src/Functions/extractConditionalFormatting.ts index 86389fb..4be28fa 100644 --- a/src/Functions/extractConditionalFormatting.ts +++ b/src/Functions/extractConditionalFormatting.ts @@ -25,7 +25,7 @@ export default function extractConditionalFormatting(ca dataViewObjects.getCommonValue( (inputCategories.objects ? inputCategories.objects[idx] : null) as powerbi.DataViewObjects, { objectName: name, propertyName: settingName }, - defaultSettings[name][settingName] + defaultSettings[name][settingName]["default"] ) ] }) diff --git a/src/defaultSettings.ts b/src/defaultSettings.ts index 4151989..9ca41d9 100644 --- a/src/defaultSettings.ts +++ b/src/defaultSettings.ts @@ -1,149 +1,195 @@ +// Values returned by each option of PBI's built-in font picker +// TODO(Andrew): Allow user to pass human-readable font names +const validFonts: string[] = [ + "'Arial', sans-serif", + "Arial", + "'Arial Black'", + "'Arial Unicode MS'", + "Calibri", + "Cambria", + "'Cambria Math'", + "Candara", + "'Comic Sans MS'", + "Consolas", + "Constantia", + "Corbel", + "'Courier New'", + "wf_standard-font, helvetica, arial, sans-serif", + "wf_standard-font_light, helvetica, arial, sans-serif", + "Georgia", + "'Lucida Sans Unicode'", + "'Segoe UI', wf_segoe-ui_normal, helvetica, arial, sans-serif", + "'Segoe UI Light', wf_segoe-ui_light, helvetica, arial, sans-serif", + "'Segoe UI Semibold', wf_segoe-ui_semibold, helvetica, arial, sans-serif", + "'Segoe UI Bold', wf_segoe-ui_bold, helvetica, arial, sans-serif", + "Symbol", + "Tahoma", + "'Times New Roman'", + "'Trebuchet MS'", + "Verdana", + "Wingdings" +]; + +// TODO(Andrew): Allow user to pass human-readable names +const validLineTypes: string[] = ["10 0", "10 10", "2 5"]; + const defaultSettings = { canvas: { - show_errors: true, - lower_padding: 10, - upper_padding: 10, - left_padding: 10, - right_padding: 10 + show_errors: { default: true }, + lower_padding: { default: 10 }, + upper_padding: { default: 10 }, + left_padding: { default: 10 }, + right_padding: { default: 10 } }, spc: { - chart_type: "i", - outliers_in_limits: false, - multiplier: 1, - sig_figs: 2, - perc_labels: "Automatic", - split_on_click: false, - ttip_show_numerator: true, - ttip_label_numerator: "Numerator", - ttip_show_denominator: true, - ttip_label_denominator: "Denominator", - ttip_show_value: true, - ttip_label_value: "Automatic", - ll_truncate: (null), - ul_truncate: (null) + chart_type: { default: "i", valid: ["run", "i", "mr", "p", "pp", "u", "up", "c", "xbar", "s", "g", "t"] }, + outliers_in_limits: { default: false }, + multiplier: { default: 1, valid: { numberRange: { min: 0 } } }, + sig_figs: { default: 2, valid: { numberRange: { min: 0, max: 20 } } }, + perc_labels: { default: "Automatic", valid: ["Automatic", "Yes", "No"]}, + split_on_click: { default: false }, + ttip_show_numerator: { default: true }, + ttip_label_numerator: { default: "Numerator"}, + ttip_show_denominator: { default: true }, + ttip_label_denominator: { default: "Denominator"}, + ttip_show_value: { default: true }, + ttip_label_value: { default: "Automatic"}, + ll_truncate: { default: null }, + ul_truncate: { default: null } }, outliers: { - process_flag_type: "both", - improvement_direction: "increase", - astronomical: false, - astronomical_limit: "3 Sigma", - ast_colour_improvement: "#00B0F0", - ast_colour_deterioration: "#E46C0A", - ast_colour_neutral_low: "#490092", - ast_colour_neutral_high: "#490092", - shift: false, - shift_n: 7, - shift_colour_improvement: "#00B0F0", - shift_colour_deterioration: "#E46C0A", - shift_colour_neutral_low: "#490092", - shift_colour_neutral_high: "#490092", - trend: false, - trend_n: 5, - trend_colour_improvement: "#00B0F0", - trend_colour_deterioration: "#E46C0A", - trend_colour_neutral_low: "#490092", - trend_colour_neutral_high: "#490092", - two_in_three: false, - two_in_three_highlight_series: false, - two_in_three_limit: "2 Sigma", - twointhree_colour_improvement: "#00B0F0", - twointhree_colour_deterioration: "#E46C0A", - twointhree_colour_neutral_low: "#490092", - twointhree_colour_neutral_high: "#490092" + process_flag_type: { default: "both", valid: ["both", "improvement", "deterioration"]}, + improvement_direction: { default: "increase", valid: ["increase", "neutral", "decrease"]}, + astronomical: { default: false }, + astronomical_limit: { default: "3 Sigma", valid: ["1 Sigma", "2 Sigma", "3 Sigma"]}, + ast_colour_improvement: { default: "#00B0F0" }, + ast_colour_deterioration: { default: "#E46C0A" }, + ast_colour_neutral_low: { default: "#490092" }, + ast_colour_neutral_high: { default: "#490092" }, + shift: { default: false }, + shift_n: { default: 7, valid: { numberRange: { min: 1 } } }, + shift_colour_improvement: { default: "#00B0F0" }, + shift_colour_deterioration: { default: "#E46C0A" }, + shift_colour_neutral_low: { default: "#490092" }, + shift_colour_neutral_high: { default: "#490092" }, + trend: { default: false }, + trend_n: { default: 5, valid: { numberRange: { min: 1 } } }, + trend_colour_improvement: { default: "#00B0F0" }, + trend_colour_deterioration: { default: "#E46C0A" }, + trend_colour_neutral_low: { default: "#490092" }, + trend_colour_neutral_high: { default: "#490092" }, + two_in_three: { default: false }, + two_in_three_highlight_series: { default: false }, + two_in_three_limit: { default: "2 Sigma", valid: ["1 Sigma", "2 Sigma", "3 Sigma"]}, + twointhree_colour_improvement: { default: "#00B0F0" }, + twointhree_colour_deterioration: { default: "#E46C0A" }, + twointhree_colour_neutral_low: { default: "#490092" }, + twointhree_colour_neutral_high: { default: "#490092" } }, nhs_icons: { - flag_last_point: true, - show_variation_icons: false, - variation_icons_locations: "Top Right", - variation_icons_scaling: 1, - show_assurance_icons: false, - assurance_icons_locations: "Top Right", - assurance_icons_scaling: 1 + flag_last_point: { default: true }, + show_variation_icons: { default: false }, + variation_icons_locations: { default: "Top Right", valid: ["Top Right", "Bottom Right", "Top Left", "Bottom Left"]}, + variation_icons_scaling: { default: 1, valid: { numberRange: { min: 0} } }, + show_assurance_icons: { default: false }, + assurance_icons_locations: { default: "Top Right", valid: ["Top Right", "Bottom Right", "Top Left", "Bottom Left"]}, + assurance_icons_scaling: { default: 1, valid: { numberRange: { min: 0} } } }, scatter: { - size: 2.5, - colour: "#000000", - opacity: 1, - opacity_unselected: 0.2 + size: { default: 2.5, valid: { numberRange: { min: 0, max: 100 }}}, + colour: { default: "#000000" }, + opacity: { default: 1, valid: { numberRange: { min: 0, max: 1 } } }, + opacity_unselected: { default: 0.2, valid: { numberRange: { min: 0, max: 1 } } } }, lines: { - show_99: true, - show_95: true, - show_68: false, - show_main: true, - show_target: true, - show_alt_target: false, - width_99: 2, - width_95: 2, - width_68: 2, - width_main: 1, - width_target: 1.5, - width_alt_target: 1.5, - type_99: "10 10", - type_95: "2 5", - type_68: "2 5", - type_main: "10 0", - type_target: "10 0", - type_alt_target: "10 0", - colour_99: "#6495ED", - colour_95: "#6495ED", - colour_68: "#6495ED", - colour_main: "#000000", - colour_target: "#000000", - colour_alt_target: "#000000", - ttip_show_99: true, - ttip_show_95: false, - ttip_show_68: false, - ttip_show_target: true, - ttip_show_alt_target: true, - ttip_label_99: "99% Limit", - ttip_label_95: "95% Limit", - ttip_label_68: "68% Limit", - ttip_label_target: "Centerline", - ttip_label_alt_target: "Additional Target", - alt_target: (null) + show_99: { default: true }, + show_95: { default: true }, + show_68: { default: false }, + show_main: { default: true }, + show_target: { default: true }, + show_alt_target: { default: false }, + width_99: { default: 2, valid: { numberRange: { min: 0, max: 100 }}}, + width_95: { default: 2, valid: { numberRange: { min: 0, max: 100 }}}, + width_68: { default: 2, valid: { numberRange: { min: 0, max: 100 }}}, + width_main: { default: 1, valid: { numberRange: { min: 0, max: 100 }}}, + width_target: { default: 1.5, valid: { numberRange: { min: 0, max: 100 }}}, + width_alt_target: { default: 1.5, valid: { numberRange: { min: 0, max: 100 }}}, + type_99: { default: "10 10", valid: validLineTypes}, + type_95: { default: "2 5", valid: validLineTypes}, + type_68: { default: "2 5", valid: validLineTypes}, + type_main: { default: "10 0", valid: validLineTypes}, + type_target: { default: "10 0", valid: validLineTypes}, + type_alt_target: { default: "10 0", valid: validLineTypes}, + colour_99: { default: "#6495ED" }, + colour_95: { default: "#6495ED" }, + colour_68: { default: "#6495ED" }, + colour_main: { default: "#000000" }, + colour_target: { default: "#000000" }, + colour_alt_target: { default: "#000000" }, + ttip_show_99: { default: true }, + ttip_show_95: { default: false }, + ttip_show_68: { default: false }, + ttip_show_target: { default: true }, + ttip_show_alt_target: { default: true }, + ttip_label_99: { default: "99% Limit" }, + ttip_label_95: { default: "95% Limit" }, + ttip_label_68: { default: "68% Limit" }, + ttip_label_target: { default: "Centerline" }, + ttip_label_alt_target: { default: "Additional Target" }, + alt_target: { default: null } }, x_axis: { - xlimit_colour: "#000000", - xlimit_ticks: true, - xlimit_tick_font: "'Arial', sans-serif", - xlimit_tick_size: 10, - xlimit_tick_colour: "#000000", - xlimit_tick_rotation: -35, - xlimit_tick_count: (null), - xlimit_label:(null), - xlimit_label_font: "'Arial', sans-serif", - xlimit_label_size: 10, - xlimit_label_colour: "#000000", - xlimit_l: (null), - xlimit_u: (null) + xlimit_colour: { default: "#000000" }, + xlimit_ticks: { default: true }, + xlimit_tick_font: { default: "'Arial', sans-serif", valid: validFonts}, + xlimit_tick_size: { default: 10, valid: { numberRange: { min: 0, max: 100 }}}, + xlimit_tick_colour: { default: "#000000" }, + xlimit_tick_rotation: { default: -35, valid: { numberRange: { min: -360, max: 360 }}}, + xlimit_tick_count: { default: 10, valid: { numberRange: { min: 0, max: 100 }}}, + xlimit_label: { default: null }, + xlimit_label_font: { default: "'Arial', sans-serif", valid: validFonts}, + xlimit_label_size: { default: 10, valid: { numberRange: { min: 0, max: 100 }}}, + xlimit_label_colour: { default: "#000000" }, + xlimit_l: { default: null }, + xlimit_u: { default: null } }, y_axis: { - ylimit_colour: "#000000", - ylimit_ticks: true, - ylimit_tick_font: "'Arial', sans-serif", - ylimit_tick_size: 10, - ylimit_tick_colour: "#000000", - ylimit_tick_rotation: 0, - ylimit_tick_count: (null), - ylimit_label:(null), - ylimit_label_font: "'Arial', sans-serif", - ylimit_label_size: 10, - ylimit_label_colour: "#000000", - ylimit_l: (null), - ylimit_u: (null), - limit_multiplier: 1.5, - ylimit_sig_figs: (null) + ylimit_colour: { default: "#000000" }, + ylimit_ticks: { default: true }, + ylimit_tick_font: { default: "'Arial', sans-serif", valid: validFonts}, + ylimit_tick_size: { default: 10, valid: { numberRange: { min: 0, max: 100 }}}, + ylimit_tick_colour: { default: "#000000" }, + ylimit_tick_rotation: { default: 0, valid: { numberRange: { min: -360, max: 360 }}}, + ylimit_tick_count: { default: 10, valid: { numberRange: { min: 0, max: 100 }}}, + ylimit_label: { default: null }, + ylimit_label_font: { default: "'Arial', sans-serif", valid: validFonts}, + ylimit_label_size: { default: 10, valid: { numberRange: { min: 0, max: 100 }}}, + ylimit_label_colour: { default: "#000000" }, + ylimit_l: { default: null }, + ylimit_u: { default: null }, + limit_multiplier: { default: 1.5, valid: { numberRange: { min: 0} } }, + ylimit_sig_figs: { default: null } }, dates: { - date_format_day: "DD", - date_format_month: "MM", - date_format_year: "YYYY", - date_format_delim: "/", - date_format_locale: "en-GB" + date_format_day: { default: "DD", valid: ["DD", "Thurs DD", "Thursday DD", "(blank)"]}, + date_format_month: { default: "MM", valid: ["MM", "Mon", "Month", "(blank)"]}, + date_format_year: { default: "YYYY", valid: ["YYYY", "YY", "(blank)"]}, + date_format_delim: { default: "/", valid: ["/", "-", " "]}, + date_format_locale: { default: "en-GB", valid: ["en-GB", "en-US"]} } }; +type RemoveValidEntry = { + [K in keyof T as Exclude]: T[K] +}; +type Unwrap = T[keyof RemoveValidEntry]; + +export type settingsValueTypes = { + [K in keyof typeof defaultSettings]: { + [L in keyof typeof defaultSettings[K]]: Unwrap + } +} + export const settingsPaneGroupings = { outliers: { "Astronomical Points": ["process_flag_type", "improvement_direction", "astronomical", "astronomical_limit", "ast_colour_improvement", "ast_colour_deterioration", "ast_colour_neutral_low", "ast_colour_neutral_high"],