This is an automated email from the ASF dual-hosted git repository.
pkdotson pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 04c0680 feat(homepage): conditionally render viewed tab and move
examples to chart and dashboard table (#15792)
04c0680 is described below
commit 04c0680f6e3ca752c964f95942d440c0e3e3ae23
Author: Phillip Kelley-Dotson <[email protected]>
AuthorDate: Thu Jul 22 10:41:49 2021 -0700
feat(homepage): conditionally render viewed tab and move examples to chart
and dashboard table (#15792)
* test examples
* fix lint
* more lint
* last test
* add suggestions
* fix lint
* fix wrong localstor
* fix tests
* add suggestions
* Update superset-frontend/src/views/CRUD/types.ts
Co-authored-by: Michael S. Molina
<[email protected]>
* Update superset-frontend/src/views/CRUD/welcome/DashboardTable.tsx
Co-authored-by: Michael S. Molina
<[email protected]>
* fix lint
* fix default tab
* fix test
Co-authored-by: Michael S. Molina
<[email protected]>
---
superset-frontend/src/views/CRUD/types.ts | 2 +
.../src/views/CRUD/welcome/ActivityTable.tsx | 10 ---
.../src/views/CRUD/welcome/ChartTable.test.tsx | 2 +-
.../src/views/CRUD/welcome/ChartTable.tsx | 70 ++++++++++++++-------
.../src/views/CRUD/welcome/DashboardTable.test.tsx | 4 +-
.../src/views/CRUD/welcome/DashboardTable.tsx | 72 ++++++++++++++--------
.../src/views/CRUD/welcome/Welcome.test.tsx | 4 +-
.../src/views/CRUD/welcome/Welcome.tsx | 40 ++++++++----
8 files changed, 129 insertions(+), 75 deletions(-)
diff --git a/superset-frontend/src/views/CRUD/types.ts
b/superset-frontend/src/views/CRUD/types.ts
index 659686e..c7e47dd 100644
--- a/superset-frontend/src/views/CRUD/types.ts
+++ b/superset-frontend/src/views/CRUD/types.ts
@@ -26,6 +26,7 @@ export type FavoriteStatus = {
export enum TableTabTypes {
FAVORITE = 'Favorite',
MINE = 'Mine',
+ EXAMPLES = 'Examples',
}
export type Filters = {
@@ -42,6 +43,7 @@ export interface DashboardTableProps {
mine: Array<Dashboard>;
showThumbnails?: boolean;
featureFlag?: boolean;
+ examples: Array<Dashboard>;
}
export interface Dashboard {
diff --git a/superset-frontend/src/views/CRUD/welcome/ActivityTable.tsx
b/superset-frontend/src/views/CRUD/welcome/ActivityTable.tsx
index 82d97aa..1bacc30 100644
--- a/superset-frontend/src/views/CRUD/welcome/ActivityTable.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/ActivityTable.tsx
@@ -219,17 +219,7 @@ export default function ActivityTable({
setInLocalStorage(HOMEPAGE_ACTIVITY_FILTER, SetTabType.VIEWED);
},
});
- } else {
- tabs.unshift({
- name: 'Examples',
- label: t('Examples'),
- onClick: () => {
- setActiveChild('Examples');
- setInLocalStorage(HOMEPAGE_ACTIVITY_FILTER, SetTabType.EXAMPLE);
- },
- });
}
-
const renderActivity = () =>
(activeChild !== 'Edited' ? activityData[activeChild] : editedObjs).map(
(entity: ActivityObject) => {
diff --git a/superset-frontend/src/views/CRUD/welcome/ChartTable.test.tsx
b/superset-frontend/src/views/CRUD/welcome/ChartTable.test.tsx
index 986a5bf..c61cb1b 100644
--- a/superset-frontend/src/views/CRUD/welcome/ChartTable.test.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/ChartTable.test.tsx
@@ -85,7 +85,7 @@ describe('ChartTable', () => {
}
});
await waitForComponentToPaint(wrapper);
- expect(fetchMock.calls(chartsEndpoint)).toHaveLength(3);
+ expect(fetchMock.calls(chartsEndpoint)).toHaveLength(1);
expect(wrapper.find('ChartCard')).toExist();
});
diff --git a/superset-frontend/src/views/CRUD/welcome/ChartTable.tsx
b/superset-frontend/src/views/CRUD/welcome/ChartTable.tsx
index 3fa7caa..e0a4ad9 100644
--- a/superset-frontend/src/views/CRUD/welcome/ChartTable.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/ChartTable.tsx
@@ -18,6 +18,7 @@
*/
import React, { useState, useMemo, useEffect } from 'react';
import { t } from '@superset-ui/core';
+import { filter } from 'lodash';
import {
useListViewResource,
useChartEditModal,
@@ -52,6 +53,7 @@ interface ChartTableProps {
user?: User;
mine: Array<any>;
showThumbnails: boolean;
+ examples?: Array<object>;
}
function ChartTable({
@@ -60,10 +62,17 @@ function ChartTable({
addSuccessToast,
mine,
showThumbnails,
+ examples,
}: ChartTableProps) {
const history = useHistory();
const filterStore = getFromLocalStorage(HOMEPAGE_CHART_FILTER, null);
- const initialFilter = filterStore || TableTabTypes.MINE;
+ let initialFilter = filterStore || TableTabTypes.EXAMPLES;
+
+ if (!examples && filterStore === TableTabTypes.EXAMPLES) {
+ initialFilter = TableTabTypes.MINE;
+ }
+
+ const filteredExamples = filter(examples, obj => 'viz_type' in obj);
const {
state: { loading, resourceCollection: charts, bulkSelectEnabled },
@@ -76,7 +85,7 @@ function ChartTable({
t('chart'),
addDangerToast,
true,
- initialFilter === 'Favorite' ? [] : mine,
+ initialFilter === 'Mine' ? mine : filteredExamples,
[],
false,
);
@@ -96,9 +105,13 @@ function ChartTable({
const [chartFilter, setChartFilter] = useState(initialFilter);
const [preparingExport, setPreparingExport] = useState<boolean>(false);
+ const [loaded, setLoaded] = useState<boolean>(false);
useEffect(() => {
- getData(chartFilter);
+ if (loaded || chartFilter === 'Favorite') {
+ getData(chartFilter);
+ }
+ setLoaded(true);
}, [chartFilter]);
const handleBulkChartExport = (chartsToExport: Chart[]) => {
@@ -118,7 +131,7 @@ function ChartTable({
operator: 'rel_o_m',
value: `${user?.userId}`,
});
- } else {
+ } else if (filterName === 'Favorite') {
filters.push({
id: 'id',
operator: 'chart_is_favorite',
@@ -128,6 +141,36 @@ function ChartTable({
return filters;
};
+ const menuTabs = [
+ {
+ name: 'Favorite',
+ label: t('Favorite'),
+ onClick: () => {
+ setChartFilter(TableTabTypes.FAVORITE);
+ setInLocalStorage(HOMEPAGE_CHART_FILTER, TableTabTypes.FAVORITE);
+ },
+ },
+ {
+ name: 'Mine',
+ label: t('Mine'),
+ onClick: () => {
+ setChartFilter(TableTabTypes.MINE);
+ setInLocalStorage(HOMEPAGE_CHART_FILTER, TableTabTypes.MINE);
+ },
+ },
+ ];
+
+ if (examples) {
+ menuTabs.push({
+ name: 'Examples',
+ label: t('Examples'),
+ onClick: () => {
+ setChartFilter(TableTabTypes.EXAMPLES);
+ setInLocalStorage(HOMEPAGE_CHART_FILTER, TableTabTypes.EXAMPLES);
+ },
+ });
+ }
+
const getData = (filter: string) =>
fetchData({
pageIndex: 0,
@@ -156,24 +199,7 @@ function ChartTable({
<SubMenu
activeChild={chartFilter}
// eslint-disable-next-line react/no-children-prop
- tabs={[
- {
- name: 'Favorite',
- label: t('Favorite'),
- onClick: () => {
- setChartFilter('Favorite');
- setInLocalStorage(HOMEPAGE_CHART_FILTER, TableTabTypes.FAVORITE);
- },
- },
- {
- name: 'Mine',
- label: t('Mine'),
- onClick: () => {
- setChartFilter('Mine');
- setInLocalStorage(HOMEPAGE_CHART_FILTER, TableTabTypes.MINE);
- },
- },
- ]}
+ tabs={menuTabs}
buttons={[
{
name: (
diff --git a/superset-frontend/src/views/CRUD/welcome/DashboardTable.test.tsx
b/superset-frontend/src/views/CRUD/welcome/DashboardTable.test.tsx
index 078b14d..26fd3a1 100644
--- a/superset-frontend/src/views/CRUD/welcome/DashboardTable.test.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/DashboardTable.test.tsx
@@ -72,9 +72,9 @@ describe('DashboardTable', () => {
it('render a submenu with clickable tabs and buttons', async () => {
expect(wrapper.find('SubMenu')).toExist();
expect(wrapper.find('li.no-router')).toHaveLength(2);
- expect(wrapper.find('Button')).toHaveLength(4);
+ expect(wrapper.find('Button')).toHaveLength(6);
act(() => {
- const handler = wrapper.find('li.no-router a').at(1).prop('onClick');
+ const handler = wrapper.find('li.no-router a').at(0).prop('onClick');
if (handler) {
handler({} as any);
}
diff --git a/superset-frontend/src/views/CRUD/welcome/DashboardTable.tsx
b/superset-frontend/src/views/CRUD/welcome/DashboardTable.tsx
index 8db07c9..9e9cf6f 100644
--- a/superset-frontend/src/views/CRUD/welcome/DashboardTable.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/DashboardTable.tsx
@@ -18,6 +18,7 @@
*/
import React, { useState, useMemo, useEffect } from 'react';
import { SupersetClient, t } from '@superset-ui/core';
+import { filter } from 'lodash';
import { useListViewResource, useFavoriteStatus } from 'src/views/CRUD/hooks';
import {
Dashboard,
@@ -54,10 +55,17 @@ function DashboardTable({
addSuccessToast,
mine,
showThumbnails,
+ examples,
}: DashboardTableProps) {
const history = useHistory();
const filterStore = getFromLocalStorage(HOMEPAGE_DASHBOARD_FILTER, null);
- const defaultFilter = filterStore || TableTabTypes.MINE;
+ let defaultFilter = filterStore || TableTabTypes.EXAMPLES;
+
+ if (!examples && filterStore === TableTabTypes.EXAMPLES) {
+ defaultFilter = TableTabTypes.MINE;
+ }
+
+ const filteredExamples = filter(examples, obj => !('viz_type' in obj));
const {
state: { loading, resourceCollection: dashboards },
@@ -70,7 +78,7 @@ function DashboardTable({
t('dashboard'),
addDangerToast,
true,
- defaultFilter === 'Favorite' ? [] : mine,
+ defaultFilter === 'Mine' ? mine : filteredExamples,
[],
false,
);
@@ -84,9 +92,13 @@ function DashboardTable({
const [editModal, setEditModal] = useState<Dashboard>();
const [dashboardFilter, setDashboardFilter] = useState(defaultFilter);
const [preparingExport, setPreparingExport] = useState<boolean>(false);
+ const [loaded, setLoaded] = useState<boolean>(false);
useEffect(() => {
- getData(dashboardFilter);
+ if (loaded || dashboardFilter === 'Favorite') {
+ getData(dashboardFilter);
+ }
+ setLoaded(true);
}, [dashboardFilter]);
const handleBulkDashboardExport = (dashboardsToExport: Dashboard[]) => {
@@ -126,7 +138,7 @@ function DashboardTable({
operator: 'rel_m_m',
value: `${user?.userId}`,
});
- } else {
+ } else if (filterName === 'Favorite') {
filters.push({
id: 'id',
operator: 'dashboard_is_favorite',
@@ -136,6 +148,36 @@ function DashboardTable({
return filters;
};
+ const menuTabs = [
+ {
+ name: 'Favorite',
+ label: t('Favorite'),
+ onClick: () => {
+ setDashboardFilter(TableTabTypes.FAVORITE);
+ setInLocalStorage(HOMEPAGE_DASHBOARD_FILTER, TableTabTypes.FAVORITE);
+ },
+ },
+ {
+ name: 'Mine',
+ label: t('Mine'),
+ onClick: () => {
+ setDashboardFilter(TableTabTypes.MINE);
+ setInLocalStorage(HOMEPAGE_DASHBOARD_FILTER, TableTabTypes.MINE);
+ },
+ },
+ ];
+
+ if (examples) {
+ menuTabs.push({
+ name: 'Examples',
+ label: t('Examples'),
+ onClick: () => {
+ setDashboardFilter(TableTabTypes.EXAMPLES);
+ setInLocalStorage(HOMEPAGE_DASHBOARD_FILTER, TableTabTypes.EXAMPLES);
+ },
+ });
+ }
+
const getData = (filter: string) =>
fetchData({
pageIndex: 0,
@@ -154,27 +196,7 @@ function DashboardTable({
<>
<SubMenu
activeChild={dashboardFilter}
- tabs={[
- {
- name: 'Favorite',
- label: t('Favorite'),
- onClick: () => {
- setDashboardFilter(TableTabTypes.FAVORITE);
- setInLocalStorage(
- HOMEPAGE_DASHBOARD_FILTER,
- TableTabTypes.FAVORITE,
- );
- },
- },
- {
- name: 'Mine',
- label: t('Mine'),
- onClick: () => {
- setDashboardFilter(TableTabTypes.MINE);
- setInLocalStorage(HOMEPAGE_DASHBOARD_FILTER, TableTabTypes.MINE);
- },
- },
- ]}
+ tabs={menuTabs}
buttons={[
{
name: (
diff --git a/superset-frontend/src/views/CRUD/welcome/Welcome.test.tsx
b/superset-frontend/src/views/CRUD/welcome/Welcome.test.tsx
index 85c9530..d71864e 100644
--- a/superset-frontend/src/views/CRUD/welcome/Welcome.test.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/Welcome.test.tsx
@@ -132,10 +132,10 @@ describe('Welcome', () => {
const savedQueryCall = fetchMock.calls(/saved_query\/\?q/);
const recentCall = fetchMock.calls(/superset\/recent_activity\/*/);
const dashboardCall = fetchMock.calls(/dashboard\/\?q/);
- expect(chartCall).toHaveLength(2);
+ expect(chartCall).toHaveLength(1);
expect(recentCall).toHaveLength(1);
expect(savedQueryCall).toHaveLength(1);
- expect(dashboardCall).toHaveLength(2);
+ expect(dashboardCall).toHaveLength(1);
});
});
diff --git a/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
b/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
index 36a0e44..df44671 100644
--- a/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
@@ -54,6 +54,8 @@ export interface ActivityData {
Examples?: Array<object>;
}
+const DEFAULT_TAB_ARR = ['2', '3'];
+
const WelcomeContainer = styled.div`
background-color: ${({ theme }) => theme.colors.grayscale.light4};
.ant-row.menu {
@@ -114,11 +116,9 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
null,
);
const [loadedCount, setLoadedCount] = useState(0);
- const [activeState, setActiveState] = useState<Array<string>>([
- '1',
- '2',
- '3',
- ]);
+ const [activeState, setActiveState] = useState<Array<string>>(
+ DEFAULT_TAB_ARR,
+ );
const userid = user.userId;
const id = userid.toString();
@@ -136,14 +136,15 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
if (res.viewed) {
const filtered = reject(res.viewed, ['item_url', null]).map(r => r);
data.Viewed = filtered;
- if (!activeTab) {
+ if (!activeTab && data.Viewed) {
setActiveChild('Viewed');
+ } else if (!activeTab && !data.Viewed) {
+ setActiveChild('Created');
} else setActiveChild(activeTab);
} else {
+ if (!activeTab) setActiveChild('Created');
+ else setActiveChild(activeTab);
data.Examples = res.examples;
- if (activeTab === 'Viewed' || !activeTab) {
- setActiveChild('Examples');
- } else setActiveChild(activeTab);
}
setActivityData(activityData => ({ ...activityData, ...data }));
})
@@ -200,9 +201,14 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
};
useEffect(() => {
+ const defaultArr = DEFAULT_TAB_ARR;
+ if (activityData?.Viewed) {
+ defaultArr.push('1');
+ }
if (queryData?.length) {
- setActiveState(['1', '2', '3', '4']);
+ defaultArr.push('4');
}
+ setActiveState(defaultArr);
setActivityData(activityData => ({
...activityData,
Created: [
@@ -213,6 +219,8 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
}));
}, [chartData, queryData, dashboardData]);
+ const isRecentActivityLoading =
+ !activityData?.Examples && !activityData?.Viewed;
return (
<WelcomeContainer>
<WelcomeNav>
@@ -243,21 +251,27 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
)}
</Collapse.Panel>
<Collapse.Panel header={t('Dashboards')} key="2">
- {!dashboardData ? (
+ {!dashboardData || isRecentActivityLoading ? (
<Loading position="inline" />
) : (
<DashboardTable
user={user}
mine={dashboardData}
showThumbnails={checked}
+ examples={activityData?.Examples}
/>
)}
</Collapse.Panel>
<Collapse.Panel header={t('Charts')} key="3">
- {!chartData ? (
+ {!chartData || isRecentActivityLoading ? (
<Loading position="inline" />
) : (
- <ChartTable showThumbnails={checked} user={user} mine={chartData}
/>
+ <ChartTable
+ showThumbnails={checked}
+ user={user}
+ mine={chartData}
+ examples={activityData?.Examples}
+ />
)}
</Collapse.Panel>
<Collapse.Panel header={t('Saved queries')} key="4">