github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/frontend-service/src/ui/components/chip/EnvironmentGroupChip.tsx (about) 1 /*This file is part of kuberpult. 2 3 Kuberpult is free software: you can redistribute it and/or modify 4 it under the terms of the Expat(MIT) License as published by 5 the Free Software Foundation. 6 7 Kuberpult is distributed in the hope that it will be useful, 8 but WITHOUT ANY WARRANTY; without even the implied warranty of 9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 MIT License for more details. 11 12 You should have received a copy of the MIT License 13 along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>. 14 15 Copyright 2023 freiheit.com*/ 16 import classNames from 'classnames'; 17 import { Environment, EnvironmentGroup } from '../../../api/api'; 18 import React from 'react'; 19 import { 20 EnvironmentGroupExtended, 21 getPriorityClassName, 22 useCurrentlyDeployedAtGroup, 23 useArgoCDNamespace, 24 } from '../../utils/store'; 25 import { LocksWhite } from '../../../images'; 26 import { EnvironmentLockDisplay } from '../EnvironmentLockDisplay/EnvironmentLockDisplay'; 27 import { ArgoAppEnvLink } from '../../utils/Links'; 28 29 export const AppLockSummary: React.FC<{ 30 app: string; 31 numLocks: number; 32 }> = ({ app, numLocks }) => { 33 const plural = numLocks === 1 ? 'lock' : 'locks'; 34 return ( 35 <div 36 key={'app-lock-hint-' + app} 37 title={'"' + app + '" has ' + numLocks + ' application ' + plural + '. Click on a tile to see details.'}> 38 <div> 39 40 <LocksWhite className="env-card-env-lock-icon" width="16px" height="16px" /> 41 </div> 42 </div> 43 ); 44 }; 45 46 export type EnvironmentChipProps = { 47 className: string; 48 env: Environment; 49 envGroup: EnvironmentGroup; 50 app: string; 51 groupNameOverride?: string; 52 numberEnvsDeployed?: number; 53 numberEnvsInGroup?: number; 54 smallEnvChip?: boolean; 55 }; 56 57 export const EnvironmentChip = (props: EnvironmentChipProps): JSX.Element => { 58 const { className, env, envGroup, smallEnvChip, app } = props; 59 const priorityClassName = getPriorityClassName(envGroup); 60 const name = props.groupNameOverride ? props.groupNameOverride : env.name; 61 62 const namespace = useArgoCDNamespace(); 63 64 const numberString = 65 props.numberEnvsDeployed && props.numberEnvsInGroup 66 ? props.numberEnvsDeployed !== props.numberEnvsInGroup 67 ? '(' + props.numberEnvsDeployed + '/' + props.numberEnvsInGroup + ')' 68 : '(' + props.numberEnvsInGroup + ')' // when all envs are deployed, only show the total number on envs 69 : ''; 70 const locks = !smallEnvChip ? ( 71 <div className={classNames(className, 'env-locks')}> 72 {Object.values(env.locks).map((lock) => ( 73 <EnvironmentLockDisplay 74 env={env.name} 75 lockId={lock.lockId} 76 bigLockIcon={false} 77 key={'key-' + env.name + '-' + lock.lockId} 78 /> 79 ))} 80 </div> 81 ) : ( 82 !!Object.entries(env.locks).length && ( 83 <div className={classNames(className, 'env-locks')}> 84 <LocksWhite className="env-card-env-lock-icon" width="12px" height="12px" /> 85 </div> 86 ) 87 ); 88 return ( 89 <div className={classNames('mdc-evolution-chip', className, priorityClassName)} role="row"> 90 <span 91 className="mdc-evolution-chip__cell mdc-evolution-chip__cell--primary mdc-evolution-chip__action--primary" 92 role="gridcell"> 93 <span className="mdc-evolution-chip__text-name"> 94 {smallEnvChip ? ( 95 name[0].toUpperCase() 96 ) : ( 97 <ArgoAppEnvLink app={app} env={name} namespace={namespace} /> 98 )} 99 </span>{' '} 100 <span className="mdc-evolution-chip__text-numbers">{numberString}</span> 101 {locks} 102 </span> 103 </div> 104 ); 105 }; 106 107 export const EnvironmentGroupChip = (props: { 108 className: string; 109 envGroup: EnvironmentGroupExtended; 110 app: string; 111 smallEnvChip?: boolean; 112 }): JSX.Element => { 113 const { className, envGroup, app, smallEnvChip } = props; 114 115 // we display it different if there's only one env in this group: 116 const displayAsGroup = envGroup.environments.length >= 2; 117 if (displayAsGroup) { 118 return ( 119 <div className={'EnvironmentGroupChip'}> 120 <EnvironmentChip 121 className={className} 122 env={envGroup.environments[0]} 123 envGroup={envGroup} 124 app={app} 125 groupNameOverride={envGroup.environmentGroupName} 126 numberEnvsDeployed={envGroup.environments.length} 127 numberEnvsInGroup={envGroup.numberOfEnvsInGroup} 128 smallEnvChip={smallEnvChip} 129 /> 130 </div> 131 ); 132 } 133 // since there's only 1 env, we display that: 134 return ( 135 <EnvironmentChip 136 className={className} 137 env={envGroup.environments[0]} 138 envGroup={envGroup} 139 app={app} 140 groupNameOverride={undefined} 141 numberEnvsDeployed={1} 142 numberEnvsInGroup={envGroup.numberOfEnvsInGroup} 143 smallEnvChip={smallEnvChip} 144 /> 145 ); 146 }; 147 148 export type EnvChipListProps = { 149 version: number; 150 app: string; 151 smallEnvChip?: boolean; 152 }; 153 154 export const EnvironmentGroupChipList: React.FC<EnvChipListProps> = (props) => { 155 const deployedAt = useCurrentlyDeployedAtGroup(props.app, props.version); 156 return ( 157 <div className={'env-group-chip-list env-group-chip-list-test'}> 158 {' '} 159 {deployedAt.map((envGroup) => ( 160 <EnvironmentGroupChip 161 key={envGroup.environmentGroupName} 162 app={props.app} 163 envGroup={envGroup} 164 className={'release-environment'} 165 smallEnvChip={props.smallEnvChip} 166 /> 167 ))}{' '} 168 </div> 169 ); 170 };