fix(UI) : Improvements (#10362)

* UI Improvements

* code optimize
This commit is contained in:
Ashish Gupta 2023-02-28 20:57:54 +05:30 committed by GitHub
parent f4fc1b6438
commit 40b68ca841
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 97 deletions

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none"><path stroke="#37352F" stroke-width=".9" d="M2 3.426v9.04c.026 1.678 2.755 3.034 6.116 3.034 3.362 0 6.09-1.356 6.116-3.034v-9.04c0 1.772-2.58 3.17-5.942 3.17C4.93 6.597 2 5.34 2 3.427Z"/><path stroke="#37352F" stroke-width=".9" d="M8.116 6.616c3.378 0 6.117-1.369 6.117-3.058C14.233 1.87 11.494.5 8.116.5S2 1.87 2 3.558c0 1.69 2.738 3.058 6.116 3.058Zm.025-1.492c1.689 0 3.058-.685 3.058-1.53 0-.844-1.37-1.528-3.058-1.528-1.69 0-3.058.684-3.058 1.529 0 .844 1.369 1.529 3.058 1.529Z" clip-rule="evenodd"/><path stroke="#37352F" stroke-width=".9" d="M6.16 11.252v2.093a.2.2 0 0 1-.3.173l-1.655-.945a.2.2 0 0 1-.101-.174V7.684a.2.2 0 0 1 .304-.171l3.581 2.175a.2.2 0 0 0 .206.001l3.68-2.182a.2.2 0 0 1 .303.172v4.813a.2.2 0 0 1-.108.177l-1.655.867a.2.2 0 0 1-.292-.177v-2.116a.2.2 0 0 0-.3-.174l-1.63.924a.2.2 0 0 1-.2-.002l-1.532-.91a.2.2 0 0 0-.302.171Z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none"><path stroke="currentColor" stroke-width=".9" d="M2 3.426v9.04c.026 1.678 2.755 3.034 6.116 3.034 3.362 0 6.09-1.356 6.116-3.034v-9.04c0 1.772-2.58 3.17-5.942 3.17C4.93 6.597 2 5.34 2 3.427Z"/><path stroke="currentColor" stroke-width=".9" d="M8.116 6.616c3.378 0 6.117-1.369 6.117-3.058C14.233 1.87 11.494.5 8.116.5S2 1.87 2 3.558c0 1.69 2.738 3.058 6.116 3.058Zm.025-1.492c1.689 0 3.058-.685 3.058-1.53 0-.844-1.37-1.528-3.058-1.528-1.69 0-3.058.684-3.058 1.529 0 .844 1.369 1.529 3.058 1.529Z" clip-rule="evenodd"/><path stroke="currentColor" stroke-width=".9" d="M6.16 11.252v2.093a.2.2 0 0 1-.3.173l-1.655-.945a.2.2 0 0 1-.101-.174V7.684a.2.2 0 0 1 .304-.171l3.581 2.175a.2.2 0 0 0 .206.001l3.68-2.182a.2.2 0 0 1 .303.172v4.813a.2.2 0 0 1-.108.177l-1.655.867a.2.2 0 0 1-.292-.177v-2.116a.2.2 0 0 0-.3-.174l-1.63.924a.2.2 0 0 1-.2-.002l-1.532-.91a.2.2 0 0 0-.302.171Z"/></svg>

Before

Width:  |  Height:  |  Size: 939 B

After

Width:  |  Height:  |  Size: 954 B

View File

@ -11,7 +11,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { Popover, Space, Table, Typography } from 'antd'; import { Button, Popover, Space, Table, Typography } from 'antd';
import { ColumnsType } from 'antd/lib/table'; import { ColumnsType } from 'antd/lib/table';
import classNames from 'classnames'; import classNames from 'classnames';
import { cloneDeep, isEmpty, isUndefined, lowerCase, toLower } from 'lodash'; import { cloneDeep, isEmpty, isUndefined, lowerCase, toLower } from 'lodash';
@ -25,6 +25,8 @@ import React, {
} from 'react'; } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { ReactComponent as IconEdit } from '../../assets/svg/ic-edit.svg';
import { ReactComponent as IconRequest } from '../../assets/svg/request-icon.svg';
import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants'; import { FQN_SEPARATOR_CHAR } from '../../constants/char.constants';
import { EntityField } from '../../constants/Feeds.constants'; import { EntityField } from '../../constants/Feeds.constants';
import { SettledStatus } from '../../enums/axios.enum'; import { SettledStatus } from '../../enums/axios.enum';
@ -43,7 +45,6 @@ import {
fetchGlossaryTerms, fetchGlossaryTerms,
getGlossaryTermlist, getGlossaryTermlist,
} from '../../utils/GlossaryUtils'; } from '../../utils/GlossaryUtils';
import SVGIcons, { Icons } from '../../utils/SvgUtils';
import { import {
getDataTypeString, getDataTypeString,
getTableExpandableConfig, getTableExpandableConfig,
@ -346,9 +347,10 @@ const EntityTable = ({
const hasDescription = Boolean(cell?.description ?? ''); const hasDescription = Boolean(cell?.description ?? '');
return ( return (
<button <Button
className="tw-w-7 tw-h-7 tw-flex-none link-text focus:tw-outline-none hover-cell-icon" className="p-0 w-7 h-7 tw-flex-none flex-center link-text focus:tw-outline-none hover-cell-icon m-r-xss"
data-testid="request-description" data-testid="request-description"
type="text"
onClick={() => onClick={() =>
hasDescription hasDescription
? onUpdateDescriptionHandler(cell) ? onUpdateDescriptionHandler(cell)
@ -364,13 +366,13 @@ const EntityTable = ({
overlayClassName="ant-popover-request-description" overlayClassName="ant-popover-request-description"
trigger="hover" trigger="hover"
zIndex={9999}> zIndex={9999}>
<SVGIcons <IconRequest
alt={t('message.request-description')} height={16}
icon={Icons.REQUEST} name={t('message.request-description')}
width="16px" width={16}
/> />
</Popover> </Popover>
</button> </Button>
); );
}; };
@ -381,9 +383,10 @@ const EntityTable = ({
: t('label.request-tag-plural'); : t('label.request-tag-plural');
return ( return (
<button <Button
className="tw-w-7 tw-h-7 tw-flex-none link-text focus:tw-outline-none tw-align-top hover-cell-icon" className="p-0 w-7 h-7 tw-flex-none link-text focus:tw-outline-none tw-align-top hover-cell-icon"
data-testid="request-tags" data-testid="request-tags"
type="text"
onClick={() => onClick={() =>
hasTags ? onUpdateTagsHandler(cell) : onRequestTagsHandler(cell) hasTags ? onUpdateTagsHandler(cell) : onRequestTagsHandler(cell)
}> }>
@ -393,13 +396,13 @@ const EntityTable = ({
overlayClassName="ant-popover-request-description" overlayClassName="ant-popover-request-description"
trigger="hover" trigger="hover"
zIndex={9999}> zIndex={9999}>
<SVGIcons <IconRequest
alt={t('label.request-tag-plural')} height={16}
icon={Icons.REQUEST} name={t('label.request-tag-plural')}
width="16px" width={16}
/> />
</Popover> </Popover>
</button> </Button>
); );
}; };
@ -441,10 +444,11 @@ const EntityTable = ({
return ( return (
<div className="hover-icon-group"> <div className="hover-icon-group">
<div className="d-inline-block"> <div className="d-inline-block">
<div <Space
className="d-flex" align="end"
data-testid="description" data-testid="description"
id={`column-description-${index}`}> id={`column-description-${index}`}
size={4}>
<div> <div>
{description ? ( {description ? (
<RichTextEditorPreviewer markdown={description} /> <RichTextEditorPreviewer markdown={description} />
@ -461,16 +465,16 @@ const EntityTable = ({
<Fragment> <Fragment>
{hasDescriptionEditAccess && ( {hasDescriptionEditAccess && (
<> <>
<button <Button
className="tw-self-start tw-w-7 tw-h-7 focus:tw-outline-none tw-flex-none hover-cell-icon" className="p-0 tw-self-start flex-center w-7 h-7 focus:tw-outline-none tw-flex-none hover-cell-icon"
type="text"
onClick={() => handleUpdate(record, index)}> onClick={() => handleUpdate(record, index)}>
<SVGIcons <IconEdit
alt={t('label.edit')} height={16}
icon="icon-edit" name={t('label.edit')}
title={t('label.edit')} width={16}
width="16px"
/> />
</button> </Button>
</> </>
)} )}
{getRequestDescriptionElement(record)} {getRequestDescriptionElement(record)}
@ -502,7 +506,7 @@ const EntityTable = ({
</Fragment> </Fragment>
) : null} ) : null}
</div> </div>
</div> </Space>
</div> </div>
{getFrequentlyJoinedColumns( {getFrequentlyJoinedColumns(
record?.name, record?.name,

View File

@ -12,7 +12,7 @@
*/ */
import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
import { Select, Space } from 'antd'; import { Button, Select, Space } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import Tags from 'components/Tag/Tags/tags'; import Tags from 'components/Tag/Tags/tags';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
@ -28,7 +28,6 @@ import React, {
import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants'; import { FQN_SEPARATOR_CHAR } from '../../../constants/char.constants';
import { TagSource } from '../../../generated/type/tagLabel'; import { TagSource } from '../../../generated/type/tagLabel';
import { withLoader } from '../../../hoc/withLoader'; import { withLoader } from '../../../hoc/withLoader';
import { Button } from '../../buttons/Button/Button';
import { TagsContainerProps } from './tags-container.interface'; import { TagsContainerProps } from './tags-container.interface';
const TagsContainer: FunctionComponent<TagsContainerProps> = ({ const TagsContainer: FunctionComponent<TagsContainerProps> = ({
@ -166,22 +165,20 @@ const TagsContainer: FunctionComponent<TagsContainerProps> = ({
<Space <Space
className={classNames('', buttonContainerClass)} className={classNames('', buttonContainerClass)}
data-testid="buttons" data-testid="buttons"
size={8}> size={4}>
<Button <Button
className="tw-px-1 tw-py-1 tw-rounded tw-text-sm tw-mr-1" className="h-8"
data-testid="cancelAssociatedTag" data-testid="cancelAssociatedTag"
size="custom" size="small"
theme="primary" type="primary"
variant="contained"
onMouseDown={handleCancel}> onMouseDown={handleCancel}>
<CloseOutlined /> <CloseOutlined />
</Button> </Button>
<Button <Button
className="tw-px-1 tw-py-1 tw-rounded tw-text-sm" className="h-8"
data-testid="saveAssociatedTag" data-testid="saveAssociatedTag"
size="custom" size="small"
theme="primary" type="primary"
variant="contained"
onMouseDown={handleSave}> onMouseDown={handleSave}>
<CheckOutlined /> <CheckOutlined />
</Button> </Button>

View File

@ -13,11 +13,14 @@
import { Button, Popover, Space, Typography } from 'antd'; import { Button, Popover, Space, Typography } from 'antd';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import classNames from 'classnames';
import { t } from 'i18next'; import { t } from 'i18next';
import { isFunction, isUndefined } from 'lodash'; import { isFunction, isUndefined } from 'lodash';
import React, { FC, Fragment } from 'react'; import React, { FC, Fragment } from 'react';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import { ReactComponent as IconCommentPlus } from '../../../assets/svg/add-chat.svg';
import { ReactComponent as IconComments } from '../../../assets/svg/comment.svg';
import { ReactComponent as IconEdit } from '../../../assets/svg/ic-edit.svg';
import { ReactComponent as IconRequest } from '../../../assets/svg/request-icon.svg';
import { ReactComponent as IconTaskColor } from '../../../assets/svg/Task-ic.svg'; import { ReactComponent as IconTaskColor } from '../../../assets/svg/Task-ic.svg';
import { EntityField } from '../../../constants/Feeds.constants'; import { EntityField } from '../../../constants/Feeds.constants';
import { EntityType } from '../../../enums/entity.enum'; import { EntityType } from '../../../enums/entity.enum';
@ -25,7 +28,6 @@ import { ThreadType } from '../../../generated/entity/feed/thread';
import { EntityFieldThreads } from '../../../interface/feed.interface'; import { EntityFieldThreads } from '../../../interface/feed.interface';
import { isTaskSupported } from '../../../utils/CommonUtils'; import { isTaskSupported } from '../../../utils/CommonUtils';
import { getEntityFeedLink } from '../../../utils/EntityUtils'; import { getEntityFeedLink } from '../../../utils/EntityUtils';
import SVGIcons, { Icons } from '../../../utils/SvgUtils';
import { import {
getRequestDescriptionPath, getRequestDescriptionPath,
getUpdateDescriptionPath, getUpdateDescriptionPath,
@ -90,9 +92,10 @@ const Description: FC<DescriptionProps> = ({
const hasDescription = Boolean(description.trim()); const hasDescription = Boolean(description.trim());
return TASK_ENTITIES.includes(entityType as EntityType) ? ( return TASK_ENTITIES.includes(entityType as EntityType) ? (
<button <Button
className="tw-w-7 tw-h-7 tw-flex-none link-text focus:tw-outline-none" className="w-7 h-7 p-0 flex-center"
data-testid="request-entity-description" data-testid="request-entity-description"
type="text"
onClick={ onClick={
hasDescription ? handleUpdateDescription : handleRequestDescription hasDescription ? handleUpdateDescription : handleRequestDescription
}> }>
@ -106,13 +109,13 @@ const Description: FC<DescriptionProps> = ({
overlayClassName="ant-popover-request-description" overlayClassName="ant-popover-request-description"
trigger="hover" trigger="hover"
zIndex={9999}> zIndex={9999}>
<SVGIcons <IconRequest
alt={t('message.request-description')} height={16}
icon={Icons.REQUEST} name={t('message.request-description')}
width="16px" width={16}
/> />
</Popover> </Popover>
</button> </Button>
) : null; ) : null;
}; };
@ -120,26 +123,27 @@ const Description: FC<DescriptionProps> = ({
descriptionThread, descriptionThread,
}: { }: {
descriptionThread?: EntityFieldThreads; descriptionThread?: EntityFieldThreads;
}) => { }) =>
return !isUndefined(descriptionThread) ? ( !isUndefined(descriptionThread) ? (
<button <Button
className="tw-w-7 tw-h-7 tw-flex-none link-text focus:tw-outline-none" className="w-9 h-7 p-0"
data-testid="description-thread" data-testid="description-thread"
type="text"
onClick={() => onThreadLinkSelect?.(descriptionThread.entityLink)}> onClick={() => onThreadLinkSelect?.(descriptionThread.entityLink)}>
<span className="tw-flex"> <Space align="center" className="h-full" size={2}>
<SVGIcons alt="comments" icon={Icons.COMMENT} width="16px" />{' '} <IconComments height={16} name="tasks" width={16} />
<span className="tw-ml-1" data-testid="description-thread-count"> <Typography.Text data-testid="description-thread-count">
{' '}
{descriptionThread.count} {descriptionThread.count}
</span> </Typography.Text>
</span> </Space>
</button> </Button>
) : ( ) : (
<Fragment> <Fragment>
{description?.trim() && onThreadLinkSelect ? ( {description?.trim() && onThreadLinkSelect ? (
<button <Button
className="tw-w-7 tw-h-7 tw-flex-none link-text focus:tw-outline-none" className="w-7 h-7 link-text p-0"
data-testid="start-description-thread" data-testid="start-description-thread"
type="text"
onClick={() => onClick={() =>
onThreadLinkSelect?.( onThreadLinkSelect?.(
getEntityFeedLink( getEntityFeedLink(
@ -149,21 +153,20 @@ const Description: FC<DescriptionProps> = ({
) )
) )
}> }>
<SVGIcons alt="comments" icon={Icons.COMMENT_PLUS} width="16px" /> <IconCommentPlus height={16} name="comments" width={16} />
</button> </Button>
) : null} ) : null}
</Fragment> </Fragment>
); );
};
const getDescriptionTaskElement = () => { const getDescriptionTaskElement = () =>
return !isUndefined(tasks) ? ( !isUndefined(tasks) ? (
<Button <Button
className="w-7 h-7 m-r-xs p-0" className="w-9 h-7 p-0"
data-testid="description-task" data-testid="description-task"
type="text" type="text"
onClick={() => onThreadLinkSelect?.(tasks.entityLink, ThreadType.Task)}> onClick={() => onThreadLinkSelect?.(tasks.entityLink, ThreadType.Task)}>
<Space align="center" className="w-full h-full" size={3}> <Space align="center" className="h-full" size={2}>
<IconTaskColor height={16} name="tasks" width={16} /> <IconTaskColor height={16} name="tasks" width={16} />
<Typography.Text data-testid="description-tasks-count"> <Typography.Text data-testid="description-tasks-count">
{tasks.count} {tasks.count}
@ -171,35 +174,34 @@ const Description: FC<DescriptionProps> = ({
</Space> </Space>
</Button> </Button>
) : null; ) : null;
};
const DescriptionActions = () => { const DescriptionActions = () => {
return !isReadOnly ? ( return !isReadOnly ? (
<div className={classNames('tw-w-5 tw-min-w-max tw-flex')}> <Space align="end" size={0}>
{hasEditAccess && ( {hasEditAccess && (
<button <Button
className="tw-w-7 tw-h-7 tw-flex-none focus:tw-outline-none" className="w-7 h-7 p-0 flex-center"
data-testid="edit-description" data-testid="edit-description"
type="text"
onClick={handleUpdate}> onClick={handleUpdate}>
<SVGIcons alt="edit" icon="icon-edit" title="Edit" width="16px" /> <IconEdit height={16} width={16} />
</button> </Button>
)} )}
{isTaskSupported(entityType as EntityType) ? ( {isTaskSupported(entityType as EntityType) ? (
<Fragment> <Fragment>
{' '}
<RequestDescriptionEl /> <RequestDescriptionEl />
{getDescriptionTaskElement()} {getDescriptionTaskElement()}
</Fragment> </Fragment>
) : null} ) : null}
<DescriptionThreadEl descriptionThread={thread} /> <DescriptionThreadEl descriptionThread={thread} />
</div> </Space>
) : null; ) : null;
}; };
return ( return (
<div className={`schema-description tw-relative ${className}`}> <div className={`schema-description tw-relative ${className}`}>
<div className="tw-flex description-inner-main-container tw-items-end"> <Space align="end" className="description-inner-main-container" size={4}>
<div className="tw-relative"> <div className="tw-relative">
<div <div
className="description tw-h-full tw-overflow-y-scroll tw-relative " className="description tw-h-full tw-overflow-y-scroll tw-relative "
@ -230,7 +232,7 @@ const Description: FC<DescriptionProps> = ({
/> />
</div> </div>
<DescriptionActions /> <DescriptionActions />
</div> </Space>
</div> </div>
); );
}; };

View File

@ -420,6 +420,7 @@
"lineage-ingestion": "Lineage Ingestion", "lineage-ingestion": "Lineage Ingestion",
"lineage-lowercase": "lineage", "lineage-lowercase": "lineage",
"list": "List", "list": "List",
"list-entity": "List {{entity}}",
"loading": "Loading", "loading": "Loading",
"local-config-source": "Local Config Source", "local-config-source": "Local Config Source",
"log-plural": "Logs", "log-plural": "Logs",

View File

@ -11,16 +11,26 @@
* limitations under the License. * limitations under the License.
*/ */
import { Button, Popover, Space, Typography } from 'antd';
import { t } from 'i18next'; import { t } from 'i18next';
import { isEmpty, isEqual, isUndefined } from 'lodash'; import { isEmpty, isEqual, isUndefined } from 'lodash';
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { ReactComponent as IconCommentPlus } from '../assets/svg/add-chat.svg';
import { ReactComponent as IconComments } from '../assets/svg/comment.svg';
import { ReactComponent as IconTaskColor } from '../assets/svg/Task-ic.svg';
import { entityUrlMap } from '../constants/Feeds.constants'; import { entityUrlMap } from '../constants/Feeds.constants';
import { ThreadType } from '../generated/entity/feed/thread'; import { ThreadType } from '../generated/entity/feed/thread';
import { EntityReference } from '../generated/entity/teams/user'; import { EntityReference } from '../generated/entity/teams/user';
import { EntityFieldThreads } from '../interface/feed.interface'; import { EntityFieldThreads } from '../interface/feed.interface';
import { getEntityFeedLink } from './EntityUtils'; import { getEntityFeedLink } from './EntityUtils';
import { getThreadField } from './FeedUtils'; import { getThreadField } from './FeedUtils';
import SVGIcons, { Icons } from './SvgUtils';
const iconsProps = {
height: 16,
name: 'comments',
width: 16,
};
export const getFieldThreadElement = ( export const getFieldThreadElement = (
columnName: string, columnName: string,
@ -45,9 +55,10 @@ export const getFieldThreadElement = (
const isTaskType = isEqual(threadType, ThreadType.Task); const isTaskType = isEqual(threadType, ThreadType.Task);
return !isEmpty(threadValue) ? ( return !isEmpty(threadValue) ? (
<button <Button
className="link-text tw-self-start tw-w-7 tw-h-7 tw-mr-1 tw-flex tw-items-center hover-cell-icon" className="link-text tw-self-start w-8 h-7 m-r-xss tw-flex tw-items-center hover-cell-icon p-0"
data-testid="field-thread" data-testid="field-thread"
type="text"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -56,23 +67,33 @@ export const getFieldThreadElement = (
isTaskType ? ThreadType.Task : ThreadType.Conversation isTaskType ? ThreadType.Task : ThreadType.Conversation
); );
}}> }}>
<SVGIcons <Popover
alt="comments" destroyTooltipOnHide
className="tw-mt-0.5" content={t('label.list-entity', {
height="16px" entity: isTaskType ? t('label.task') : t('label.conversation'),
icon={isTaskType ? Icons.TASK_ICON : Icons.COMMENT} })}
width="16px" overlayClassName="ant-popover-request-description"
/> trigger="hover">
<span className="tw-ml-1" data-testid="field-thread-count"> <Space align="center" className="w-full h-full" size={4}>
{threadValue.count} {isTaskType ? (
</span> <IconTaskColor {...iconsProps} />
</button> ) : (
<IconComments {...iconsProps} />
)}
<Typography.Text data-testid="field-thread-count">
{threadValue.count}
</Typography.Text>
</Space>
</Popover>
</Button>
) : ( ) : (
<Fragment> <Fragment>
{entityType && entityFqn && entityField && flag && !isTaskType ? ( {entityType && entityFqn && entityField && flag && !isTaskType ? (
<button <Button
className="link-text tw-self-start tw-w-7 tw-h-7 tw-mr-1 tw-flex-none hover-cell-icon" className="link-text tw-self-start w-7 h-7 m-r-xss tw-flex-none hover-cell-icon p-0"
data-testid="start-field-thread" data-testid="start-field-thread"
type="text"
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -80,8 +101,16 @@ export const getFieldThreadElement = (
getEntityFeedLink(entityType, entityFqn, entityField) getEntityFeedLink(entityType, entityFqn, entityField)
); );
}}> }}>
<SVGIcons alt="comments" icon={Icons.COMMENT_PLUS} width="16px" /> <Popover
</button> destroyTooltipOnHide
content={t('label.start-entity', {
entity: t('label.conversation'),
})}
overlayClassName="ant-popover-request-description"
trigger="hover">
<IconCommentPlus {...iconsProps} />
</Popover>
</Button>
) : null} ) : null}
</Fragment> </Fragment>
); );