fix: Tags Page Polish (#25403)

Co-authored-by: Lily Kuang <lily@preset.io>
This commit is contained in:
Hugh A. Miles II 2023-09-29 22:13:26 -04:00 committed by GitHub
parent 0cebffd59a
commit 85251f8cae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 116 additions and 37 deletions

View File

@ -22,18 +22,33 @@ import { t, styled, logging } 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 AllEntitiesTableContainer = styled.div`
text-align: left;
border-radius: ${({ theme }) => theme.gridUnit * 1}px 0;
margin: 0 ${({ theme }) => theme.gridUnit * 4}px;
.table {
table-layout: fixed;
}
.td {
width: 33%;
}
.entity-title {
font-family: Inter;
font-size: ${({ theme }) => theme.typography.sizes.m}px;
font-weight: ${({ theme }) => theme.typography.weights.medium};
line-height: 17px;
letter-spacing: 0px;
text-align: left;
margin: ${({ theme }) => theme.gridUnit * 4}px 0;
}
`;
interface TaggedObject {
@ -44,6 +59,8 @@ interface TaggedObject {
changed_on: moment.MomentInput;
created_by: number | undefined;
creator: string;
owners: Owner[];
tags: Tag[];
}
interface TaggedObjects {
@ -54,10 +71,12 @@ interface TaggedObjects {
interface AllEntitiesTableProps {
search?: string;
setShowTagModal: (show: boolean) => void;
}
export default function AllEntitiesTable({
search = '',
setShowTagModal,
}: AllEntitiesTableProps) {
type objectType = 'dashboard' | 'chart' | 'query';
@ -66,8 +85,19 @@ export default function AllEntitiesTable({
chart: [],
query: [],
});
const [isLoading, setLoading] = useState<boolean>(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[]) => {
@ -77,6 +107,7 @@ export default function AllEntitiesTable({
objects[object_type].push(object);
});
setObjects(objects);
setLoading(false);
},
(error: Response) => {
addDangerToast('Error Fetching Tagged Objects');
@ -89,7 +120,10 @@ export default function AllEntitiesTable({
const data = objects[type].map((o: TaggedObject) => ({
[type]: <a href={o.url}>{o.name}</a>,
modified: moment.utc(o.changed_on).fromNow(),
tags: o.tags,
owners: o.owners,
}));
return (
<TableView
className="table-condensed"
@ -99,27 +133,69 @@ export default function AllEntitiesTable({
columns={[
{
accessor: type,
Header: type.charAt(0).toUpperCase() + type.slice(1),
Header: 'Title',
},
{
Cell: ({
row: {
original: { tags = [] },
},
}: {
row: {
original: {
tags: Tag[];
};
};
}) => (
// Only show custom type tags
<TagsList
tags={tags.filter(
(tag: Tag) =>
tag.type === 'TagTypes.custom' || tag.type === 1,
)}
maxTags={MAX_TAGS_TO_SHOW}
/>
),
Header: t('Tags'),
accessor: 'tags',
disableSortBy: true,
},
{
Cell: ({
row: {
original: { owners = [] },
},
}: any) => <FacePile users={owners} />,
Header: t('Owners'),
accessor: 'owners',
disableSortBy: true,
size: 'xl',
},
{ accessor: 'modified', Header: 'Modified' },
]}
/>
);
};
if (objects) {
return (
<AllEntitiesTableContainer>
<h3>{t('Dashboards')}</h3>
{renderTable('dashboard')}
<hr />
<h3>{t('Charts')}</h3>
{renderTable('chart')}
<hr />
<h3>{t('Queries')}</h3>
{renderTable('query')}
</AllEntitiesTableContainer>
);
}
return <Loading />;
if (isLoading) return <Loading />;
return (
<AllEntitiesTableContainer>
{showListViewObjs ? (
<>
<div className="entity-title">{t('Dashboards')}</div>
{renderTable('dashboard')}
<div className="entity-title">{t('Charts')}</div>
{renderTable('chart')}
<div className="entity-title">{t('Queries')}</div>
{renderTable('query')}
</>
) : (
<EmptyStateBig
image="dashboard.svg"
title={t('No entities have this tag currently assigned')}
buttonAction={() => setShowTagModal(true)}
buttonText={t('Add tag to entities')}
/>
)}
</AllEntitiesTableContainer>
);
}

View File

@ -57,7 +57,7 @@ const AllEntitiesContainer = styled.div`
margin-bottom: ${theme.gridUnit * 1}px;
}
.entities {
margin: ${theme.gridUnit * 7.5}px; 0px;
margin: ${theme.gridUnit * 6}px; 0px;
}
`}
`;
@ -88,6 +88,7 @@ function AllEntities() {
const [tag, setTag] = useState<Tag | null>(null);
const [showTagModal, setShowTagModal] = useState<boolean>(false);
const { addSuccessToast, addDangerToast } = useToasts();
const editableTitleProps = {
title: tag?.name || '',
placeholder: 'testing',
@ -166,10 +167,14 @@ function AllEntities() {
menuDropdownProps={{
disabled: true,
}}
showMenuDropdown={false}
/>
</AllEntitiesNav>
<div className="entities">
<AllEntitiesTable search={tag?.name || ''} />
<AllEntitiesTable
search={tag?.name || ''}
setShowTagModal={setShowTagModal}
/>
</div>
</AllEntitiesContainer>
);

View File

@ -86,7 +86,7 @@ interface DashboardListProps {
};
}
interface Dashboard {
export interface Dashboard {
changed_by_name: string;
changed_on_delta_humanized: string;
changed_by: string;

View File

@ -175,16 +175,6 @@ class TagDAO(BaseDAO[Tag]):
returns a list of tagged objects filtered by tag names and object types
if no filters applied returns all tagged objects
"""
# id = fields.Int()
# type = fields.String()
# name = fields.String()
# url = fields.String()
# changed_on = fields.DateTime()
# created_by = fields.Nested(UserSchema)
# creator = fields.String(
# filter types
results: list[dict[str, Any]] = []
# dashboards
@ -211,6 +201,8 @@ class TagDAO(BaseDAO[Tag]):
"changed_on": obj.changed_on,
"created_by": obj.created_by_fk,
"creator": obj.creator(),
"tags": obj.tags,
"owners": obj.owners,
}
for obj in dashboards
)
@ -238,6 +230,8 @@ class TagDAO(BaseDAO[Tag]):
"changed_on": obj.changed_on,
"created_by": obj.created_by_fk,
"creator": obj.creator(),
"tags": obj.tags,
"owners": obj.owners,
}
for obj in charts
)
@ -265,6 +259,8 @@ class TagDAO(BaseDAO[Tag]):
"changed_on": obj.changed_on,
"created_by": obj.created_by_fk,
"creator": obj.creator(),
"tags": obj.tags,
"owners": [obj.creator()],
}
for obj in saved_queries
)

View File

@ -38,6 +38,12 @@ openapi_spec_methods_override = {
}
class TagGetResponseSchema(Schema):
id = fields.Int()
name = fields.String()
type = fields.String()
class TaggedObjectEntityResponseSchema(Schema):
id = fields.Int()
type = fields.String()
@ -46,12 +52,8 @@ class TaggedObjectEntityResponseSchema(Schema):
changed_on = fields.DateTime()
created_by = fields.Nested(UserSchema(exclude=["username"]))
creator = fields.String()
class TagGetResponseSchema(Schema):
id = fields.Int()
name = fields.String()
type = fields.String()
tags = fields.List(fields.Nested(TagGetResponseSchema))
owners = fields.List(fields.Nested(UserSchema))
class TagObjectSchema(Schema):