Skip to content

Commit

Permalink
feat(listview): skeleton loading states for table and card collections (
Browse files Browse the repository at this point in the history
  • Loading branch information
nytai authored and villebro committed Sep 11, 2020
1 parent 3e8249b commit cfd8691
Show file tree
Hide file tree
Showing 18 changed files with 456 additions and 95 deletions.
21 changes: 21 additions & 0 deletions superset-frontend/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,27 @@ module.exports = {
],
},
},
{
files: [
'src/**/*.test.ts',
'src/**/*.test.tsx',
'src/**/*.test.js',
'src/**/*.test.jsx',
],
plugins: ['jest', 'no-only-tests'],
env: {
'jest/globals': true,
},
extends: ['plugin:jest/recommended'],
rules: {
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true },
],
'jest/consistent-test-it': 'error',
'no-only-tests/no-only-tests': 'error',
},
},
],
rules: {
camelcase: [
Expand Down
50 changes: 34 additions & 16 deletions superset-frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion superset-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.16.0",
"exports-loader": "^0.7.0",
"fetch-mock": "^7.0.0-alpha.6",
"fetch-mock": "^7.7.3",
"file-loader": "^6.0.0",
"fork-ts-checker-webpack-plugin": "^0.4.9",
"ignore-styles": "^5.0.1",
Expand All @@ -267,6 +267,7 @@
"less": "^3.9.0",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.4.0",
"node-fetch": "^2.6.0",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"po2json": "^0.4.5",
"prettier": "^2.0.5",
Expand Down
7 changes: 2 additions & 5 deletions superset-frontend/spec/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
{
"plugins": [
"jest",
"no-only-tests"
],
"plugins": ["jest", "no-only-tests"],
"env": {
"jest/globals": true
},
"extends": ["plugin:jest/recommended"],
"rules": {
"import/no-extraneous-dependencies": ["error", {"devDependencies": true}],
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
"jest/consistent-test-it": "error",
"no-only-tests/no-only-tests": "error"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const mockCharts = [...new Array(3)].map((_, i) => ({
url: 'url',
viz_type: 'bar',
datasource_name: `ds${i}`,
thumbnail_url: '/thumbnail',
}));

fetchMock.get(chartsInfoEndpoint, {
Expand All @@ -70,6 +71,9 @@ fetchMock.get(chartsDtasourcesEndpoint, {
count: 0,
});

global.URL.createObjectURL = jest.fn();
fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false });

describe('ChartList', () => {
const mockedProps = {};
const wrapper = mount(<ChartList {...mockedProps} />, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const mockDashboards = [...new Array(3)].map((_, i) => ({
changed_on_utc: new Date().toISOString(),
changed_on_delta_humanized: '5 minutes ago',
owners: [{ first_name: 'admin', last_name: 'admin_user' }],
thumbnail_url: '/thumbnail',
}));

fetchMock.get(dashboardsInfoEndpoint, {
Expand All @@ -61,6 +62,9 @@ fetchMock.get(dashboardsEndpoint, {
dashboard_count: 3,
});

global.URL.createObjectURL = jest.fn();
fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false });

describe('DashboardList', () => {
const mockedProps = {};
const wrapper = mount(<DashboardList {...mockedProps} />, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
import styled from '@superset-ui/style';
import { Skeleton } from 'antd';

/*
Antd is exported from here so we can override components with Emotion as needed.
For documentation, see https://ant.design/components/overview/
*/
/* eslint no-restricted-imports: 0 */

export * from 'antd';

export const ThinSkeleton = styled(Skeleton)`
h3 {
margin: ${({ theme }) => theme.gridUnit}px 0;
}
ul {
margin-bottom: 0;
}
`;
2 changes: 0 additions & 2 deletions superset-frontend/src/components/Label/Label.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
* under the License.
*/

/* global jest */
import React from 'react';
/* eslint-disable-next-line import/no-extraneous-dependencies */
import { ReactWrapper } from 'enzyme';
import { styledMount as mount } from 'spec/helpers/theming';
import Label from '.';
Expand Down
53 changes: 34 additions & 19 deletions superset-frontend/src/components/ListView/CardCollection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
* under the License.
*/
import React from 'react';
import { TableInstance } from 'react-table';
import { TableInstance, Row } from 'react-table';
import styled from '@superset-ui/style';
import cx from 'classnames';

interface CardCollectionProps {
bulkSelectEnabled?: boolean;
Expand All @@ -42,6 +43,9 @@ const CardWrapper = styled.div`
&.card-selected {
border: 2px solid ${({ theme }) => theme.colors.primary.base};
}
&.bulk-select {
cursor: pointer;
}
`;

export default function CardCollection({
Expand All @@ -51,32 +55,43 @@ export default function CardCollection({
renderCard,
rows,
}: CardCollectionProps) {
function handleClick(event: React.FormEvent, onClick: any) {
function handleClick(
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
toggleRowSelected: Row['toggleRowSelected'],
) {
if (bulkSelectEnabled) {
event.preventDefault();
event.stopPropagation();
onClick();
toggleRowSelected();
}
}

if (!renderCard) return null;
return (
<CardContainer>
{rows.map(row => {
if (!renderCard) return null;
prepareRow(row);
return (
<CardWrapper
className={
row.isSelected && bulkSelectEnabled ? 'card-selected' : ''
}
key={row.id}
onClick={e => handleClick(e, row.toggleRowSelected())}
role="none"
>
{renderCard({ ...row.original, loading })}
</CardWrapper>
);
})}
{loading &&
rows.length === 0 &&
[...new Array(25)].map((e, i) => {
return <div key={i}>{renderCard({ loading })}</div>;
})}
{rows.length > 0 &&
rows.map(row => {
if (!renderCard) return null;
prepareRow(row);
return (
<CardWrapper
className={cx({
'card-selected': bulkSelectEnabled && row.isSelected,
'bulk-select': bulkSelectEnabled,
})}
key={row.id}
onClick={e => handleClick(e, row.toggleRowSelected)}
role="none"
>
{renderCard({ ...row.original, loading })}
</CardWrapper>
);
})}
</CardContainer>
);
}
15 changes: 9 additions & 6 deletions superset-frontend/src/components/ListView/ListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,13 @@ const ListView: FunctionComponent<ListViewProps> = ({
prepareRow={prepareRow}
headerGroups={headerGroups}
rows={rows}
columns={columns}
loading={loading}
/>
)}
</div>
</div>

<div className="pagination-container">
<Pagination
totalPages={pageCount || 0}
Expand All @@ -352,12 +354,13 @@ const ListView: FunctionComponent<ListViewProps> = ({
hideFirstAndLastPageLinks
/>
<div className="row-count-container">
{t(
'%s-%s of %s',
pageSize * pageIndex + (rows.length && 1),
pageSize * pageIndex + rows.length,
count,
)}
{!loading &&
t(
'%s-%s of %s',
pageSize * pageIndex + (rows.length && 1),
pageSize * pageIndex + rows.length,
count,
)}
</div>
</div>
</ListViewStyles>
Expand Down
Loading

0 comments on commit cfd8691

Please sign in to comment.