diff --git a/portals-ui/packages/components/lib/components/status-icon/index.tsx b/portals-ui/packages/components/lib/components/status-icon/index.tsx new file mode 100644 index 0000000000..5f972cbff1 --- /dev/null +++ b/portals-ui/packages/components/lib/components/status-icon/index.tsx @@ -0,0 +1,41 @@ +import { RunStatuses } from '@cloud-pipeline/core'; +import type { CommonProps } from '../common.types'; +import classNames from 'classnames'; + +type StatusIconProps = CommonProps & { + status: RunStatuses; + radius?: number; + strokeWidth?: number; +}; + +const statusClassNames: Record = { + [RunStatuses.success]: 'fill-green-600 stroke-green-600', + [RunStatuses.running]: 'fill-transparent stroke-green-600', + [RunStatuses.failure]: 'fill-red-600 stroke-red-600', + [RunStatuses.stopped]: 'fill-transparent stroke-red-600', + [RunStatuses.resuming]: 'fill-sky-600 stroke-sky-600', + [RunStatuses.paused]: 'fill-slate-400 stroke-slate-400', + [RunStatuses.pausing]: 'fill-sky-600 stroke-sky-600', +}; + +export function StatusIcon({ + radius = 5, + strokeWidth = 3, + className, + style, + status, +}: StatusIconProps) { + return ( + + + + ); +} diff --git a/portals-ui/packages/components/lib/index.ts b/portals-ui/packages/components/lib/index.ts index e19da45bcf..00460084ad 100644 --- a/portals-ui/packages/components/lib/index.ts +++ b/portals-ui/packages/components/lib/index.ts @@ -1,11 +1,12 @@ import List, { ListHeader } from './components/list'; import type { UserCardProps } from './components/user-card'; import { UserCard } from './components/user-card'; +import { StatusIcon } from './components/status-icon'; import '@epam/uui-components/styles.css'; import '@epam/uui/styles.css'; import './style.css'; -export { List, UserCard, ListHeader }; +export { List, UserCard, ListHeader, StatusIcon }; export type { UserCardProps }; export type * from './components/common.types'; export type * from './components/list/types'; diff --git a/portals-ui/packages/core/src/utilities/dates.ts b/portals-ui/packages/core/src/utilities/dates.ts new file mode 100644 index 0000000000..326b3d1eab --- /dev/null +++ b/portals-ui/packages/core/src/utilities/dates.ts @@ -0,0 +1,15 @@ +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; + +dayjs.extend(utc); + +const displayFormat = 'YYYY-MM-DD, HH:mm:ss'; + +const displayDate = (date: string, format: string = displayFormat): string => { + if (!date) { + return ''; + } + return dayjs.utc(date).local().format(format); +}; + +export { displayDate }; diff --git a/portals-ui/packages/core/src/utilities/index.ts b/portals-ui/packages/core/src/utilities/index.ts index dd0168b303..4d05fb941d 100644 --- a/portals-ui/packages/core/src/utilities/index.ts +++ b/portals-ui/packages/core/src/utilities/index.ts @@ -1,3 +1,4 @@ export * from './acl'; export * from './misc'; export * from './users'; +export * from './dates'; diff --git a/portals-ui/sites/ngs-portal/src/pages/home/components/pipeline-card.tsx b/portals-ui/sites/ngs-portal/src/pages/home/components/pipeline-card.tsx index cfea2617ff..0f0a80f005 100644 --- a/portals-ui/sites/ngs-portal/src/pages/home/components/pipeline-card.tsx +++ b/portals-ui/sites/ngs-portal/src/pages/home/components/pipeline-card.tsx @@ -1,4 +1,4 @@ -import { Tag, Badge, FlexRow, RichTextView } from '@epam/uui'; +import { Tag, Badge, FlexRow, Button, RichTextView } from '@epam/uui'; import ContentPersonFillIcon from '@epam/assets/icons/content-person-fill.svg?react'; import cn from 'classnames'; import { Link } from 'react-router-dom'; @@ -89,46 +89,54 @@ export const PipelineCard = ({ const filteredTag = useMemo(() => tags.filter(filterTag), [tags]); return ( -
- {/* {tags?.length && ( -
- {tags.map((tag) => ( - - ))} -
- )} */} - {filteredTag.length > 0 && ( -
- {filteredTag.map((tag) => ( - - ))} -
+
- - {name} - - - } - color="neutral" - size="18" - cx="shrink-0" - /> - - - {description && ( - {description} + style={style}> +
+ {filteredTag.length > 0 && ( +
+ {filteredTag.map((tag) => ( + + ))} +
+ )} + + + {name} + + } + color="neutral" + size="18" + cx="shrink-0" + /> + + {description && ( + {description} + )} +
+ {mode === 'extended' && ( +
+
)}
); diff --git a/portals-ui/sites/ngs-portal/src/pages/home/components/project-card.tsx b/portals-ui/sites/ngs-portal/src/pages/home/components/project-card.tsx index e2208f2740..a345072d56 100644 --- a/portals-ui/sites/ngs-portal/src/pages/home/components/project-card.tsx +++ b/portals-ui/sites/ngs-portal/src/pages/home/components/project-card.tsx @@ -1,14 +1,17 @@ import { Badge, FlexRow, RichTextView } from '@epam/uui'; import ContentPersonFillIcon from '@epam/assets/icons/content-person-fill.svg?react'; +import ActionCalendarFillIcon from '@epam/assets/icons/action-calendar-fill.svg?react'; import cn from 'classnames'; import { Link } from 'react-router-dom'; import type { Project } from '@cloud-pipeline/core'; +import { RunStatuses } from '@cloud-pipeline/core'; import { + displayDate, executeAllowed, readAllowed, writeAllowed, } from '@cloud-pipeline/core'; -import type { CommonProps } from '@cloud-pipeline/components'; +import { StatusIcon, type CommonProps } from '@cloud-pipeline/components'; import HighlightedText from '../../../shared/highlight-text'; import { NgsUserCard } from '../../../widgets/ngs-user-card'; import { useMemo } from 'react'; @@ -101,52 +104,98 @@ export const ProjectCard = ({ const hasSomeRights = read || write || execute; + const { showPermissionTags, showExtraInfo, showDescription, showStatusInfo } = + useMemo( + () => ({ + showPermissionTags: mode === 'standard' && hasSomeRights, + showExtraInfo: mode === 'extended', + showDescription: !!description, + showStatusInfo: mode === 'extended', + }), + [description, hasSomeRights, mode], + ); + return ( -
- {filteredTag.length > 0 && ( -
- {filteredTag.map((tag) => ( - - ))} -
+
- - {name} - - } - color="neutral" - size="18" - cx="shrink-0" - /> - - - {hasSomeRights && ( - - {read && ( - - )} - {write && ( - - )} - {execute && ( - + style={style}> +
+ {filteredTag.length > 0 && ( +
+ {filteredTag.map((tag) => ( + + ))} +
+ )} + + + {name} + + } + color="neutral" + size="18" + cx="shrink-0" + /> + {showExtraInfo && ( +
+
+ + {displayDate(project.createdDate)} +
+
+ + {Math.floor(Math.random() * 10 + 1)} users +
+
)}
+ {showPermissionTags && ( + + {read && ( + + )} + {write && ( + + )} + {execute && ( + + )} + + )} + {showDescription && {description}} +
+ {showStatusInfo && ( +
+
+ + {Math.floor(Math.random() * 10 + 1)} running +
+
+ + + Last finished: RNA Sequence pipeline with a long name (version: 3) + +
+
)} - - {description && {description}}
); }; diff --git a/portals-ui/sites/ngs-portal/src/pages/home/components/style.css b/portals-ui/sites/ngs-portal/src/pages/home/components/style.css index 06dad0e51f..afb2ec7012 100644 --- a/portals-ui/sites/ngs-portal/src/pages/home/components/style.css +++ b/portals-ui/sites/ngs-portal/src/pages/home/components/style.css @@ -1,3 +1,7 @@ .ngs-container { - @apply px-3 py-2 bg-white space-y-1; + @apply px-3 py-2 bg-white space-y-1; +} + +.ngs-container-extended { + @apply px-3 py-2 bg-white flex gap-2 flex-nowrap; } diff --git a/portals-ui/sites/ngs-portal/src/pages/projects/projects.tsx b/portals-ui/sites/ngs-portal/src/pages/projects/projects.tsx index 1ff5604571..a4ff3d05d8 100644 --- a/portals-ui/sites/ngs-portal/src/pages/projects/projects.tsx +++ b/portals-ui/sites/ngs-portal/src/pages/projects/projects.tsx @@ -66,7 +66,7 @@ export function ProjectsPage() { //todo: search refactoring needed (see search) return (