mirror of
https://github.com/datahub-project/datahub.git
synced 2025-12-27 09:58:14 +00:00
fix(ui): humanize timestamps on ML entities UI (#12788)
This commit is contained in:
parent
372feeeade
commit
34928ad5f5
@ -3,12 +3,12 @@ import styled from 'styled-components';
|
||||
import { Space, Table, Typography } from 'antd';
|
||||
import { formatDetailedDuration } from '@src/app/shared/time/timeUtils';
|
||||
import { capitalize } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { Pill } from '@components';
|
||||
import { MlHyperParam, MlMetric, DataProcessInstanceRunResultType } from '../../../../types.generated';
|
||||
import { useBaseEntity } from '../../shared/EntityContext';
|
||||
import { InfoItem } from '../../shared/components/styled/InfoItem';
|
||||
import { GetDataProcessInstanceQuery } from '../../../../graphql/dataProcessInstance.generated';
|
||||
import { Pill } from '../../../../alchemy-components/components/Pills';
|
||||
import { TimestampPopover } from '../../../sharedV2/TimestampPopover';
|
||||
|
||||
const TabContent = styled.div`
|
||||
padding: 16px;
|
||||
@ -39,7 +39,7 @@ const propertyTableColumns = [
|
||||
},
|
||||
];
|
||||
|
||||
export default function MLModelSummary() {
|
||||
export default function DataProcessInstanceSummary() {
|
||||
const baseEntity = useBaseEntity<GetDataProcessInstanceQuery>();
|
||||
const dpi = baseEntity?.dataProcessInstance;
|
||||
|
||||
@ -61,11 +61,7 @@ export default function MLModelSummary() {
|
||||
<Typography.Title level={3}>Details</Typography.Title>
|
||||
<InfoItemContainer justifyContent="left">
|
||||
<InfoItem title="Created At">
|
||||
<InfoItemContent>
|
||||
{dpi?.properties?.created?.time
|
||||
? moment(dpi.properties.created.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={dpi?.properties?.created?.time} title="Created At" />
|
||||
</InfoItem>
|
||||
<InfoItem title="Status">
|
||||
<InfoItemContent>{formatStatus(dpi?.state)}</InfoItemContent>
|
||||
|
||||
@ -3,7 +3,6 @@ import styled from 'styled-components';
|
||||
import { Space, Table, Typography } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { colors } from '@src/alchemy-components/theme';
|
||||
import moment from 'moment';
|
||||
import { useEntityRegistry } from '../../../useEntityRegistry';
|
||||
import { MlHyperParam, MlMetric, EntityType } from '../../../../types.generated';
|
||||
import { useBaseEntity } from '../../shared/EntityContext';
|
||||
@ -11,6 +10,7 @@ import { GetMlModelQuery } from '../../../../graphql/mlModel.generated';
|
||||
import { InfoItem } from '../../shared/components/styled/InfoItem';
|
||||
import { notEmpty } from '../../shared/utils';
|
||||
import { Pill } from '../../../../alchemy-components/components/Pills';
|
||||
import { TimestampPopover } from '../../../sharedV2/TimestampPopover';
|
||||
|
||||
const TabContent = styled.div`
|
||||
padding: 16px;
|
||||
@ -85,21 +85,13 @@ export default function MLModelSummary() {
|
||||
<InfoItemContent>{model?.versionProperties?.version?.versionTag}</InfoItemContent>
|
||||
</InfoItem>
|
||||
<InfoItem title="Registered At">
|
||||
<InfoItemContent>
|
||||
{model?.properties?.created?.time
|
||||
? moment(model.properties.created.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={model?.properties?.created?.time} title="Registered At" />
|
||||
</InfoItem>
|
||||
<InfoItem title="Last Modified At">
|
||||
<InfoItemContent>
|
||||
{model?.properties?.lastModified?.time
|
||||
? moment(model.properties.lastModified.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={model?.properties?.lastModified?.time} title="Last Modified At" />
|
||||
</InfoItem>
|
||||
<InfoItem title="Created By">
|
||||
<InfoItemContent>{model?.properties?.created?.actor}</InfoItemContent>
|
||||
<InfoItemContent>{model?.properties?.created?.actor || '-'}</InfoItemContent>
|
||||
</InfoItem>
|
||||
</InfoItemContainer>
|
||||
<InfoItemContainer justifyContent="left">
|
||||
|
||||
@ -3,7 +3,6 @@ import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { colors } from '@src/alchemy-components/theme';
|
||||
import { Pill } from '@src/alchemy-components/components/Pills';
|
||||
import moment from 'moment';
|
||||
import { GetMlModelGroupQuery } from '../../../../graphql/mlModelGroup.generated';
|
||||
import { EntityType } from '../../../../types.generated';
|
||||
import { useEntityRegistry } from '../../../useEntityRegistry';
|
||||
@ -11,6 +10,7 @@ import { useBaseEntity } from '../../shared/EntityContext';
|
||||
import { notEmpty } from '../../shared/utils';
|
||||
import { EmptyTab } from '../../shared/components/styled/EmptyTab';
|
||||
import { InfoItem } from '../../shared/components/styled/InfoItem';
|
||||
import { TimestampPopover } from '../../../sharedV2/TimestampPopover';
|
||||
|
||||
const InfoItemContainer = styled.div<{ justifyContent }>`
|
||||
display: flex;
|
||||
@ -33,6 +33,7 @@ const NameLink = styled.a`
|
||||
font-weight: 700;
|
||||
color: inherit;
|
||||
font-size: 0.9rem;
|
||||
|
||||
&:hover {
|
||||
color: ${colors.blue[400]} !important;
|
||||
}
|
||||
@ -101,11 +102,7 @@ export default function MLGroupModels() {
|
||||
key: 'createdAt',
|
||||
width: 150,
|
||||
render: (_: any, record: any) => (
|
||||
<Typography.Text>
|
||||
{record.properties?.createdTS?.time
|
||||
? moment(record.properties.createdTS.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</Typography.Text>
|
||||
<TimestampPopover timestamp={record.properties?.createdTS?.time} title="Created At" showPopover />
|
||||
),
|
||||
},
|
||||
{
|
||||
@ -159,18 +156,10 @@ export default function MLGroupModels() {
|
||||
<Typography.Title level={3}>Model Group Details</Typography.Title>
|
||||
<InfoItemContainer justifyContent="left">
|
||||
<InfoItem title="Created At">
|
||||
<InfoItemContent>
|
||||
{modelGroup?.properties?.created?.time
|
||||
? moment(modelGroup.properties.created.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={modelGroup?.properties?.created?.time} title="Created At" />
|
||||
</InfoItem>
|
||||
<InfoItem title="Last Modified At">
|
||||
<InfoItemContent>
|
||||
{modelGroup?.properties?.lastModified?.time
|
||||
? moment(modelGroup.properties.lastModified.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={modelGroup?.properties?.lastModified?.time} title="Last Modified At" />
|
||||
</InfoItem>
|
||||
{modelGroup?.properties?.created?.actor && (
|
||||
<InfoItem title="Created By">
|
||||
|
||||
@ -10,7 +10,7 @@ import styled from 'styled-components';
|
||||
import { Space, Table, Typography } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { colors } from '@src/alchemy-components/theme';
|
||||
import moment from 'moment';
|
||||
import { TimestampPopover } from '../../../sharedV2/TimestampPopover';
|
||||
|
||||
const TabContent = styled.div`
|
||||
padding: 16px;
|
||||
@ -87,21 +87,13 @@ export default function MLModelSummary() {
|
||||
<InfoItemContent>{model?.versionProperties?.version?.versionTag}</InfoItemContent>
|
||||
</InfoItem>
|
||||
<InfoItem title="Registered At">
|
||||
<InfoItemContent>
|
||||
{model?.properties?.created?.time
|
||||
? moment(model.properties.created.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={model?.properties?.created?.time} title="Registered At" />
|
||||
</InfoItem>
|
||||
<InfoItem title="Last Modified At">
|
||||
<InfoItemContent>
|
||||
{model?.properties?.lastModified?.time
|
||||
? moment(model.properties.lastModified.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={model?.properties?.lastModified?.time} title="Last Modified At" />
|
||||
</InfoItem>
|
||||
<InfoItem title="Created By">
|
||||
<InfoItemContent>{model?.properties?.created?.actor}</InfoItemContent>
|
||||
<InfoItemContent>{model?.properties?.created?.actor || '-'}</InfoItemContent>
|
||||
</InfoItem>
|
||||
</InfoItemContainer>
|
||||
<InfoItemContainer justifyContent="left">
|
||||
|
||||
@ -10,7 +10,7 @@ import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { colors } from '@src/alchemy-components/theme';
|
||||
import { Pill } from '@src/alchemy-components/components/Pills';
|
||||
import moment from 'moment';
|
||||
import { TimestampPopover } from '../../../sharedV2/TimestampPopover';
|
||||
|
||||
const InfoItemContainer = styled.div<{ justifyContent }>`
|
||||
display: flex;
|
||||
@ -104,11 +104,7 @@ export default function MLGroupModels() {
|
||||
key: 'createdAt',
|
||||
width: 150,
|
||||
render: (_: any, record: any) => (
|
||||
<Typography.Text>
|
||||
{record.properties?.createdTS?.time
|
||||
? moment(record.properties.createdTS.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</Typography.Text>
|
||||
<TimestampPopover timestamp={record.properties?.createdTS?.time} title="Created At" showPopover />
|
||||
),
|
||||
},
|
||||
{
|
||||
@ -162,18 +158,10 @@ export default function MLGroupModels() {
|
||||
<Typography.Title level={3}>Model Group Details</Typography.Title>
|
||||
<InfoItemContainer justifyContent="left">
|
||||
<InfoItem title="Created At">
|
||||
<InfoItemContent>
|
||||
{modelGroup?.properties?.created?.time
|
||||
? moment(modelGroup.properties.created.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={modelGroup?.properties?.created?.time} title="Created At" />
|
||||
</InfoItem>
|
||||
<InfoItem title="Last Modified At">
|
||||
<InfoItemContent>
|
||||
{modelGroup?.properties?.lastModified?.time
|
||||
? moment(modelGroup.properties.lastModified.time).format('YYYY-MM-DD HH:mm:ss')
|
||||
: '-'}
|
||||
</InfoItemContent>
|
||||
<TimestampPopover timestamp={modelGroup?.properties?.lastModified?.time} title="Last Modified At" />
|
||||
</InfoItem>
|
||||
{modelGroup?.properties?.created?.actor && (
|
||||
<InfoItem title="Created By">
|
||||
|
||||
63
datahub-web-react/src/app/sharedV2/TimestampPopover.tsx
Normal file
63
datahub-web-react/src/app/sharedV2/TimestampPopover.tsx
Normal file
@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Popover } from '@components';
|
||||
import colors from '@src/alchemy-components/theme/foundations/colors';
|
||||
import { toRelativeTimeString, toLocalDateTimeString } from '@src/app/shared/time/timeUtils';
|
||||
|
||||
const PopoverContent = styled.div`
|
||||
color: ${colors.gray[500]};
|
||||
font-size: 0.8rem;
|
||||
`;
|
||||
|
||||
const Title = styled.div`
|
||||
color: ${colors.gray[500]};
|
||||
border-bottom: none;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
`;
|
||||
|
||||
const InfoItemContent = styled.div`
|
||||
padding-top: 8px;
|
||||
width: 100px;
|
||||
overflow-wrap: break-word;
|
||||
`;
|
||||
|
||||
const popoverStyles = {
|
||||
overlayInnerStyle: {
|
||||
borderRadius: '10px',
|
||||
},
|
||||
overlayStyle: {
|
||||
margin: '5px',
|
||||
},
|
||||
};
|
||||
|
||||
interface TimestampProps {
|
||||
timestamp?: number;
|
||||
title: string;
|
||||
showPopover?: boolean;
|
||||
}
|
||||
|
||||
export const TimestampPopover: React.FC<TimestampProps> = ({ timestamp, title, showPopover = true }) => {
|
||||
if (!timestamp) {
|
||||
return <InfoItemContent>-</InfoItemContent>;
|
||||
}
|
||||
|
||||
const relativeTime = toRelativeTimeString(timestamp);
|
||||
const absoluteTime = toLocalDateTimeString(timestamp);
|
||||
|
||||
if (!showPopover) {
|
||||
return <InfoItemContent>{relativeTime}</InfoItemContent>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover
|
||||
content={<PopoverContent>{absoluteTime}</PopoverContent>}
|
||||
title={<Title>{title}</Title>}
|
||||
trigger="hover"
|
||||
overlayInnerStyle={popoverStyles.overlayInnerStyle}
|
||||
overlayStyle={popoverStyles.overlayStyle}
|
||||
>
|
||||
<InfoItemContent>{relativeTime}</InfoItemContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
@ -21,8 +21,7 @@ describe("models", () => {
|
||||
cy.wait("@graphqlRequest");
|
||||
|
||||
// Ensure page has loaded by checking for specific content
|
||||
cy.contains("2025-03-03").should("be.visible");
|
||||
cy.contains("2025-03-04").should("be.visible");
|
||||
cy.contains("ago").should("be.visible"); // relative time
|
||||
cy.contains("urn:li:corpuser:datahub").should("be.visible");
|
||||
|
||||
// Navigate to Properties tab with verification
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user