mirror of https://github.com/apache/superset.git
fix: Tags Page Polish (#25403)
Co-authored-by: Lily Kuang <lily@preset.io>
This commit is contained in:
parent
0cebffd59a
commit
85251f8cae
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -86,7 +86,7 @@ interface DashboardListProps {
|
|||
};
|
||||
}
|
||||
|
||||
interface Dashboard {
|
||||
export interface Dashboard {
|
||||
changed_by_name: string;
|
||||
changed_on_delta_humanized: string;
|
||||
changed_by: string;
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue