Skip to content

Commit

Permalink
feat(homescreen and cards): Toggle thumbnails off or on and feature f…
Browse files Browse the repository at this point in the history
…lag (#13683)
  • Loading branch information
pkdotson authored Mar 25, 2021
1 parent 1d5c58d commit 3e4c3bd
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ import thunk from 'redux-thunk';
import fetchMock from 'fetch-mock';
import { act } from 'react-dom/test-utils';
import configureStore from 'redux-mock-store';
import * as featureFlags from 'src/featureFlags';
import Welcome from 'src/views/CRUD/welcome/Welcome';
import { ReactWrapper } from 'enzyme';
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';

const mockStore = configureStore([thunk]);
const store = mockStore({});
Expand Down Expand Up @@ -92,19 +94,19 @@ fetchMock.get(savedQueryInfoEndpoint, {
permissions: [],
});

describe('Welcome', () => {
const mockedProps = {
user: {
username: 'alpha',
firstName: 'alpha',
lastName: 'alpha',
createdOn: '2016-11-11T12:34:17',
userId: 5,
email: 'alpha@alpha.com',
isActive: true,
},
};
const mockedProps = {
user: {
username: 'alpha',
firstName: 'alpha',
lastName: 'alpha',
createdOn: '2016-11-11T12:34:17',
userId: 5,
email: 'alpha@alpha.com',
isActive: true,
},
};

describe('Welcome', () => {
let wrapper: ReactWrapper;

beforeAll(async () => {
Expand Down Expand Up @@ -136,3 +138,44 @@ describe('Welcome', () => {
expect(dashboardCall).toHaveLength(1);
});
});

async function mountAndWait(props = mockedProps) {
const wrapper = mount(
<Provider store={store}>
<Welcome {...props} />
</Provider>,
);
await waitForComponentToPaint(wrapper);
return wrapper;
}

describe('Welcome page with toggle switch', () => {
let wrapper: ReactWrapper;
let isFeatureEnabledMock: any;

beforeAll(async () => {
isFeatureEnabledMock = jest
.spyOn(featureFlags, 'isFeatureEnabled')
.mockReturnValue(true);
await act(async () => {
wrapper = await mountAndWait();
});
});

afterAll(() => {
isFeatureEnabledMock.restore();
});

it('shows a toggle button when feature flags is turned on', async () => {
await waitForComponentToPaint(wrapper);
expect(wrapper.find('Switch')).toExist();
});
it('does not show thumbnails when switch is off', async () => {
act(() => {
// @ts-ignore
wrapper.find('button[role="switch"]').props().onClick();
});
await waitForComponentToPaint(wrapper);
expect(wrapper.find('ImageLoader')).not.toExist();
});
});
5 changes: 5 additions & 0 deletions superset-frontend/src/views/CRUD/chart/ChartCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ interface ChartCardProps {
favoriteStatus: boolean;
chartFilter?: string;
userId?: number;
showThumbnails?: boolean;
featureFlag?: boolean;
}

export default function ChartCard({
Expand All @@ -55,10 +57,12 @@ export default function ChartCard({
addSuccessToast,
refreshData,
loading,
showThumbnails,
saveFavoriteStatus,
favoriteStatus,
chartFilter,
userId,
featureFlag,
}: ChartCardProps) {
const canEdit = hasPerm('can_write');
const canDelete = hasPerm('can_write');
Expand Down Expand Up @@ -138,6 +142,7 @@ export default function ChartCard({
<ListViewCard
loading={loading}
title={chart.slice_name}
cover={!featureFlag || !showThumbnails ? <></> : null}
url={bulkSelectEnabled ? undefined : chart.url}
imgURL={chart.thumbnail_url || ''}
imgFallbackURL="/static/assets/images/chart-card-fallback.svg"
Expand Down
5 changes: 5 additions & 0 deletions superset-frontend/src/views/CRUD/dashboard/DashboardCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ interface DashboardCardProps {
favoriteStatus: boolean;
dashboardFilter?: string;
userId?: number;
showThumbnails?: boolean;
featureFlag?: boolean;
}

function DashboardCard({
Expand All @@ -60,6 +62,8 @@ function DashboardCard({
openDashboardEditModal,
favoriteStatus,
saveFavoriteStatus,
showThumbnails,
featureFlag,
}: DashboardCardProps) {
const canEdit = hasPerm('can_write');
const canDelete = hasPerm('can_write');
Expand Down Expand Up @@ -146,6 +150,7 @@ function DashboardCard({
titleRight={
<Label>{dashboard.published ? t('published') : t('draft')}</Label>
}
cover={!featureFlag || !showThumbnails ? <></> : null}
url={bulkSelectEnabled ? undefined : dashboard.url}
imgURL={dashboard.thumbnail_url}
imgFallbackURL="/static/assets/images/dashboard-card-fallback.svg"
Expand Down
2 changes: 2 additions & 0 deletions superset-frontend/src/views/CRUD/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export interface DashboardTableProps {
search: string;
user?: User;
mine: Array<Dashboard>;
showThumbnails?: boolean;
featureFlag?: boolean;
}

export interface Dashboard {
Expand Down
6 changes: 6 additions & 0 deletions superset-frontend/src/views/CRUD/welcome/ChartTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,17 @@ interface ChartTableProps {
chartFilter?: string;
user?: User;
mine: Array<any>;
showThumbnails: boolean;
featureFlag: boolean;
}

function ChartTable({
user,
addDangerToast,
addSuccessToast,
mine,
showThumbnails,
featureFlag,
}: ChartTableProps) {
const history = useHistory();
const {
Expand Down Expand Up @@ -180,7 +184,9 @@ function ChartTable({
chart={e}
userId={user?.userId}
hasPerm={hasPerm}
showThumbnails={showThumbnails}
bulkSelectEnabled={bulkSelectEnabled}
featureFlag={featureFlag}
refreshData={refreshData}
addDangerToast={addDangerToast}
addSuccessToast={addSuccessToast}
Expand Down
4 changes: 4 additions & 0 deletions superset-frontend/src/views/CRUD/welcome/DashboardTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ function DashboardTable({
addDangerToast,
addSuccessToast,
mine,
showThumbnails,
featureFlag,
}: DashboardTableProps) {
const history = useHistory();
const {
Expand Down Expand Up @@ -191,6 +193,8 @@ function DashboardTable({
dashboard={e}
hasPerm={hasPerm}
bulkSelectEnabled={false}
featureFlag={featureFlag}
showThumbnails={showThumbnails}
dashboardFilter={dashboardFilter}
refreshData={refreshData}
addDangerToast={addDangerToast}
Expand Down
10 changes: 8 additions & 2 deletions superset-frontend/src/views/CRUD/welcome/SavedQueries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ interface SavedQueriesProps {
addDangerToast: (arg0: string) => void;
addSuccessToast: (arg0: string) => void;
mine: Array<Query>;
showThumbnails: boolean;
featureFlag: boolean;
}

export const CardStyles = styled.div`
Expand Down Expand Up @@ -110,6 +112,8 @@ const SavedQueries = ({
addDangerToast,
addSuccessToast,
mine,
showThumbnails,
featureFlag,
}: SavedQueriesProps) => {
const {
state: { loading, resourceCollection: queries },
Expand Down Expand Up @@ -307,7 +311,7 @@ const SavedQueries = ({
imgFallbackURL="/static/assets/images/empty-query.svg"
description={t('Last run %s', q.changed_on_delta_humanized)}
cover={
q?.sql?.length ? (
q?.sql?.length && showThumbnails && featureFlag ? (
<QueryContainer>
<SyntaxHighlighter
language="sql"
Expand All @@ -328,8 +332,10 @@ const SavedQueries = ({
{shortenSQL(q.sql, 25)}
</SyntaxHighlighter>
</QueryContainer>
) : (
) : showThumbnails && !q?.sql?.length ? (
false
) : (
<></>
)
}
actions={
Expand Down
69 changes: 65 additions & 4 deletions superset-frontend/src/views/CRUD/welcome/Welcome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import { styled, t } from '@superset-ui/core';
import Collapse from 'src/common/components/Collapse';
import { User } from 'src/types/bootstrapTypes';
import { reject } from 'lodash';
import {
getFromLocalStorage,
setInLocalStorage,
} from 'src/utils/localStorageHelpers';
import withToasts from 'src/messageToasts/enhancers/withToasts';
import Loading from 'src/components/Loading';
import {
Expand All @@ -29,6 +33,8 @@ import {
mq,
getUserOwnedObjects,
} from 'src/views/CRUD/utils';
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
import { Switch } from 'src/common/components';

import ActivityTable from './ActivityTable';
import ChartTable from './ChartTable';
Expand Down Expand Up @@ -83,17 +89,44 @@ const WelcomeContainer = styled.div`
}
`;

const WelcomeNav = styled.div`
height: 50px;
background-color: white;
margin-top: ${({ theme }) => theme.gridUnit * -4 - 1}px;
.navbar-brand {
margin-left: ${({ theme }) => theme.gridUnit * 2}px;
font-weight: ${({ theme }) => theme.typography.weights.bold};
}
.switch {
float: right;
margin: ${({ theme }) => theme.gridUnit * 5}px;
display: flex;
flex-direction: row;
span {
display: block;
margin: ${({ theme }) => theme.gridUnit * 1}px;
line-height: 1;
}
}
`;

function Welcome({ user, addDangerToast }: WelcomeProps) {
const recent = `/superset/recent_activity/${user.userId}/?limit=6`;
const [activeChild, setActiveChild] = useState('Viewed');
const [checked, setChecked] = useState(true);
const [activityData, setActivityData] = useState<ActivityData | null>(null);
const [chartData, setChartData] = useState<Array<object> | null>(null);
const [queryData, setQueryData] = useState<Array<object> | null>(null);
const [dashboardData, setDashboardData] = useState<Array<object> | null>(
null,
);

const userid = user.userId;
const id = userid.toString();

useEffect(() => {
const userKey = getFromLocalStorage(id, null);
if (userKey && !userKey.thumbnails) setChecked(false);
getRecentAcitivtyObjs(user.userId, recent, addDangerToast)
.then(res => {
const data: ActivityData | null = {};
Expand All @@ -117,7 +150,6 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
);

// Sets other activity data in parallel with recents api call
const id = user.userId;
getUserOwnedObjects(id, 'dashboard')
.then(r => {
setDashboardData(r);
Expand Down Expand Up @@ -148,6 +180,11 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
});
}, []);

const handleToggle = () => {
setChecked(!checked);
setInLocalStorage(id, { thumbnails: !checked });
};

useEffect(() => {
setActivityData(activityData => ({
...activityData,
Expand All @@ -161,6 +198,15 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {

return (
<WelcomeContainer>
<WelcomeNav>
<span className="navbar-brand">Home</span>
{isFeatureEnabled(FeatureFlag.THUMBNAILS) ? (
<div className="switch">
<Switch checked={checked} onChange={handleToggle} />
<span>Thumbnails</span>
</div>
) : null}
</WelcomeNav>
<Collapse defaultActiveKey={['1', '2', '3', '4']} ghost bigger>
<Collapse.Panel header={t('Recents')} key="1">
{activityData && (activityData.Viewed || activityData.Examples) ? (
Expand All @@ -178,21 +224,36 @@ function Welcome({ user, addDangerToast }: WelcomeProps) {
{!dashboardData ? (
<Loading position="inline" />
) : (
<DashboardTable user={user} mine={dashboardData} />
<DashboardTable
user={user}
mine={dashboardData}
showThumbnails={checked}
featureFlag={isFeatureEnabled(FeatureFlag.THUMBNAILS)}
/>
)}
</Collapse.Panel>
<Collapse.Panel header={t('Saved queries')} key="3">
{!queryData ? (
<Loading position="inline" />
) : (
<SavedQueries user={user} mine={queryData} />
<SavedQueries
showThumbnails={checked}
user={user}
mine={queryData}
featureFlag={isFeatureEnabled(FeatureFlag.THUMBNAILS)}
/>
)}
</Collapse.Panel>
<Collapse.Panel header={t('Charts')} key="4">
{!chartData ? (
<Loading position="inline" />
) : (
<ChartTable user={user} mine={chartData} />
<ChartTable
showThumbnails={checked}
user={user}
mine={chartData}
featureFlag={isFeatureEnabled(FeatureFlag.THUMBNAILS)}
/>
)}
</Collapse.Panel>
</Collapse>
Expand Down

0 comments on commit 3e4c3bd

Please sign in to comment.