blob: f29f4e0bffcdb53eadde3eb336efb5583b62e556 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { 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 { Button, Loading } from '@superset-ui/core/components';
import MetadataBar, {
MetadataType,
Description,
Owner,
LastModified,
} from '@superset-ui/core/components/MetadataBar';
import { PageHeaderWithActions } from '@superset-ui/core/components/PageHeaderWithActions';
import { Tag } from 'src/views/CRUD/types';
import TagModal from 'src/features/tags/TagModal';
import withToasts, { useToasts } from 'src/components/MessageToasts/withToasts';
import { fetchObjectsByTagIds, fetchSingleTag } from 'src/features/tags/tags';
import getOwnerName from 'src/utils/getOwnerName';
import { TaggedObject, TaggedObjects } from 'src/types/TaggedObject';
import { findPermission } from 'src/utils/findPermission';
import { useSelector } from 'react-redux';
import { RootState } from 'src/dashboard/types';
const additionalItemsStyles = (theme: SupersetTheme) => css`
display: flex;
align-items: center;
margin-left: ${theme.sizeUnit}px;
& > span {
margin-right: ${theme.sizeUnit * 3}px;
}
`;
const AllEntitiesContainer = styled.div`
${({ theme }) => `
background-color: ${theme.colorBgContainer};
.select-control {
margin-left: ${theme.sizeUnit * 4}px;
margin-right: ${theme.sizeUnit * 4}px;
margin-bottom: ${theme.sizeUnit * 2}px;
}
.select-control-label {
font-size: ${theme.sizeUnit * 3}px;
color: ${theme.colorText};
margin-bottom: ${theme.sizeUnit * 1}px;
}
.entities {
margin: ${theme.sizeUnit * 6}px; 0px;
}
.pagination-container {
background-color: transparent;
}
`}
`;
const AllEntitiesNav = styled.div`
${({ theme }) => `
height: ${theme.sizeUnit * 12.5}px;
background-color: ${theme.colorBgBase};
margin-bottom: ${theme.sizeUnit * 4}px;
.navbar-brand {
margin-left: ${theme.sizeUnit * 2}px;
font-weight: ${theme.fontWeightStrong};
}
.header {
font-weight: ${theme.fontWeightStrong};
margin-right: ${theme.sizeUnit * 3}px;
text-align: left;
font-size: ${theme.sizeUnit * 4.5}px;
padding: ${theme.sizeUnit * 3}px;
display: inline-block;
line-height: ${theme.sizeUnit * 9}px;
}
`};
`;
function AllEntities() {
const [tagId] = useQueryParam('id', NumberParam);
const [tag, setTag] = useState<Tag | null>(null);
const [showTagModal, setShowTagModal] = useState<boolean>(false);
const { addSuccessToast, addDangerToast } = useToasts();
const [isLoading, setLoading] = useState<boolean>(false);
const [objects, setObjects] = useState<TaggedObjects>({
dashboard: [],
chart: [],
query: [],
});
const canEditTag = useSelector((state: RootState) =>
findPermission('can_write', 'Tag', state.user?.roles),
);
const editableTitleProps = {
title: tag?.name || '',
placeholder: 'testing',
onSave: () => {},
canEdit: false,
label: t('dataset name'),
};
const items = [];
if (tag?.description) {
const description: Description = {
type: MetadataType.Description,
value: tag?.description || '',
};
items.push(description);
}
const owner: Owner = {
type: MetadataType.Owner,
createdBy: getOwnerName(tag?.created_by),
createdOn: tag?.created_on_delta_humanized || '',
};
items.push(owner);
const lastModified: LastModified = {
type: MetadataType.LastModified,
value: tag?.changed_on_delta_humanized || '',
modifiedBy: getOwnerName(tag?.changed_by),
};
items.push(lastModified);
const fetchTaggedObjects = () => {
setLoading(true);
if (!tag) {
addDangerToast('Error tag object is not referenced!');
return;
}
fetchObjectsByTagIds(
{ tagIds: tag?.id !== undefined ? [tag.id] : '', types: null },
(data: TaggedObject[]) => {
const objects: TaggedObjects = { dashboard: [], chart: [], query: [] };
data.forEach(function (object) {
const object_type = object.type;
objects[object_type as keyof TaggedObjects].push(object);
});
setObjects(objects);
setLoading(false);
},
(error: Response) => {
addDangerToast('Error Fetching Tagged Objects');
setLoading(false);
},
);
};
const fetchTag = (tagId: number) => {
fetchSingleTag(
tagId,
(tag: Tag) => {
setTag(tag);
setLoading(false);
},
(error: Response) => {
addDangerToast(t('Error Fetching Tagged Objects'));
setLoading(false);
},
);
};
useEffect(() => {
// fetch single tag met
if (tagId) {
setLoading(true);
fetchTag(tagId);
}
}, [tagId]);
useEffect(() => {
if (tag) fetchTaggedObjects();
}, [tag]);
if (isLoading) return <Loading />;
return (
<AllEntitiesContainer>
<TagModal
show={showTagModal}
onHide={() => {
setShowTagModal(false);
}}
editTag={tag}
addSuccessToast={addSuccessToast}
addDangerToast={addDangerToast}
refreshData={() => {
fetchTaggedObjects();
if (tagId) fetchTag(tagId);
}}
/>
<AllEntitiesNav>
<PageHeaderWithActions
additionalActionsMenu={<></>}
editableTitleProps={editableTitleProps}
faveStarProps={{ itemId: 1, saveFaveStar: () => {} }}
showFaveStar={false}
showTitlePanelItems
titlePanelAdditionalItems={
<div css={additionalItemsStyles}>
<MetadataBar items={items} tooltipPlacement="bottom" />
</div>
}
rightPanelAdditionalItems={
<>
{canEditTag && (
<Button
data-test="bulk-select-action"
buttonStyle="secondary"
onClick={() => setShowTagModal(true)}
showMarginRight={false}
>
{t('Edit tag')}{' '}
</Button>
)}
</>
}
menuDropdownProps={{
disabled: true,
}}
showMenuDropdown={false}
/>
</AllEntitiesNav>
<div className="entities">
<AllEntitiesTable
search={tag?.name || ''}
setShowTagModal={setShowTagModal}
objects={objects}
canEditTag={canEditTag}
/>
</div>
</AllEntitiesContainer>
);
}
export default withToasts(AllEntities);