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                  &nbsp;
    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  };