diff --git a/superset-frontend/src/views/CRUD/chart/ChartCard.tsx b/superset-frontend/src/views/CRUD/chart/ChartCard.tsx index 07f9dbf3bfbd8..69812bd641559 100644 --- a/superset-frontend/src/views/CRUD/chart/ChartCard.tsx +++ b/superset-frontend/src/views/CRUD/chart/ChartCard.tsx @@ -43,7 +43,7 @@ interface ChartCardProps { saveFavoriteStatus: (id: number, isStarred: boolean) => void; favoriteStatus: boolean; chartFilter?: string; - userId?: number; + userId?: string | number; showThumbnails?: boolean; handleBulkChartExport: (chartsToExport: Chart[]) => void; } @@ -165,11 +165,13 @@ export default function ChartCard({ e.preventDefault(); }} > - + {userId && ( + + )} diff --git a/superset-frontend/src/views/CRUD/chart/ChartList.test.jsx b/superset-frontend/src/views/CRUD/chart/ChartList.test.jsx index fa5d363c5123e..fd9aee16ab06c 100644 --- a/superset-frontend/src/views/CRUD/chart/ChartList.test.jsx +++ b/superset-frontend/src/views/CRUD/chart/ChartList.test.jsx @@ -17,6 +17,7 @@ * under the License. */ import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; import { Provider } from 'react-redux'; @@ -34,6 +35,9 @@ import ConfirmStatusChange from 'src/components/ConfirmStatusChange'; import ListView from 'src/components/ListView'; import PropertiesModal from 'src/explore/components/PropertiesModal'; import ListViewCard from 'src/components/ListViewCard'; +import FaveStar from 'src/components/FaveStar'; +import TableCollection from 'src/components/TableCollection'; +import CardCollection from 'src/components/ListView/CardCollection'; // store needed for withToasts(ChartTable) const mockStore = configureStore([thunk]); const store = mockStore({}); @@ -105,13 +109,17 @@ describe('ChartList', () => { }); const mockedProps = {}; - const wrapper = mount( - - - , - ); + let wrapper; beforeAll(async () => { + wrapper = mount( + + + + + , + ); + await waitForComponentToPaint(wrapper); }); @@ -159,6 +167,18 @@ describe('ChartList', () => { await waitForComponentToPaint(wrapper); expect(wrapper.find(ConfirmStatusChange)).toExist(); }); + + it('renders the Favorite Star column in list view for logged in user', async () => { + wrapper.find('[aria-label="list-view"]').first().simulate('click'); + await waitForComponentToPaint(wrapper); + expect(wrapper.find(TableCollection).find(FaveStar)).toExist(); + }); + + it('renders the Favorite Star in card view for logged in user', async () => { + wrapper.find('[aria-label="card-view"]').first().simulate('click'); + await waitForComponentToPaint(wrapper); + expect(wrapper.find(CardCollection).find(FaveStar)).toExist(); + }); }); describe('RTL', () => { @@ -201,3 +221,39 @@ describe('RTL', () => { expect(importTooltip).toBeInTheDocument(); }); }); + +describe('ChartList - anonymous view', () => { + const mockedProps = {}; + const mockUserLoggedOut = {}; + let wrapper; + + beforeAll(async () => { + fetchMock.resetHistory(); + wrapper = mount( + + + + + , + ); + + await waitForComponentToPaint(wrapper); + }); + + afterAll(() => { + cleanup(); + fetch.resetMocks(); + }); + + it('does not render the Favorite Star column in list view for anonymous user', async () => { + wrapper.find('[aria-label="list-view"]').first().simulate('click'); + await waitForComponentToPaint(wrapper); + expect(wrapper.find(TableCollection).find(FaveStar)).not.toExist(); + }); + + it('does not render the Favorite Star in card view for anonymous user', async () => { + wrapper.find('[aria-label="card-view"]').first().simulate('click'); + await waitForComponentToPaint(wrapper); + expect(wrapper.find(CardCollection).find(FaveStar)).not.toExist(); + }); +}); diff --git a/superset-frontend/src/views/CRUD/chart/ChartList.tsx b/superset-frontend/src/views/CRUD/chart/ChartList.tsx index 2645aa41c74ba..637e9b6ea72c0 100644 --- a/superset-frontend/src/views/CRUD/chart/ChartList.tsx +++ b/superset-frontend/src/views/CRUD/chart/ChartList.tsx @@ -22,7 +22,7 @@ import { SupersetClient, t, } from '@superset-ui/core'; -import React, { useMemo, useState } from 'react'; +import React, { useState, useMemo, useCallback } from 'react'; import rison from 'rison'; import { uniqBy } from 'lodash'; import moment from 'moment'; @@ -146,7 +146,11 @@ const Actions = styled.div` `; function ChartList(props: ChartListProps) { - const { addDangerToast, addSuccessToast } = props; + const { + addDangerToast, + addSuccessToast, + user: { userId }, + } = props; const { state: { @@ -180,7 +184,6 @@ function ChartList(props: ChartListProps) { const [passwordFields, setPasswordFields] = useState([]); const [preparingExport, setPreparingExport] = useState(false); - const { userId } = props.user; // TODO: Fix usage of localStorage keying on the user id const userSettings = dangerouslyGetItemDoNotUse(userId?.toString(), null) as { thumbnails: boolean; @@ -235,27 +238,25 @@ function ChartList(props: ChartListProps) { const columns = useMemo( () => [ - ...(props.user.userId - ? [ - { - Cell: ({ - row: { - original: { id }, - }, - }: any) => ( - - ), - Header: '', - id: 'id', - disableSortBy: true, - size: 'sm', - }, - ] - : []), + { + Cell: ({ + row: { + original: { id }, + }, + }: any) => + userId && ( + + ), + Header: '', + id: 'id', + disableSortBy: true, + size: 'xs', + hidden: !userId, + }, { Cell: ({ row: { @@ -451,10 +452,15 @@ function ChartList(props: ChartListProps) { }, ], [ + userId, canEdit, canDelete, canExport, - ...(props.user.userId ? [favoriteStatus] : []), + saveFavoriteStatus, + favoriteStatus, + refreshData, + addSuccessToast, + addDangerToast, ], ); @@ -552,7 +558,7 @@ function ChartList(props: ChartListProps) { fetchSelects: createFetchDatasets, paginate: true, }, - ...(props.user.userId ? [favoritesFilter] : []), + ...(userId ? [favoritesFilter] : []), { Header: t('Certified'), id: 'id', @@ -596,8 +602,8 @@ function ChartList(props: ChartListProps) { }, ]; - function renderCard(chart: Chart) { - return ( + const renderCard = useCallback( + (chart: Chart) => ( - ); - } + ), + [ + addDangerToast, + addSuccessToast, + bulkSelectEnabled, + favoriteStatus, + hasPerm, + loading, + ], + ); + const subMenuButtons: SubMenuProps['buttons'] = []; if (canDelete || canExport) { subMenuButtons.push({ diff --git a/superset-frontend/src/views/CRUD/utils.tsx b/superset-frontend/src/views/CRUD/utils.tsx index 31f3d4c9edeb1..a0004a844b7d3 100644 --- a/superset-frontend/src/views/CRUD/utils.tsx +++ b/superset-frontend/src/views/CRUD/utils.tsx @@ -246,7 +246,7 @@ export function handleChartDelete( addDangerToast: (arg0: string) => void, refreshData: (arg0?: FetchDataConfig | null) => void, chartFilter?: string, - userId?: number, + userId?: string | number, ) { const filters = { pageIndex: 0,