• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / gui / 1113439055

19 Dec 2023 09:01PM UTC coverage: 82.752% (-17.2%) from 99.964%
1113439055

Pull #4258

gitlab-ci

mender-test-bot
chore: Types update

Signed-off-by: Mender Test Bot <mender@northern.tech>
Pull Request #4258: chore: Types update

4326 of 6319 branches covered (0.0%)

8348 of 10088 relevant lines covered (82.75%)

189.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/src/js/components/deployments/deployment-report/overview.js
1
// Copyright 2020 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14
import React from 'react';
15
import { Link } from 'react-router-dom';
16

17
import { Launch as LaunchIcon, ArrowDropDownCircleOutlined as ScrollDownIcon } from '@mui/icons-material';
18
import { Chip } from '@mui/material';
19
import { makeStyles } from 'tss-react/mui';
20

21
import pluralize from 'pluralize';
22
import isUUID from 'validator/lib/isUUID';
23

24
import failImage from '../../../../assets/img/largeFail.png';
25
import successImage from '../../../../assets/img/largeSuccess.png';
26
import { DEPLOYMENT_STATES, DEPLOYMENT_TYPES } from '../../../constants/deploymentConstants';
27
import { groupDeploymentStats, isEmpty } from '../../../helpers';
28
import { TwoColumnData } from '../../common/configurationobject';
29
import DeviceIdentityDisplay from '../../common/deviceidentity';
30
import Time from '../../common/time';
31
import { getDevicesLink } from '../deployment-wizard/softwaredevices';
32
import { defaultColumnDataProps } from '../report';
33

34
const useStyles = makeStyles()(theme => ({
10✔
35
  chip: {
36
    opacity: 0.5,
37
    fontSize: '0.675rem',
38
    height: 18
39
  },
40
  scheduleLink: {
41
    marginLeft: theme.spacing(12),
42
    '&svg': {
43
      marginLeft: theme.spacing()
44
    }
45
  },
46
  statusWrapper: {
47
    backgroundColor: theme.palette.background.lightgrey,
48
    ['&:after']: {
49
      borderRight: '20px solid',
50
      borderRightColor: theme.palette.background.lightgrey
51
    }
52
  }
53
}));
54

55
const defaultLinkProps = {
10✔
56
  className: 'flexbox centered',
57
  style: { fontWeight: '500' },
58
  target: '_blank',
59
  rel: 'noopener noreferrer'
60
};
61

62
export const DeploymentOverview = ({ creator, deployment, devicesById, onScheduleClick, tenantCapabilities }) => {
10✔
63
  const { classes } = useStyles();
6✔
64
  const {
65
    artifact_name,
66
    created: creationTime = new Date().toISOString(),
×
67
    devices = {},
×
68
    filter,
69
    group,
70
    name = '',
×
71
    status,
72
    totalDeviceCount,
73
    type = DEPLOYMENT_TYPES.software
6✔
74
  } = deployment;
6✔
75
  const { failures, successes } = groupDeploymentStats(deployment);
6✔
76
  const finished = deployment.finished || status === DEPLOYMENT_STATES.finished;
6✔
77
  const isDeviceDeployment = isUUID(name) && (isEmpty(devices) || Object.keys(devices).length === 1);
6!
78
  const isSoftwareDeployment = type === DEPLOYMENT_TYPES.software;
6✔
79
  const { hasFullFiltering } = tenantCapabilities;
6✔
80

81
  let deploymentRelease = (
82
    <Link {...defaultLinkProps} to={`/releases/${encodeURIComponent(artifact_name)}`}>
6✔
83
      {artifact_name}
84
      <LaunchIcon className="margin-left-small" fontSize="small" />
85
    </Link>
86
  );
87

88
  const devicesLink = getDevicesLink({
6✔
89
    devices: Object.values(devices),
90
    filters: filter?.filters,
91
    group: group || filter?.name,
11✔
92
    hasFullFiltering,
93
    name
94
  });
95
  let targetDevices = (
96
    <Link {...defaultLinkProps} to={devicesLink}>
6✔
97
      {isDeviceDeployment && devicesById[name] ? (
12!
98
        <DeviceIdentityDisplay device={devicesById[name]} isEditable={false} />
99
      ) : isUUID(name) ? (
6!
100
        Object.keys(devices).join(', ')
101
      ) : (
102
        name
103
      )}
104
      <LaunchIcon className="margin-left-small" fontSize="small" />
105
      <Chip className={`margin-left uppercased ${classes.chip}`} label={filter ? 'dynamic' : 'static'} size="small" />
6✔
106
    </Link>
107
  );
108

109
  if (!isSoftwareDeployment) {
6!
110
    deploymentRelease = type;
×
111
    targetDevices = Object.keys(devices).join(', ') || name;
×
112
  }
113

114
  const deploymentInfo = {
6✔
115
    'Release': deploymentRelease,
116
    'Target device(s)': targetDevices,
117
    'Category': isSoftwareDeployment ? 'Software update' : 'Configuration'
6!
118
  };
119
  const createdBy = creator ? { 'Created by': creator } : {};
6!
120
  const deploymentInfo2 = {
6✔
121
    ...createdBy,
122
    'Created at': <Time value={creationTime} />
123
  };
124

125
  return (
6✔
126
    <div className="report-container margin-top-large margin-bottom-large">
127
      <TwoColumnData config={deploymentInfo} {...defaultColumnDataProps} />
128
      <div className="flexbox column">
129
        <TwoColumnData config={deploymentInfo2} {...defaultColumnDataProps} />
130
        <a className={`margin-top-small flexbox center-aligned ${classes.scheduleLink}`} onClick={onScheduleClick}>
131
          Schedule details <ScrollDownIcon fontSize="small" />
132
        </a>
133
      </div>
134

135
      {finished && (
8✔
136
        <div className="statusLarge flexbox centered">
137
          <img src={successes ? successImage : failImage} />
2!
138
          <div className={`statusWrapper flexbox centered ${classes.statusWrapper}`}>
139
            <div className="statusWrapperMessage">
140
              {(!!successes || !failures) && (
6✔
141
                <>
142
                  <b className={successes ? 'green' : 'red'}>
2!
143
                    {successes === totalDeviceCount && totalDeviceCount > 1 && <>All </>}
2!
144
                    {successes}
145
                  </b>{' '}
146
                  {pluralize('devices', successes)} updated successfully
147
                </>
148
              )}
149
              {!!failures && (
2!
150
                <>
151
                  <b className="red">{failures}</b> {pluralize('devices', failures)} failed to update
152
                </>
153
              )}
154
            </div>
155
          </div>
156
        </div>
157
      )}
158
    </div>
159
  );
160
};
161

162
export default DeploymentOverview;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc