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

mendersoftware / gui / 901187442

pending completion
901187442

Pull #3795

gitlab-ci

mzedel
feat: increased chances of adopting our intended navigation patterns instead of unsupported browser navigation

Ticket: None
Changelog: None
Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #3795: feat: increased chances of adopting our intended navigation patterns instead of unsupported browser navigation

4389 of 6365 branches covered (68.96%)

5 of 5 new or added lines in 1 file covered. (100.0%)

1729 existing lines in 165 files now uncovered.

8274 of 10019 relevant lines covered (82.58%)

144.86 hits per line

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

89.89
/src/js/components/deployments/deploymentitem.js
1
// Copyright 2019 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, { useEffect, useState } from 'react';
15
import { useDispatch } from 'react-redux';
16

17
// material ui
18
import { CancelOutlined as CancelOutlinedIcon } from '@mui/icons-material';
19
import { Button, IconButton, Tooltip } from '@mui/material';
20
import { makeStyles } from 'tss-react/mui';
21

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

24
import { getDeviceById } from '../../actions/deviceActions';
25
import { DEPLOYMENT_STATES, DEPLOYMENT_TYPES } from '../../constants/deploymentConstants';
26
import { FileSize, getDeploymentState } from '../../helpers';
27
import Confirm from '../common/confirm';
28
import { RelativeTime } from '../common/time';
29
import { PhaseProgressDisplay } from './deployment-report/phaseprogress';
30
import { getDeploymentTargetText } from './deployment-wizard/softwaredevices';
31
import DeploymentStats from './deploymentstatus';
32
import ProgressDisplay, { DeploymentStatusNotification } from './progressChart';
33

34
export const deploymentTypeClasses = {
12✔
35
  [DEPLOYMENT_STATES.finished]: 'past-item',
36
  [DEPLOYMENT_STATES.pending]: 'pending-item',
37
  [DEPLOYMENT_STATES.inprogress]: 'progress-item',
38
  [DEPLOYMENT_STATES.scheduled]: 'scheduled-item'
39
};
40

41
export const DeploymentDeviceCount = ({ className, deployment }) => (
12✔
42
  <div className={className} key="DeploymentDeviceCount">
890✔
43
    {Math.max(deployment.device_count || 0, deployment.max_devices || 0)}
2,677✔
44
  </div>
45
);
46
export const DeploymentDeviceGroup = ({ deployment, devicesById, idAttribute, wrappingClass }) => {
12✔
47
  const deploymentName = getDeploymentTargetText({ deployment, devicesById, idAttribute });
3,161✔
48
  return (
3,161✔
49
    <div className={wrappingClass} key="DeploymentDeviceGroup" title={deploymentName}>
50
      {deploymentName}
51
    </div>
52
  );
53
};
54
export const DeploymentEndTime = ({ deployment }) => <RelativeTime key="DeploymentEndTime" updateTime={deployment.finished} shouldCount="none" />;
890✔
55
export const DeploymentPhases = ({ deployment }) => <div key="DeploymentPhases">{deployment.phases ? deployment.phases.length : '-'}</div>;
12!
56
export const DeploymentProgress = ({ deployment, minimal = false }) => {
12✔
57
  const { phases = [], update_control_map } = deployment;
1,577✔
58
  const status = getDeploymentState(deployment);
1,577✔
59
  if (status === 'queued') {
1,577✔
60
    return <DeploymentStatusNotification status={status} />;
787✔
61
  } else if (phases.length > 1 || !update_control_map) {
790!
62
    return <ProgressDisplay key="DeploymentProgress" deployment={deployment} status={status} minimal={minimal} />;
790✔
63
  }
UNCOV
64
  return <PhaseProgressDisplay key="DeploymentProgress" deployment={deployment} status={status} minimal={minimal} />;
×
65
};
66
export const DeploymentRelease = ({ deployment: { artifact_name, type = DEPLOYMENT_TYPES.software }, wrappingClass }) => {
12✔
67
  const deploymentRelease = type === DEPLOYMENT_TYPES.configuration ? type : artifact_name;
890!
68
  return (
890✔
69
    <div className={wrappingClass} key="DeploymentRelease" title={deploymentRelease}>
70
      {deploymentRelease}
71
    </div>
72
  );
73
};
74
export const DeploymentStartTime = ({ direction = 'both', started }) => <RelativeTime key="DeploymentStartTime" updateTime={started} shouldCount={direction} />;
890✔
75

76
export const DeploymentStatus = ({ deployment }) => <DeploymentStats key="DeploymentStatus" deployment={deployment} />;
68✔
77

78
export const DeploymentSize = ({ deployment: { total_size } }) => <div className="align-right">{total_size ? <FileSize fileSize={total_size} /> : '-'}</div>;
68!
79

80
const useStyles = makeStyles()(theme => ({
25✔
81
  detailsButton: {
82
    backgroundColor: 'transparent',
83
    color: theme.palette.text.primary,
84
    justifySelf: 'center',
85
    textTransform: 'none',
86
    [`&:hover`]: {
87
      backgroundColor: 'transparent',
88
      color: theme.palette.text.primary
89
    }
90
  },
91
  textWrapping: { whiteSpace: 'initial' }
92
}));
93

94
export const DeploymentItem = ({
12✔
95
  abort: abortDeployment,
96
  canConfigure,
97
  canDeploy,
98
  columnHeaders,
99
  deployment,
100
  devices,
101
  idAttribute,
102
  isEnterprise,
103
  openReport,
104
  type
105
}) => {
106
  const [abort, setAbort] = useState(null);
890✔
107

108
  const { classes } = useStyles();
890✔
109
  const dispatch = useDispatch();
890✔
110

111
  useEffect(() => {
890✔
112
    if (isUUID(deployment.name) && !devices[deployment.name]) {
25!
UNCOV
113
      dispatch(getDeviceById(deployment.name));
×
114
    }
115
  }, [deployment.name]);
116

117
  const toggleConfirm = id => {
890✔
118
    setTimeout(() => setAbort(abort ? null : id), 150);
2✔
119
  };
120
  const { created, id, phases } = deployment;
890✔
121

122
  let confirmation;
123
  if (abort === id) {
890✔
124
    confirmation = <Confirm classes="flexbox centered confirmation-overlay" cancel={() => toggleConfirm(id)} action={() => abortDeployment(id)} type="abort" />;
5✔
125
  }
126
  const started = isEnterprise && phases?.length >= 1 ? phases[0].start_ts || created : created;
890✔
127
  const wrappingClass = `text-overflow ${type === DEPLOYMENT_STATES.inprogress ? classes.textWrapping : ''}`;
890✔
128
  return (
890✔
129
    <div className={`deployment-item ${deploymentTypeClasses[type]}`}>
130
      {!!confirmation && confirmation}
895✔
131
      {columnHeaders.map((column, i) => {
132
        const ColumnComponent = column.renderer;
5,408✔
133
        return (
5,408✔
134
          <div className={column.class} key={`deploy-item-${i}`}>
135
            {column.title && <span className="deployment-item-title muted">{column.title}</span>}
10,816✔
136
            <ColumnComponent
137
              className={column.class || ''}
9,926✔
138
              idAttribute={idAttribute}
139
              deployment={deployment}
140
              devicesById={devices}
141
              started={started}
142
              wrappingClass={wrappingClass}
143
              {...column.props}
144
            />
145
          </div>
146
        );
147
      })}
148
      <Button className={classes.detailsButton} variant="contained" onClick={() => openReport(type, deployment.id)}>
1✔
149
        View details
150
      </Button>
151
      {(canDeploy || (canConfigure && deployment.type === DEPLOYMENT_TYPES.configuration)) && type !== DEPLOYMENT_STATES.finished && (
2,599!
152
        <Tooltip className="columnHeader" title="Abort" placement="top-start">
153
          <IconButton onClick={() => toggleConfirm(id)} size="large">
1✔
154
            <CancelOutlinedIcon className="cancelButton muted" />
155
          </IconButton>
156
        </Tooltip>
157
      )}
158
    </div>
159
  );
160
};
161

162
export default DeploymentItem;
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