From c6a1ae9c1b4976799b6f6c0f02c768eb4b6f3df9 Mon Sep 17 00:00:00 2001 From: Damien Coraboeuf Date: Sun, 15 Dec 2024 18:47:26 +0100 Subject: [PATCH] #1236 Horizontal display for promotions --- .../components/branches/BranchBuilds.js | 7 +- .../components/builds/BuildContent.js | 12 +-- .../components/builds/BuildPromotionInfo.js | 10 ++- .../builds/BuildPromotionInfoItem.js | 14 ++-- .../components/common/ClassUtils.js | 4 + .../components/common/ProxyImage.js | 5 +- .../components/common/icons/GeneratedIcon.js | 29 ++++--- .../extension/environments/EnvironmentIcon.js | 6 +- .../notifications/EntityNotificationsBadge.js | 82 ++++++++++++------- .../notifications/NotificationStatusBadge.js | 34 ++++---- .../EnvironmentBuildCount/Actions.js | 14 ---- .../EnvironmentBuildCount/Dot.js | 27 +++++- .../EnvironmentBuildCount/Name.js | 15 ---- .../PromotionLevel/Actions.js | 12 --- .../PromotionLevel/Dot.js | 27 +++++- .../PromotionLevel/Name.js | 14 ---- .../PromotionRun/Actions.js | 56 ------------- .../PromotionRun/Dot.js | 11 ++- .../PromotionRun/Name.js | 20 ----- .../SlotPipeline/Actions.js | 14 ---- .../SlotPipeline/Dot.js | 32 +++++++- .../SlotPipeline/Name.js | 13 --- .../promotionLevels/PromotionLevelImage.js | 5 +- .../promotionRuns/PromotionRunStep.js | 71 ++++++++++++++++ ontrack-web-core/styles/globals.css | 7 ++ 25 files changed, 298 insertions(+), 243 deletions(-) create mode 100644 ontrack-web-core/components/common/ClassUtils.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Actions.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Name.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Actions.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Name.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Actions.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Name.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Actions.js delete mode 100644 ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Name.js create mode 100644 ontrack-web-core/components/promotionRuns/PromotionRunStep.js diff --git a/ontrack-web-core/components/branches/BranchBuilds.js b/ontrack-web-core/components/branches/BranchBuilds.js index bd92f27f65..7824b7f552 100644 --- a/ontrack-web-core/components/branches/BranchBuilds.js +++ b/ontrack-web-core/components/branches/BranchBuilds.js @@ -1,7 +1,6 @@ import BuildBox from "@components/builds/BuildBox"; import {Button, Col, Popover, Row, Space, Spin, Table, Typography} from "antd"; import {FaCheckSquare, FaEyeSlash, FaSearch, FaSquare} from "react-icons/fa"; -import PromotionRun from "@components/promotionRuns/PromotionRun"; import RangeSelector from "@components/common/RangeSelector"; import {useRouter} from "next/router"; import BuildFilterDropdown from "@components/branches/filters/builds/BuildFilterDropdown"; @@ -15,6 +14,7 @@ import {useConnection, useGraphQLClient} from "@components/providers/ConnectionC import {gql} from "graphql-request"; import {buildUri, scmChangeLogUri} from "@components/common/Links"; import EntityNotificationsBadge from "@components/extension/notifications/EntityNotificationsBadge"; +import PromotionRunStep from "@components/promotionRuns/PromotionRunStep"; const {Column} = Table; @@ -233,10 +233,9 @@ export default function BranchBuilds({ { build.promotionRuns.map(promotionRun => - ) } diff --git a/ontrack-web-core/components/builds/BuildContent.js b/ontrack-web-core/components/builds/BuildContent.js index 347b8b5b91..4479743572 100644 --- a/ontrack-web-core/components/builds/BuildContent.js +++ b/ontrack-web-core/components/builds/BuildContent.js @@ -8,11 +8,11 @@ import BuildPromotionInfo from "@components/builds/BuildPromotionInfo"; export default function BuildContent({build}) { const defaultLayout = [ - {i: "promotions", x: 0, y: 0, w: 4, h: 18}, - {i: "validations", x: 6, y: 0, w: 8, h: 9}, - {i: "using", x: 4, y: 9, w: 4, h: 9}, - {i: "usedBy", x: 8, y: 9, w: 4, h: 9}, - {i: "notifications", x: 0, y: 18, w: 12, h: 9}, + {i: "promotions", x: 0, y: 0, w: 12, h: 4}, + {i: "validations", x: 0, y: 4, w: 12, h: 9}, + {i: "using", x: 0, y: 13, w: 6, h: 9}, + {i: "usedBy", x: 6, y: 13, w: 6, h: 9}, + {i: "notifications", x: 0, y: 22, w: 12, h: 9}, ] const items = [ @@ -51,7 +51,7 @@ export default function BuildContent({build}) { return ( <> { setLoading(false) @@ -99,10 +101,10 @@ export default function BuildPromotionInfo({build}) { return ( <> - diff --git a/ontrack-web-core/components/builds/BuildPromotionInfoItem.js b/ontrack-web-core/components/builds/BuildPromotionInfoItem.js index f954c8ea2c..019dd00a26 100644 --- a/ontrack-web-core/components/builds/BuildPromotionInfoItem.js +++ b/ontrack-web-core/components/builds/BuildPromotionInfoItem.js @@ -1,18 +1,14 @@ import {Dynamic} from "@components/common/Dynamic"; +/** + * Used in a Steps component. + */ export default function buildPromotionInfoItem({item, build, promotionLevel, onChange}) { return ({ - label: , - dot: , - children: , + status: 'finish', }) } \ No newline at end of file diff --git a/ontrack-web-core/components/common/ClassUtils.js b/ontrack-web-core/components/common/ClassUtils.js new file mode 100644 index 0000000000..2def602e45 --- /dev/null +++ b/ontrack-web-core/components/common/ClassUtils.js @@ -0,0 +1,4 @@ +export const actionClassName = (onClick, disabled, base = "") => { + const addons = onClick ? (disabled ? "ot-action ot-disabled" : "ot-action") : (disabled ? "ot-disabled" : "") + return `${base} ${addons}` +} \ No newline at end of file diff --git a/ontrack-web-core/components/common/ProxyImage.js b/ontrack-web-core/components/common/ProxyImage.js index dcf5f4c705..e0c42dc921 100644 --- a/ontrack-web-core/components/common/ProxyImage.js +++ b/ontrack-web-core/components/common/ProxyImage.js @@ -1,11 +1,12 @@ import {useRestClient} from "@components/providers/ConnectionContextProvider"; import {useEffect, useState} from "react"; import {Tooltip} from "antd"; +import {actionClassName} from "@components/common/ClassUtils"; /** * This renders an image using a call to the REST API. */ -export default function ProxyImage({restUri, alt, width, height, onClick, tooltipText}) { +export default function ProxyImage({restUri, alt, width, height, onClick, tooltipText, disabled = false}) { const client = useRestClient() @@ -38,7 +39,7 @@ export default function ProxyImage({restUri, alt, width, height, onClick, toolti width={width} height={height} onClick={onClick} - className={onClick ? "ot-action" : undefined} + className={actionClassName(onClick, disabled)} /> } diff --git a/ontrack-web-core/components/common/icons/GeneratedIcon.js b/ontrack-web-core/components/common/icons/GeneratedIcon.js index c2e77cce03..731e430f5b 100644 --- a/ontrack-web-core/components/common/icons/GeneratedIcon.js +++ b/ontrack-web-core/components/common/icons/GeneratedIcon.js @@ -1,36 +1,45 @@ import {getTextColorForBackground, numberToColorHsl} from "@components/common/colors/Colors"; import {Tooltip} from "antd"; +import {actionClassName} from "@components/common/ClassUtils"; -export default function GeneratedIcon({name, colorIndex, onClick, tooltipText}) { +export default function GeneratedIcon({name, colorIndex, onClick, tooltipText, size = 24, disabled = false}) { - const initials = generateInitials(name) + const initials = name && generateInitials(name) const bgColor = numberToColorHsl(colorIndex) const textColor = getTextColorForBackground(bgColor) + const fontSize = size * 0.5 + return ( <> - + { + name && + {initials} - + + } ) } diff --git a/ontrack-web-core/components/extension/environments/EnvironmentIcon.js b/ontrack-web-core/components/extension/environments/EnvironmentIcon.js index 1607fa57cb..90865b6500 100644 --- a/ontrack-web-core/components/extension/environments/EnvironmentIcon.js +++ b/ontrack-web-core/components/extension/environments/EnvironmentIcon.js @@ -8,7 +8,7 @@ import {useGraphQLClient} from "@components/providers/ConnectionContextProvider" import {gql} from "graphql-request"; import LoadingInline from "@components/common/LoadingInline"; -export default function EnvironmentIcon({environmentId, onClick, tooltipText, size = 16}) { +export default function EnvironmentIcon({environmentId, onClick, showTooltip = true, tooltipText, size = 16}) { const client = useGraphQLClient() const [refreshState, refresh] = useReloadState() @@ -35,7 +35,9 @@ export default function EnvironmentIcon({environmentId, onClick, tooltipText, si ).then(data => { const env = data.environmentById; setEnvironment(env) - setTooltip(tooltipText ?? env.name) + if (showTooltip) { + setTooltip(tooltipText ?? env.name) + } }).finally(() => { setLoading(false) }) diff --git a/ontrack-web-core/components/extension/notifications/EntityNotificationsBadge.js b/ontrack-web-core/components/extension/notifications/EntityNotificationsBadge.js index f1ecf3153b..3a745b9218 100644 --- a/ontrack-web-core/components/extension/notifications/EntityNotificationsBadge.js +++ b/ontrack-web-core/components/extension/notifications/EntityNotificationsBadge.js @@ -3,14 +3,17 @@ import {useEffect, useState} from "react"; import LoadingInline from "@components/common/LoadingInline"; import {gql} from "graphql-request"; import NotificationStatusBadge from "@components/extension/notifications/NotificationStatusBadge"; -import {Space} from "antd"; +import {Badge, Space} from "antd"; -export default function EntityNotificationsBadge({entityType, entityId, href}) { +export default function EntityNotificationsBadge({entityType, entityId, href, showText = false, children}) { const client = useGraphQLClient() const [loading, setLoading] = useState(true) const [statuses, setStatuses] = useState({}) + const [badgeCount, setBadgeCount] = useState(0) + const [badgeColour, setBadgeColour] = useState('') + useEffect(() => { if (client) { setLoading(true) @@ -54,6 +57,16 @@ export default function EntityNotificationsBadge({entityType, entityId, href}) { } }) setStatuses({success, running, error}) + if (error) { + setBadgeCount(error) + setBadgeColour("red") + } else if (running) { + setBadgeCount(running) + setBadgeColour("blue") + } else if (success) { + setBadgeCount(success) + setBadgeColour("green") + } }).finally(() => { setLoading(false) }) @@ -62,32 +75,45 @@ export default function EntityNotificationsBadge({entityType, entityId, href}) { return ( <> - - - - - - - + { + children && <> + + {children} + + + } + { + !children && + + + + + + + + } ) } \ No newline at end of file diff --git a/ontrack-web-core/components/extension/notifications/NotificationStatusBadge.js b/ontrack-web-core/components/extension/notifications/NotificationStatusBadge.js index f8de6de591..7290c822f6 100644 --- a/ontrack-web-core/components/extension/notifications/NotificationStatusBadge.js +++ b/ontrack-web-core/components/extension/notifications/NotificationStatusBadge.js @@ -2,24 +2,30 @@ import {Space, Tag, Typography} from "antd"; import Link from "next/link"; import {FaSpinner} from "react-icons/fa"; -export default function NotificationStatusBadge({status, spin, count, href, title}) { +export default function NotificationStatusBadge({status, spin, count, href, title, showText = false}) { return ( <> { count > 0 && - - - - { - spin && - } - {count} - - - + + + + + { + spin && + } + {count} + + + + { + showText && + {title} + } + } ) diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Actions.js b/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Actions.js deleted file mode 100644 index d681b1b1ac..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Actions.js +++ /dev/null @@ -1,14 +0,0 @@ -import {Badge} from "antd"; -import Link from "next/link"; -import {environmentsUri} from "@components/extension/environments/EnvironmentsLinksUtils"; - -export default function EnvironmentBuildCountBuildPromotionInfoItemActions({item, build, onChange}) { - return ( - <> - {/* TODO https://trello.com/c/LYl0s5dH/151-environment-page-as-control-board */} - - - - - ) -} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Dot.js b/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Dot.js index e3f7ec37ca..a6cc89bff8 100644 --- a/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Dot.js +++ b/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Dot.js @@ -1,9 +1,34 @@ import {FaServer} from "react-icons/fa"; +import {environmentsUri} from "@components/extension/environments/EnvironmentsLinksUtils"; +import Link from "next/link"; +import {Badge, Popover} from "antd"; +import {actionClassName} from "@components/common/ClassUtils"; export default function EnvironmentBuildCountBuildPromotionInfoItemDot({item, build, onChange}) { return ( <> - + + {/* TODO https://trello.com/c/LYl0s5dH/151-environment-page-as-control-board */} + + + + + + ) } \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Name.js b/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Name.js deleted file mode 100644 index 921327de02..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/EnvironmentBuildCount/Name.js +++ /dev/null @@ -1,15 +0,0 @@ -import {environmentsUri} from "@components/extension/environments/EnvironmentsLinksUtils"; -import Link from "next/link"; - -export default function EnvironmentBuildCountBuildPromotionInfoItemName({item, build, onChange}) { - return ( - <> - - # of environments - - - ) -} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Actions.js b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Actions.js deleted file mode 100644 index 85a38a5ed9..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Actions.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; -import {isAuthorized} from "@components/common/authorizations"; -import BuildPromoteAction from "@components/builds/BuildPromoteAction"; - -export default function PromotionLevelBuildPromotionInfoItemActions({item, build, promotionLevel, onChange}) { - return isAuthorized(build, 'build', 'promote') ? - : undefined -} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Dot.js b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Dot.js index 26084059c5..1c3d0705b1 100644 --- a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Dot.js +++ b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Dot.js @@ -1,8 +1,33 @@ import React from "react"; import {PromotionLevelImage} from "@components/promotionLevels/PromotionLevelImage"; +import {promotionLevelUri} from "@components/common/Links"; +import Link from "next/link"; +import {Popover, Space} from "antd"; +import PromotionLevelLink from "@components/promotionLevels/PromotionLevelLink"; +import {isAuthorized} from "@components/common/authorizations"; +import BuildPromoteAction from "@components/builds/BuildPromoteAction"; export default function PromotionLevelBuildPromotionInfoItemDor({item, build, promotionLevel, onChange}) { return ( - + } + content={ + + {item.description} + { + isAuthorized(build, 'build', 'promote') && + + } + + } + > + + + + ) } \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Name.js b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Name.js deleted file mode 100644 index 497097807f..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionLevel/Name.js +++ /dev/null @@ -1,14 +0,0 @@ -import {promotionLevelUri} from "@components/common/Links"; -import {Space, Typography} from "antd"; -import Link from "next/link"; -import React from "react"; - -export default function PromotionLevelBuildPromotionInfoItemName({item, build, promotionLevel, onChange}) { - return ( - - - {item.name} - - - ) -} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Actions.js b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Actions.js deleted file mode 100644 index db2ecfd230..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Actions.js +++ /dev/null @@ -1,56 +0,0 @@ -import React from "react"; -import {Popover, Space, Typography} from "antd"; -import TimestampText from "@components/common/TimestampText"; -import AnnotatedDescription from "@components/common/AnnotatedDescription"; -import {isAuthorized} from "@components/common/authorizations"; -import PromotionRunLink from "@components/promotionRuns/PromotionRunLink"; -import {FaCog} from "react-icons/fa"; -import PromotionRunDeleteAction from "@components/promotionRuns/PromotionRunDeleteAction"; -import {promotionRunUri} from "@components/common/Links"; -import Link from "next/link"; -import BuildPromoteAction from "@components/builds/BuildPromoteAction"; - -export default function PromotionRunBuildPromotionInfoItemActions({item, build, promotionLevel, onChange}) { - return ( - <> - - - Promoted by {item.creation.user} - - - - }> - - - - - {/* Link to the promotion run */} - { - } - /> - } - {/* Repromoting */} - { - isAuthorized(build, 'build', 'promote') ? - : undefined - - } - {/* Deleting the promotion */} - { - isAuthorized(item, 'promotion_run', 'delete') ? - : undefined - } - - - ) -} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Dot.js b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Dot.js index 4393317614..9582a68989 100644 --- a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Dot.js +++ b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Dot.js @@ -1,8 +1,15 @@ import React from "react"; -import {PromotionLevelImage} from "@components/promotionLevels/PromotionLevelImage"; +import PromotionRunStep from "@components/promotionRuns/PromotionRunStep"; export default function PromotionRunBuildPromotionInfoItemDor({item, build, promotionLevel, onChange}) { return ( - + ) } \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Name.js b/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Name.js deleted file mode 100644 index 10d61ed088..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/PromotionRun/Name.js +++ /dev/null @@ -1,20 +0,0 @@ -import {promotionLevelUri, promotionRunUri} from "@components/common/Links"; -import {Space, Typography} from "antd"; -import Link from "next/link"; -import React from "react"; -import EntityNotificationsBadge from "@components/extension/notifications/EntityNotificationsBadge"; - -export default function PromotionRunBuildPromotionInfoItemName({item, build, promotionLevel, onChange}) { - return ( - - - {promotionLevel.name} - - - - ) -} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Actions.js b/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Actions.js deleted file mode 100644 index 84c87be0fa..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Actions.js +++ /dev/null @@ -1,14 +0,0 @@ -import {environmentsUri} from "@components/extension/environments/EnvironmentsLinksUtils"; -import Link from "next/link"; -import TimestampText from "@components/common/TimestampText"; -import React from "react"; - -export default function SlotPipelineBuildPromotionInfoItemActions({item, onChange}) { - return ( - <> - - - - - ) -} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Dot.js b/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Dot.js index 4c3cf2d9bb..1b6c04e1b8 100644 --- a/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Dot.js +++ b/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Dot.js @@ -1,5 +1,35 @@ import EnvironmentIcon from "@components/extension/environments/EnvironmentIcon"; +import {environmentsUri, slotPipelineUri} from "@components/extension/environments/EnvironmentsLinksUtils"; +import Link from "next/link"; +import {Popover, Space} from "antd"; +import TimestampText from "@components/common/TimestampText"; +import React from "react"; export default function SlotPipelineBuildPromotionInfoItemDot({item}) { - return + return ( + <> + + + {item.slot.environment.name} + + } + content={ + <> + + + + + + + } + > + {/* TODO https://trello.com/c/LYl0s5dH/151-environment-page-as-control-board */} + + + + + + ) } \ No newline at end of file diff --git a/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Name.js b/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Name.js deleted file mode 100644 index be29228fa7..0000000000 --- a/ontrack-web-core/components/framework/build-promotion-info-item/SlotPipeline/Name.js +++ /dev/null @@ -1,13 +0,0 @@ -import Link from "next/link"; -import {environmentsUri} from "@components/extension/environments/EnvironmentsLinksUtils"; - -export default function SlotPipelineBuildPromotionInfoItemActions({item, build, promotionLevel, onChange}) { - return ( - <> - {/* TODO https://trello.com/c/LYl0s5dH/151-environment-page-as-control-board */} - - {item.slot.environment.name}{item.slot.qualifier && `/${item.slot.qualifier}`}   - - - ) -} \ No newline at end of file diff --git a/ontrack-web-core/components/promotionLevels/PromotionLevelImage.js b/ontrack-web-core/components/promotionLevels/PromotionLevelImage.js index e77b2f05e2..c19ceefac9 100644 --- a/ontrack-web-core/components/promotionLevels/PromotionLevelImage.js +++ b/ontrack-web-core/components/promotionLevels/PromotionLevelImage.js @@ -4,7 +4,7 @@ import {EventsContext} from "@components/common/EventsContext"; import ProxyImage from "@components/common/ProxyImage"; import GeneratedIcon from "@components/common/icons/GeneratedIcon"; -export const PromotionLevelImage = ({promotionLevel, size = 16}) => { +export const PromotionLevelImage = ({promotionLevel, size = 24, disabled = false}) => { const [refresh, setRefresh] = useState(0) const eventsContext = useContext(EventsContext) @@ -20,9 +20,12 @@ export const PromotionLevelImage = ({promotionLevel, size = 16}) => { alt={promotionLevel.name} width={size} height={size} + disabled={disabled} /> : ) } \ No newline at end of file diff --git a/ontrack-web-core/components/promotionRuns/PromotionRunStep.js b/ontrack-web-core/components/promotionRuns/PromotionRunStep.js new file mode 100644 index 0000000000..ea90271124 --- /dev/null +++ b/ontrack-web-core/components/promotionRuns/PromotionRunStep.js @@ -0,0 +1,71 @@ +import {Popover, Space, Typography} from "antd"; +import PromotionLevelLink from "@components/promotionLevels/PromotionLevelLink"; +import TimestampText from "@components/common/TimestampText"; +import AnnotatedDescription from "@components/common/AnnotatedDescription"; +import EntityNotificationsBadge from "@components/extension/notifications/EntityNotificationsBadge"; +import {promotionRunUri} from "@components/common/Links"; +import {isAuthorized} from "@components/common/authorizations"; +import BuildPromoteAction from "@components/builds/BuildPromoteAction"; +import PromotionRunDeleteAction from "@components/promotionRuns/PromotionRunDeleteAction"; +import Link from "next/link"; +import {PromotionLevelImage} from "@components/promotionLevels/PromotionLevelImage"; +import React from "react"; + +/** + * Representation of a promotion run to place in a list of steps. + * + * @param run Promotion run + * @param onChange Function to call when the promotion run triggers an action (delete or promotion) + */ +export default function PromotionRunStep({run, onChange}) { + return ( + <> + } + content={ + + Promoted by {run.creation.user} + + + + + {/* Repromoting */} + { + isAuthorized(run, 'build', 'promote') ? + : undefined + + } + {/* Deleting the promotion */} + { + isAuthorized(run, 'promotion_run', 'delete') ? + : undefined + } + + + } + > + + + + + + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/styles/globals.css b/ontrack-web-core/styles/globals.css index 856cd56b70..5d41be8c5e 100644 --- a/ontrack-web-core/styles/globals.css +++ b/ontrack-web-core/styles/globals.css @@ -35,6 +35,13 @@ opacity: 100%; } +/** + * Disabled icon + */ +.ot-disabled { + filter: opacity(33%); +} + /** * Displaying a pointer cursor */