fix(dashboard): fix default filter bar visibility + add docs (#18741)

* fix(dashboard): fix default filter tab visibility + add tests

* fix types

* lint

* rename docs + add double bang to length
This commit is contained in:
Ville Brofeldt 2022-03-23 08:55:03 +02:00 committed by GitHub
parent 375c03e084
commit b7ecb14230
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 16 deletions

View File

@ -189,3 +189,23 @@ all charts will load their data even if feature flag is turned on and no roles a
to roles the access will fallback to **Dataset permissions** to roles the access will fallback to **Dataset permissions**
<img src={useBaseUrl("/img/tutorial/tutorial_dashboard_access.png" )} /> <img src={useBaseUrl("/img/tutorial/tutorial_dashboard_access.png" )} />
### Customizing dashboard
The following URL parameters can be used to modify how the dashboard is rendered:
- `standalone`:
- `0` (default): dashboard is displayed normally
- `1`: Top Navigation is hidden
- `2`: Top Navigation + title is hidden
- `3`: Top Navigation + title + top level tabs are hidden
- `show_filters`:
- `0`: render dashboard without Filter Bar
- `1` (default): render dashboard with Filter Bar if native filters are enabled
- `expand_filters`:
- (default): render dashboard with Filter Bar expanded if there are native filters
- `0`: render dashboard with Filter Bar collapsed
- `1`: render dashboard with Filter Bar expanded
For example, when running the local development build, the following will disable the
Top Nav and remove the Filter Bar:
`http://localhost:8088/superset/dashboard/my-dashboard/?standalone=1&show_filters=0`

View File

@ -41,7 +41,7 @@ export const useUiConfig = () => useContext(UiConfigContext);
export const EmbeddedUiConfigProvider: React.FC<EmbeddedUiConfigProviderProps> = export const EmbeddedUiConfigProvider: React.FC<EmbeddedUiConfigProviderProps> =
({ children }) => { ({ children }) => {
const config = getUrlParam(URL_PARAMS.uiConfig); const config = getUrlParam(URL_PARAMS.uiConfig) || 0;
const [embeddedConfig] = useState({ const [embeddedConfig] = useState({
hideTitle: (config & 1) !== 0, hideTitle: (config & 1) !== 0,
hideTab: (config & 2) !== 0, hideTab: (config & 2) !== 0,

View File

@ -55,6 +55,10 @@ export const URL_PARAMS = {
name: 'show_filters', name: 'show_filters',
type: 'boolean', type: 'boolean',
}, },
expandFilters: {
name: 'expand_filters',
type: 'boolean',
},
formDataKey: { formDataKey: {
name: 'form_data_key', name: 'form_data_key',
type: 'string', type: 'string',

View File

@ -32,11 +32,10 @@ import {
export const useNativeFilters = () => { export const useNativeFilters = () => {
const filterboxMigrationState = useContext(MigrationContext); const filterboxMigrationState = useContext(MigrationContext);
const [isInitialized, setIsInitialized] = useState(false); const [isInitialized, setIsInitialized] = useState(false);
const [dashboardFiltersOpen, setDashboardFiltersOpen] = useState(
getUrlParam(URL_PARAMS.showFilters) ?? true,
);
const showNativeFilters = useSelector<RootState, boolean>( const showNativeFilters = useSelector<RootState, boolean>(
state => state.dashboardInfo.metadata?.show_native_filters, state =>
(getUrlParam(URL_PARAMS.showFilters) ?? true) &&
state.dashboardInfo.metadata?.show_native_filters,
); );
const canEdit = useSelector<RootState, boolean>( const canEdit = useSelector<RootState, boolean>(
({ dashboardInfo }) => dashboardInfo.dash_edit_perm, ({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
@ -44,6 +43,10 @@ export const useNativeFilters = () => {
const filters = useFilters(); const filters = useFilters();
const filterValues = Object.values(filters); const filterValues = Object.values(filters);
const expandFilters = getUrlParam(URL_PARAMS.expandFilters);
const [dashboardFiltersOpen, setDashboardFiltersOpen] = useState(
expandFilters ?? !!filterValues.length,
);
const nativeFiltersEnabled = const nativeFiltersEnabled =
showNativeFilters && showNativeFilters &&
@ -74,9 +77,10 @@ export const useNativeFilters = () => {
useEffect(() => { useEffect(() => {
if ( if (
filterValues.length === 0 && expandFilters === false ||
nativeFiltersEnabled && (filterValues.length === 0 &&
['CONVERTED', 'REVIEWING', 'NOOP'].includes(filterboxMigrationState) nativeFiltersEnabled &&
['CONVERTED', 'REVIEWING', 'NOOP'].includes(filterboxMigrationState))
) { ) {
toggleDashboardFiltersOpen(false); toggleDashboardFiltersOpen(false);
} else { } else {

View File

@ -21,7 +21,7 @@ import { DashboardPermalinkValue } from 'src/dashboard/types';
const assembleEndpoint = ( const assembleEndpoint = (
dashId: string | number, dashId: string | number,
key?: string, key?: string | null,
tabId?: string, tabId?: string,
) => { ) => {
let endpoint = `api/v1/dashboard/${dashId}/filter_state`; let endpoint = `api/v1/dashboard/${dashId}/filter_state`;
@ -65,7 +65,7 @@ export const createFilterKey = (
return null; return null;
}); });
export const getFilterValue = (dashId: string | number, key: string) => export const getFilterValue = (dashId: string | number, key?: string | null) =>
SupersetClient.get({ SupersetClient.get({
endpoint: assembleEndpoint(dashId, key), endpoint: assembleEndpoint(dashId, key),
}) })

View File

@ -30,14 +30,22 @@ import serializeActiveFilterValues from '../dashboard/util/serializeActiveFilter
export type UrlParamType = 'string' | 'number' | 'boolean' | 'object' | 'rison'; export type UrlParamType = 'string' | 'number' | 'boolean' | 'object' | 'rison';
export type UrlParam = typeof URL_PARAMS[keyof typeof URL_PARAMS]; export type UrlParam = typeof URL_PARAMS[keyof typeof URL_PARAMS];
export function getUrlParam(param: UrlParam & { type: 'string' }): string; export function getUrlParam(
export function getUrlParam(param: UrlParam & { type: 'number' }): number; param: UrlParam & { type: 'string' },
export function getUrlParam(param: UrlParam & { type: 'boolean' }): boolean; ): string | null;
export function getUrlParam(param: UrlParam & { type: 'object' }): object; export function getUrlParam(
export function getUrlParam(param: UrlParam & { type: 'rison' }): object; param: UrlParam & { type: 'number' },
): number | null;
export function getUrlParam(
param: UrlParam & { type: 'boolean' },
): boolean | null;
export function getUrlParam(
param: UrlParam & { type: 'object' },
): object | null;
export function getUrlParam(param: UrlParam & { type: 'rison' }): object | null;
export function getUrlParam( export function getUrlParam(
param: UrlParam & { type: 'rison | string' }, param: UrlParam & { type: 'rison | string' },
): string | object; ): string | object | null;
export function getUrlParam({ name, type }: UrlParam): unknown { export function getUrlParam({ name, type }: UrlParam): unknown {
const urlParam = new URLSearchParams(window.location.search).get(name); const urlParam = new URLSearchParams(window.location.search).get(name);
switch (type) { switch (type) {