mirror of
https://github.com/apache/superset.git
synced 2024-09-17 11:09:47 -04:00
chore: Homepage cleanup (#14823)
* initial commit * update welcome * fix lint * add enum * more choring * fix lint * redo logic for api stick api calls * fix test * fix chart test * lint fix and remove unused code * fix flicker and add suggestions * lint * fix test * add suggestions * add suggestions and fix test * revert packagelock * fix space
This commit is contained in:
parent
53df152362
commit
8e6a5a6f52
23
superset-frontend/src/views/CRUD/storageKeys.ts
Normal file
23
superset-frontend/src/views/CRUD/storageKeys.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// storage keys for welcome page sticky tabs..
|
||||
export const HOMEPAGE_CHART_FILTER = 'homepage_chart_filter';
|
||||
export const HOMEPAGE_ACTIVITY_FILTER = 'homepage_activity_filter';
|
||||
export const HOMEPAGE_DASHBOARD_FILTER = 'homepage_dashboard_filter';
|
@ -23,6 +23,11 @@ export type FavoriteStatus = {
|
||||
[id: number]: boolean;
|
||||
};
|
||||
|
||||
export enum TableTabTypes {
|
||||
FAVORITE = 'Favorite',
|
||||
MINE = 'Mine',
|
||||
}
|
||||
|
||||
export type Filters = {
|
||||
col: string;
|
||||
opr: string;
|
||||
|
@ -23,7 +23,6 @@ import { ReactWrapper } from 'enzyme';
|
||||
import { Provider } from 'react-redux';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import thunk from 'redux-thunk';
|
||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import ActivityTable from 'src/views/CRUD/welcome/ActivityTable';
|
||||
|
||||
@ -82,7 +81,7 @@ describe('ActivityTable', () => {
|
||||
activityData: mockData,
|
||||
setActiveChild: jest.fn(),
|
||||
user: { userId: '1' },
|
||||
loading: false,
|
||||
loadedCount: 3,
|
||||
};
|
||||
|
||||
let wrapper: ReactWrapper;
|
||||
@ -113,19 +112,21 @@ describe('ActivityTable', () => {
|
||||
handler({} as any);
|
||||
}
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
const dashboardCall = fetchMock.calls(/dashboard\/\?q/);
|
||||
const chartCall = fetchMock.calls(/chart\/\?q/);
|
||||
// waitforcomponenttopaint does not work here in this instance...
|
||||
setTimeout(() => {
|
||||
expect(chartCall).toHaveLength(1);
|
||||
expect(dashboardCall).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
it('show empty state if there is no data', () => {
|
||||
const activityProps = {
|
||||
activeChild: 'Created',
|
||||
activityData: {},
|
||||
setActiveChild: jest.fn(),
|
||||
user: { userId: '1' },
|
||||
loading: false,
|
||||
loadedCount: 3,
|
||||
};
|
||||
const wrapper = mount(
|
||||
<Provider store={store}>
|
||||
|
@ -24,9 +24,10 @@ import { setInLocalStorage } from 'src/utils/localStorageHelpers';
|
||||
import Loading from 'src/components/Loading';
|
||||
import ListViewCard from 'src/components/ListViewCard';
|
||||
import SubMenu from 'src/components/Menu/SubMenu';
|
||||
import { mq, CardStyles, getEditedObjects } from 'src/views/CRUD/utils';
|
||||
import { HOMEPAGE_ACTIVITY_FILTER } from 'src/views/CRUD/storageKeys';
|
||||
import { Chart } from 'src/types/Chart';
|
||||
import { Dashboard, SavedQueryObject } from 'src/views/CRUD/types';
|
||||
import { mq, CardStyles, getEditedObjects } from 'src/views/CRUD/utils';
|
||||
|
||||
import { ActivityData } from './Welcome';
|
||||
import EmptyState from './EmptyState';
|
||||
@ -51,6 +52,12 @@ interface RecentDashboard extends RecentActivity {
|
||||
item_type: 'dashboard';
|
||||
}
|
||||
|
||||
enum SetTabType {
|
||||
EDITED = 'Edited',
|
||||
CREATED = 'Created',
|
||||
VIEWED = 'Viewed',
|
||||
EXAMPLE = 'Examples',
|
||||
}
|
||||
/**
|
||||
* Recent activity objects fetched by `getRecentAcitivtyObjs`.
|
||||
*/
|
||||
@ -68,6 +75,7 @@ interface ActivityProps {
|
||||
activeChild: string;
|
||||
setActiveChild: (arg0: string) => void;
|
||||
activityData: ActivityData;
|
||||
loadedCount: number;
|
||||
}
|
||||
|
||||
const ActivityContainer = styled.div`
|
||||
@ -161,20 +169,11 @@ export default function ActivityTable({
|
||||
setActiveChild,
|
||||
activityData,
|
||||
user,
|
||||
loadedCount,
|
||||
}: ActivityProps) {
|
||||
const [editedObjs, setEditedObjs] = useState<Array<ActivityData>>();
|
||||
const [loadingState, setLoadingState] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeChild === 'Edited') {
|
||||
setLoadingState(true);
|
||||
getEditedObjects(user.userId).then(r => {
|
||||
setEditedObjs([...r.editedChart, ...r.editedDash]);
|
||||
setLoadingState(false);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getEditedCards = () => {
|
||||
setLoadingState(true);
|
||||
getEditedObjects(user.userId).then(r => {
|
||||
@ -182,14 +181,21 @@ export default function ActivityTable({
|
||||
setLoadingState(false);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (activeChild === 'Edited') {
|
||||
setLoadingState(true);
|
||||
getEditedCards();
|
||||
}
|
||||
}, [activeChild]);
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
name: 'Edited',
|
||||
label: t('Edited'),
|
||||
onClick: () => {
|
||||
setActiveChild('Edited');
|
||||
setInLocalStorage('activity', { activity: 'Edited' });
|
||||
getEditedCards();
|
||||
setInLocalStorage(HOMEPAGE_ACTIVITY_FILTER, SetTabType.EDITED);
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -197,7 +203,7 @@ export default function ActivityTable({
|
||||
label: t('Created'),
|
||||
onClick: () => {
|
||||
setActiveChild('Created');
|
||||
setInLocalStorage('activity', { activity: 'Created' });
|
||||
setInLocalStorage(HOMEPAGE_ACTIVITY_FILTER, SetTabType.CREATED);
|
||||
},
|
||||
},
|
||||
];
|
||||
@ -208,7 +214,7 @@ export default function ActivityTable({
|
||||
label: t('Viewed'),
|
||||
onClick: () => {
|
||||
setActiveChild('Viewed');
|
||||
setInLocalStorage('activity', { activity: 'Viewed' });
|
||||
setInLocalStorage(HOMEPAGE_ACTIVITY_FILTER, SetTabType.VIEWED);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
@ -217,7 +223,7 @@ export default function ActivityTable({
|
||||
label: t('Examples'),
|
||||
onClick: () => {
|
||||
setActiveChild('Examples');
|
||||
setInLocalStorage('activity', { activity: 'Examples' });
|
||||
setInLocalStorage(HOMEPAGE_ACTIVITY_FILTER, SetTabType.EXAMPLE);
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -246,16 +252,15 @@ export default function ActivityTable({
|
||||
);
|
||||
},
|
||||
);
|
||||
if (loadingState && !editedObjs) {
|
||||
|
||||
const doneFetching = loadedCount < 3;
|
||||
|
||||
if ((loadingState && !editedObjs) || doneFetching) {
|
||||
return <Loading position="inline" />;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<SubMenu
|
||||
activeChild={activeChild}
|
||||
// eslint-disable-next-line react/no-children-prop
|
||||
tabs={tabs}
|
||||
/>
|
||||
<SubMenu activeChild={activeChild} tabs={tabs} />
|
||||
{activityData[activeChild]?.length > 0 ||
|
||||
(activeChild === 'Edited' && editedObjs && editedObjs.length > 0) ? (
|
||||
<ActivityContainer>{renderActivity()}</ActivityContainer>
|
||||
|
@ -85,11 +85,21 @@ describe('ChartTable', () => {
|
||||
}
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(fetchMock.calls(chartsEndpoint)).toHaveLength(1);
|
||||
expect(fetchMock.calls(chartsEndpoint)).toHaveLength(3);
|
||||
expect(wrapper.find('ChartCard')).toExist();
|
||||
});
|
||||
|
||||
it('display EmptyState if there is no data', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mount(
|
||||
<ChartTable
|
||||
chartFilter="Mine"
|
||||
user={{ userId: '2' }}
|
||||
mine={[]}
|
||||
store={store}
|
||||
/>,
|
||||
);
|
||||
});
|
||||
expect(wrapper.find('EmptyState')).toExist();
|
||||
});
|
||||
});
|
||||
|
@ -29,8 +29,11 @@ import {
|
||||
} from 'src/utils/localStorageHelpers';
|
||||
import withToasts from 'src/messageToasts/enhancers/withToasts';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { TableTabTypes } from 'src/views/CRUD/types';
|
||||
import PropertiesModal from 'src/explore/components/PropertiesModal';
|
||||
import { User } from 'src/types/bootstrapTypes';
|
||||
import { CardContainer } from 'src/views/CRUD/utils';
|
||||
import { HOMEPAGE_CHART_FILTER } from 'src/views/CRUD/storageKeys';
|
||||
import ChartCard from 'src/views/CRUD/chart/ChartCard';
|
||||
import Chart from 'src/types/Chart';
|
||||
import handleResourceExport from 'src/utils/export';
|
||||
@ -38,7 +41,6 @@ import Loading from 'src/components/Loading';
|
||||
import ErrorBoundary from 'src/components/ErrorBoundary';
|
||||
import SubMenu from 'src/components/Menu/SubMenu';
|
||||
import EmptyState from './EmptyState';
|
||||
import { CardContainer } from '../utils';
|
||||
|
||||
const PAGE_SIZE = 3;
|
||||
|
||||
@ -60,6 +62,9 @@ function ChartTable({
|
||||
showThumbnails,
|
||||
}: ChartTableProps) {
|
||||
const history = useHistory();
|
||||
const filterStore = getFromLocalStorage(HOMEPAGE_CHART_FILTER, null);
|
||||
const initialFilter = filterStore || TableTabTypes.MINE;
|
||||
|
||||
const {
|
||||
state: { loading, resourceCollection: charts, bulkSelectEnabled },
|
||||
setResourceCollection: setCharts,
|
||||
@ -71,12 +76,11 @@ function ChartTable({
|
||||
t('chart'),
|
||||
addDangerToast,
|
||||
true,
|
||||
mine,
|
||||
initialFilter === 'Favorite' ? [] : mine,
|
||||
[],
|
||||
false,
|
||||
);
|
||||
|
||||
useEffect(() => {});
|
||||
const chartIds = useMemo(() => charts.map(c => c.id), [charts]);
|
||||
const [saveFavoriteStatus, favoriteStatus] = useFavoriteStatus(
|
||||
'chart',
|
||||
@ -90,15 +94,12 @@ function ChartTable({
|
||||
closeChartEditModal,
|
||||
} = useChartEditModal(setCharts, charts);
|
||||
|
||||
const [chartFilter, setChartFilter] = useState('Mine');
|
||||
const [chartFilter, setChartFilter] = useState(initialFilter);
|
||||
const [preparingExport, setPreparingExport] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const filter = getFromLocalStorage('chart', null);
|
||||
if (!filter) {
|
||||
setChartFilter('Mine');
|
||||
} else setChartFilter(filter.tab);
|
||||
}, []);
|
||||
getData(chartFilter);
|
||||
}, [chartFilter]);
|
||||
|
||||
const handleBulkChartExport = (chartsToExport: Chart[]) => {
|
||||
const ids = chartsToExport.map(({ id }) => id);
|
||||
@ -159,20 +160,18 @@ function ChartTable({
|
||||
{
|
||||
name: 'Favorite',
|
||||
label: t('Favorite'),
|
||||
onClick: () =>
|
||||
getData('Favorite').then(() => {
|
||||
onClick: () => {
|
||||
setChartFilter('Favorite');
|
||||
setInLocalStorage('chart', { tab: 'Favorite' });
|
||||
}),
|
||||
setInLocalStorage(HOMEPAGE_CHART_FILTER, TableTabTypes.FAVORITE);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Mine',
|
||||
label: t('Mine'),
|
||||
onClick: () =>
|
||||
getData('Mine').then(() => {
|
||||
onClick: () => {
|
||||
setChartFilter('Mine');
|
||||
setInLocalStorage('chart', { tab: 'Mine' });
|
||||
}),
|
||||
setInLocalStorage(HOMEPAGE_CHART_FILTER, TableTabTypes.MINE);
|
||||
},
|
||||
},
|
||||
]}
|
||||
buttons={[
|
||||
|
@ -19,20 +19,26 @@
|
||||
import React, { useState, useMemo, useEffect } from 'react';
|
||||
import { SupersetClient, t } from '@superset-ui/core';
|
||||
import { useListViewResource, useFavoriteStatus } from 'src/views/CRUD/hooks';
|
||||
import { Dashboard, DashboardTableProps } from 'src/views/CRUD/types';
|
||||
import {
|
||||
Dashboard,
|
||||
DashboardTableProps,
|
||||
TableTabTypes,
|
||||
} from 'src/views/CRUD/types';
|
||||
import handleResourceExport from 'src/utils/export';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
setInLocalStorage,
|
||||
getFromLocalStorage,
|
||||
} from 'src/utils/localStorageHelpers';
|
||||
import { createErrorHandler, CardContainer } from 'src/views/CRUD/utils';
|
||||
import { HOMEPAGE_DASHBOARD_FILTER } from 'src/views/CRUD/storageKeys';
|
||||
|
||||
import withToasts from 'src/messageToasts/enhancers/withToasts';
|
||||
import Loading from 'src/components/Loading';
|
||||
import PropertiesModal from 'src/dashboard/components/PropertiesModal';
|
||||
import DashboardCard from 'src/views/CRUD/dashboard/DashboardCard';
|
||||
import SubMenu from 'src/components/Menu/SubMenu';
|
||||
import EmptyState from './EmptyState';
|
||||
import { createErrorHandler, CardContainer } from '../utils';
|
||||
|
||||
const PAGE_SIZE = 3;
|
||||
|
||||
@ -50,6 +56,9 @@ function DashboardTable({
|
||||
showThumbnails,
|
||||
}: DashboardTableProps) {
|
||||
const history = useHistory();
|
||||
const filterStore = getFromLocalStorage(HOMEPAGE_DASHBOARD_FILTER, null);
|
||||
const defaultFilter = filterStore || TableTabTypes.MINE;
|
||||
|
||||
const {
|
||||
state: { loading, resourceCollection: dashboards },
|
||||
setResourceCollection: setDashboards,
|
||||
@ -61,7 +70,7 @@ function DashboardTable({
|
||||
t('dashboard'),
|
||||
addDangerToast,
|
||||
true,
|
||||
mine,
|
||||
defaultFilter === 'Favorite' ? [] : mine,
|
||||
[],
|
||||
false,
|
||||
);
|
||||
@ -71,16 +80,14 @@ function DashboardTable({
|
||||
dashboardIds,
|
||||
addDangerToast,
|
||||
);
|
||||
|
||||
const [editModal, setEditModal] = useState<Dashboard>();
|
||||
const [dashboardFilter, setDashboardFilter] = useState('Mine');
|
||||
const [dashboardFilter, setDashboardFilter] = useState(defaultFilter);
|
||||
const [preparingExport, setPreparingExport] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
const filter = getFromLocalStorage('dashboard', null);
|
||||
if (!filter) {
|
||||
setDashboardFilter('Mine');
|
||||
} else setDashboardFilter(filter.tab);
|
||||
}, []);
|
||||
getData(dashboardFilter);
|
||||
}, [dashboardFilter]);
|
||||
|
||||
const handleBulkDashboardExport = (dashboardsToExport: Dashboard[]) => {
|
||||
const ids = dashboardsToExport.map(({ id }) => id);
|
||||
@ -128,14 +135,6 @@ function DashboardTable({
|
||||
}
|
||||
return filters;
|
||||
};
|
||||
const subMenus = [];
|
||||
if (dashboards.length > 0 && dashboardFilter === 'favorite') {
|
||||
subMenus.push({
|
||||
name: 'Favorite',
|
||||
label: t('Favorite'),
|
||||
onClick: () => setDashboardFilter('Favorite'),
|
||||
});
|
||||
}
|
||||
|
||||
const getData = (filter: string) =>
|
||||
fetchData({
|
||||
@ -160,20 +159,19 @@ function DashboardTable({
|
||||
name: 'Favorite',
|
||||
label: t('Favorite'),
|
||||
onClick: () => {
|
||||
getData('Favorite').then(() => {
|
||||
setDashboardFilter('Favorite');
|
||||
setInLocalStorage('dashboard', { tab: 'Favorite' });
|
||||
});
|
||||
setDashboardFilter(TableTabTypes.FAVORITE);
|
||||
setInLocalStorage(
|
||||
HOMEPAGE_DASHBOARD_FILTER,
|
||||
TableTabTypes.FAVORITE,
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Mine',
|
||||
label: t('Mine'),
|
||||
onClick: () => {
|
||||
getData('Mine').then(() => {
|
||||
setDashboardFilter('Mine');
|
||||
setInLocalStorage('dashboard', { tab: 'Mine' });
|
||||
});
|
||||
setDashboardFilter(TableTabTypes.MINE);
|
||||
setInLocalStorage(HOMEPAGE_DASHBOARD_FILTER, TableTabTypes.MINE);
|
||||
},
|
||||
},
|
||||
]}
|
||||
|
@ -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(1);
|
||||
expect(chartCall).toHaveLength(2);
|
||||
expect(recentCall).toHaveLength(1);
|
||||
expect(savedQueryCall).toHaveLength(1);
|
||||
expect(dashboardCall).toHaveLength(1);
|
||||
expect(dashboardCall).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -33,6 +33,7 @@ import {
|
||||
mq,
|
||||
getUserOwnedObjects,
|
||||
} from 'src/views/CRUD/utils';
|
||||
import { HOMEPAGE_ACTIVITY_FILTER } from 'src/views/CRUD/storageKeys';
|
||||
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
|
||||
import { Switch } from 'src/common/components';
|
||||
|
||||
@ -65,7 +66,7 @@ const WelcomeContainer = styled.div`
|
||||
margin: 0px ${({ theme }) => theme.gridUnit * 6}px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
${[mq[1]]} {
|
||||
${mq[1]} {
|
||||
margin-top: 5px;
|
||||
margin: 0px 2px;
|
||||
}
|
||||
@ -104,7 +105,7 @@ const WelcomeNav = styled.div`
|
||||
|
||||
function Welcome({ user, addDangerToast }: WelcomeProps) {
|
||||
const recent = `/superset/recent_activity/${user.userId}/?limit=6`;
|
||||
const [activeChild, setActiveChild] = useState('Viewed');
|
||||
const [activeChild, setActiveChild] = useState('Loading');
|
||||
const [checked, setChecked] = useState(true);
|
||||
const [activityData, setActivityData] = useState<ActivityData | null>(null);
|
||||
const [chartData, setChartData] = useState<Array<object> | null>(null);
|
||||
@ -112,12 +113,14 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
|
||||
const [dashboardData, setDashboardData] = useState<Array<object> | null>(
|
||||
null,
|
||||
);
|
||||
const [loadedCount, setLoadedCount] = useState(0);
|
||||
|
||||
const userid = user.userId;
|
||||
const id = userid.toString();
|
||||
|
||||
useEffect(() => {
|
||||
const userKey = getFromLocalStorage(id, null);
|
||||
const activeTab = getFromLocalStorage(HOMEPAGE_ACTIVITY_FILTER, null);
|
||||
if (userKey && !userKey.thumbnails) setChecked(false);
|
||||
getRecentAcitivtyObjs(user.userId, recent, addDangerToast)
|
||||
.then(res => {
|
||||
@ -125,13 +128,14 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
|
||||
if (res.viewed) {
|
||||
const filtered = reject(res.viewed, ['item_url', null]).map(r => r);
|
||||
data.Viewed = filtered;
|
||||
const savedActivity = getFromLocalStorage('activity', null);
|
||||
if (!savedActivity) {
|
||||
if (!activeTab) {
|
||||
setActiveChild('Viewed');
|
||||
} else setActiveChild(savedActivity.activity);
|
||||
} else setActiveChild(activeTab);
|
||||
} else {
|
||||
data.Examples = res.examples;
|
||||
if (activeTab === 'Viewed' || !activeTab) {
|
||||
setActiveChild('Examples');
|
||||
} else setActiveChild(activeTab);
|
||||
}
|
||||
setActivityData(activityData => ({ ...activityData, ...data }));
|
||||
})
|
||||
@ -145,12 +149,15 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
|
||||
);
|
||||
|
||||
// Sets other activity data in parallel with recents api call
|
||||
|
||||
getUserOwnedObjects(id, 'dashboard')
|
||||
.then(r => {
|
||||
setDashboardData(r);
|
||||
setLoadedCount(loadedCount => loadedCount + 1);
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
setDashboardData([]);
|
||||
setLoadedCount(loadedCount => loadedCount + 1);
|
||||
addDangerToast(
|
||||
t('There was an issues fetching your dashboards: %s', err),
|
||||
);
|
||||
@ -158,17 +165,21 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
|
||||
getUserOwnedObjects(id, 'chart')
|
||||
.then(r => {
|
||||
setChartData(r);
|
||||
setLoadedCount(loadedCount => loadedCount + 1);
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
setChartData([]);
|
||||
setLoadedCount(loadedCount => loadedCount + 1);
|
||||
addDangerToast(t('There was an issues fetching your chart: %s', err));
|
||||
});
|
||||
getUserOwnedObjects(id, 'saved_query')
|
||||
.then(r => {
|
||||
setQueryData(r);
|
||||
setLoadedCount(loadedCount => loadedCount + 1);
|
||||
})
|
||||
.catch((err: unknown) => {
|
||||
setQueryData([]);
|
||||
setLoadedCount(loadedCount => loadedCount + 1);
|
||||
addDangerToast(
|
||||
t('There was an issues fetching your saved queries: %s', err),
|
||||
);
|
||||
@ -204,12 +215,17 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
|
||||
</WelcomeNav>
|
||||
<Collapse defaultActiveKey={['1', '2', '3', '4']} ghost bigger>
|
||||
<Collapse.Panel header={t('Recents')} key="1">
|
||||
{activityData && (activityData.Viewed || activityData.Examples) ? (
|
||||
{activityData &&
|
||||
(activityData.Viewed ||
|
||||
activityData.Examples ||
|
||||
activityData.Created) &&
|
||||
activeChild !== 'Loading' ? (
|
||||
<ActivityTable
|
||||
user={user}
|
||||
activeChild={activeChild}
|
||||
setActiveChild={setActiveChild}
|
||||
activityData={activityData}
|
||||
loadedCount={loadedCount}
|
||||
/>
|
||||
) : (
|
||||
<Loading position="inline" />
|
||||
|
Loading…
Reference in New Issue
Block a user