From 4532079c71d791060a99a773d744c2656b13acea Mon Sep 17 00:00:00 2001 From: "Hugh A. Miles II" Date: Thu, 5 Oct 2023 13:46:10 -0400 Subject: [PATCH] fix(tags): Update loading + pagination for Tags Page (#25473) --- .../features/allEntities/AllEntitiesTable.tsx | 46 +++------------ .../src/pages/AllEntities/index.tsx | 59 ++++++++++++++++++- 2 files changed, 63 insertions(+), 42 deletions(-) diff --git a/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx b/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx index 75491c5baa2b1..ac544208247ac 100644 --- a/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx +++ b/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx @@ -16,20 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import moment from 'moment'; -import { t, styled, logging } from '@superset-ui/core'; +import { t, styled } from '@superset-ui/core'; import TableView, { EmptyWrapperType } from 'src/components/TableView'; -import { addDangerToast } from 'src/components/MessageToasts/actions'; -import Loading from 'src/components/Loading'; import { TagsList } from 'src/components/Tags'; import FacePile from 'src/components/FacePile'; import Tag from 'src/types/TagType'; import Owner from 'src/types/Owner'; import { EmptyStateBig } from 'src/components/EmptyState'; -import { fetchObjects } from '../tags/tags'; const MAX_TAGS_TO_SHOW = 3; +const PAGE_SIZE = 5; const AllEntitiesTableContainer = styled.div` text-align: left; @@ -63,7 +61,7 @@ interface TaggedObject { tags: Tag[]; } -interface TaggedObjects { +export interface TaggedObjects { dashboard: TaggedObject[]; chart: TaggedObject[]; query: TaggedObject[]; @@ -72,50 +70,21 @@ interface TaggedObjects { interface AllEntitiesTableProps { search?: string; setShowTagModal: (show: boolean) => void; + objects: TaggedObjects; } export default function AllEntitiesTable({ search = '', setShowTagModal, + objects, }: AllEntitiesTableProps) { type objectType = 'dashboard' | 'chart' | 'query'; - const [objects, setObjects] = useState({ - dashboard: [], - chart: [], - query: [], - }); - const [isLoading, setLoading] = useState(true); const showListViewObjs = objects.dashboard.length > 0 || objects.chart.length > 0 || objects.query.length > 0; - useEffect(() => { - if (search === '') { - return; - } - - setLoading(true); - - fetchObjects( - { tags: search, types: null }, - (data: TaggedObject[]) => { - const objects = { dashboard: [], chart: [], query: [] }; - data.forEach(function (object) { - const object_type = object.type; - objects[object_type].push(object); - }); - setObjects(objects); - setLoading(false); - }, - (error: Response) => { - addDangerToast('Error Fetching Tagged Objects'); - logging.log(error.text); - }, - ); - }, [search]); - const renderTable = (type: objectType) => { const data = objects[type].map((o: TaggedObject) => ({ [type]: {o.name}, @@ -129,7 +98,7 @@ export default function AllEntitiesTable({ className="table-condensed" emptyWrapperType={EmptyWrapperType.Small} data={data} - pageSize={50} + pageSize={PAGE_SIZE} columns={[ { accessor: type, @@ -176,7 +145,6 @@ export default function AllEntitiesTable({ ); }; - if (isLoading) return ; return ( {showListViewObjs ? ( diff --git a/superset-frontend/src/pages/AllEntities/index.tsx b/superset-frontend/src/pages/AllEntities/index.tsx index 8d51291057876..e131e7e6fb865 100644 --- a/superset-frontend/src/pages/AllEntities/index.tsx +++ b/superset-frontend/src/pages/AllEntities/index.tsx @@ -19,7 +19,9 @@ import React, { useEffect, useState } from 'react'; import { styled, t, css, SupersetTheme } from '@superset-ui/core'; import { NumberParam, useQueryParam } from 'use-query-params'; -import AllEntitiesTable from 'src/features/allEntities/AllEntitiesTable'; +import AllEntitiesTable, { + TaggedObjects, +} from 'src/features/allEntities/AllEntitiesTable'; import Button from 'src/components/Button'; import MetadataBar, { MetadataType, @@ -28,10 +30,23 @@ import MetadataBar, { LastModified, } from 'src/components/MetadataBar'; import { PageHeaderWithActions } from 'src/components/PageHeaderWithActions'; -import { fetchSingleTag } from 'src/features/tags/tags'; import { Tag } from 'src/views/CRUD/types'; import TagModal from 'src/features/tags/TagModal'; import withToasts, { useToasts } from 'src/components/MessageToasts/withToasts'; +import { fetchObjects, fetchSingleTag } from 'src/features/tags/tags'; +import Loading from 'src/components/Loading'; + +interface TaggedObject { + id: number; + type: string; + name: string; + url: string; + changed_on: moment.MomentInput; + created_by: number | undefined; + creator: string; + owners: Owner[]; + tags: Tag[]; +} const additionalItemsStyles = (theme: SupersetTheme) => css` display: flex; @@ -59,6 +74,9 @@ const AllEntitiesContainer = styled.div` .entities { margin: ${theme.gridUnit * 6}px; 0px; } + .pagination-container { + background-color: transparent; + } `} `; @@ -88,6 +106,12 @@ function AllEntities() { const [tag, setTag] = useState(null); const [showTagModal, setShowTagModal] = useState(false); const { addSuccessToast, addDangerToast } = useToasts(); + const [isLoading, setLoading] = useState(false); + const [objects, setObjects] = useState({ + dashboard: [], + chart: [], + query: [], + }); const editableTitleProps = { title: tag?.name || '', @@ -120,21 +144,49 @@ function AllEntities() { }; items.push(lastModified); + const fetchTaggedObjects = () => { + setLoading(true); + fetchObjects( + { tags: tag?.name || '', types: null }, + (data: TaggedObject[]) => { + const objects = { dashboard: [], chart: [], query: [] }; + data.forEach(function (object) { + const object_type = object.type; + objects[object_type].push(object); + }); + setObjects(objects); + setLoading(false); + }, + (error: Response) => { + addDangerToast('Error Fetching Tagged Objects'); + setLoading(false); + }, + ); + }; + useEffect(() => { // fetch single tag met if (tagId) { + setLoading(true); fetchSingleTag( tagId, (tag: Tag) => { setTag(tag); + setLoading(false); }, (error: Response) => { addDangerToast(t('Error Fetching Tagged Objects')); + setLoading(false); }, ); } }, [tagId]); + useEffect(() => { + if (tag) fetchTaggedObjects(); + }, [tag]); + + if (isLoading) return ; return ( {}} // todo(hugh): implement refreshData on table reload + refreshData={fetchTaggedObjects} />