• 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

88.46
/src/js/components/deployments/deployment-wizard/rolloutsteps.js
1
// Copyright 2021 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

16
import { Add as AddIcon, ArrowRight as ArrowRightIcon, PauseCircleOutline as PauseIcon } from '@mui/icons-material';
17
import { Chip } from '@mui/material';
18
import { makeStyles } from 'tss-react/mui';
19

20
import { TIMEOUTS } from '../../../constants/appConstants';
21
import InfoHint from '../../common/info-hint';
22
import InfoText from '../../common/infotext';
23
import MenderTooltip from '../../common/mendertooltip';
24

25
const useStyles = makeStyles()(theme => ({
36✔
26
  chip: { marginLeft: theme.spacing(-3), marginRight: theme.spacing(-3) },
27
  connector: {
28
    backgroundColor: theme.palette.text.secondary,
29
    height: 3,
30
    width: '100%',
31
    marginRight: theme.spacing(-1),
32
    '& svg': { color: theme.palette.text.secondary }
33
  },
34
  connectorArrowWrapper: { height: theme.spacing(4), paddingLeft: theme.spacing(), width: '100%' },
35
  connectorWrapper: { minWidth: 120 },
36
  pauseConnector: { borderLeft: `${theme.palette.grey[500]} dashed 1px`, height: theme.spacing(6), margin: 4, marginTop: -10 },
37
  stepChip: { minWidth: theme.spacing(11) }
38
}));
39

40
const stepActions = {
13✔
41
  continue: 'continue',
42
  force_continue: 'force_continue',
43
  pause: 'pause',
44
  fail: 'fail'
45
};
46

47
const defaultStep = { action: stepActions.continue };
13✔
48

49
const defaultSteps = {
13✔
50
  ArtifactDownload: { ...defaultStep, title: 'Download', tooltip: 'The Artifact is downloaded (streamed) to the inactive partition.' },
51
  ArtifactInstall_Enter: {
52
    ...defaultStep,
53
    title: 'Install',
54
    tooltip: (
55
      <>
56
        For <b>operating system updates</b>, this means switching the <i>inactive</i> partition on the device to be <i>active</i> next time the device reboots.
57
        This means that on the next reboot the device will boot the updated software, regardless if it was rebooted by Mender, an external process or due to
58
        power loss.
59
        <br />
60
        For <b>application updates</b>, it depends on the Update Module but in general refers to the <i>system changing</i> effects; e.g. writing a file to its
61
        location, running a script, installing or starting a container.
62
      </>
63
    ),
64
    state: 'ArtifactInstall_Enter'
65
  },
66
  ArtifactReboot_Enter: {
67
    ...defaultStep,
68
    title: 'Reboot',
69
    tooltip:
70
      'The device will reboot and the installed update will be active when the device boots up again. As changes are not yet committed, the update is not persistent and the device will still roll back again on the next reboot.',
71
    state: 'ArtifactReboot_Enter'
72
  },
73
  ArtifactCommit_Enter: {
74
    ...defaultStep,
75
    title: 'Commit',
76
    tooltip:
77
      'If the update passes integrity checks, Mender will mark the update as successful and continue running from this partition. The commit makes the update persistent.',
78
    state: 'ArtifactCommit_Enter'
79
  }
80
};
81

82
const menderDemoArtifactName = 'mender-demo-artifact';
13✔
83

84
export const RolloutStepConnector = ({ disabled, step, onStepChange, release = {} }) => {
13✔
85
  const { classes } = useStyles();
774✔
86
  const onTogglePauseClick = () => {
774✔
UNCOV
87
    onStepChange({ ...step, action: step.action === stepActions.pause ? stepActions.continue : stepActions.pause });
×
88
  };
89

90
  let stepModifier = { props: {}, toggleButton: undefined };
774✔
91
  if (onStepChange) {
774✔
92
    stepModifier.props = { onDelete: onTogglePauseClick };
768✔
93
    stepModifier.toggleButton = <Chip className={classes.chip} icon={<AddIcon />} label="Add a pause" color="primary" onClick={onTogglePauseClick} />;
768✔
94
  }
95

96
  const pauseChip = <Chip className={classes.chip} icon={<PauseIcon />} label="Pause" {...stepModifier.props} />;
774✔
97
  const stepPauseChip =
98
    step.state === defaultSteps.ArtifactReboot_Enter.state && release.Name?.includes(menderDemoArtifactName) ? (
774!
99
      <MenderTooltip
100
        arrow
101
        leaveDelay={TIMEOUTS.oneSecond}
102
        placement="top"
103
        title="The demo artifact you selected does not require a reboot and will not pause before starting with the next stage."
104
      >
105
        {pauseChip}
106
      </MenderTooltip>
107
    ) : (
108
      pauseChip
109
    );
110

111
  return (
774✔
112
    <div className={`flexbox column center-aligned ${classes.connectorWrapper}`}>
113
      <div className={`flexbox centered ${classes.connectorArrowWrapper}`}>
114
        <div className={classes.connector} />
115
        <ArrowRightIcon fontSize="small" />
116
      </div>
117
      {!disabled && (
1,140✔
118
        <>
119
          {(onStepChange || step.action === stepActions.pause) && <div className={classes.pauseConnector} />}
732✔
120
          {step.action === stepActions.pause ? stepPauseChip : stepModifier.toggleButton}
366!
121
        </>
122
      )}
123
    </div>
124
  );
125
};
126

127
export const RolloutSteps = ({ disabled, onStepChange, release, steps = {} }) => {
13!
128
  const { classes } = useStyles();
258✔
129
  const mappableSteps = Object.entries(defaultSteps).reduce((accu, [key, step]) => [...accu, { ...step, ...steps[key] }], []);
1,032✔
130

131
  return (
258✔
132
    <div className={`flexbox margin-top ${onStepChange ? 'margin-left-large margin-right-large' : ''}`}>
258✔
133
      {mappableSteps.map((step, index) => (
134
        <React.Fragment key={step.title}>
1,032✔
135
          {index !== 0 && <RolloutStepConnector disabled={disabled} step={step} onStepChange={onStepChange} release={release} />}
1,806✔
136
          <MenderTooltip title={step.tooltip} arrow>
137
            <Chip className={classes.stepChip} disabled={disabled} label={step.title} variant="outlined" />
138
          </MenderTooltip>
139
        </React.Fragment>
140
      ))}
141
    </div>
142
  );
143
};
144

145
export const RolloutStepsContainer = ({ className = '', disabled, docsVersion, onStepChange, release, steps }) => (
13✔
146
  <div className={className}>
258✔
147
    <div className={disabled ? 'muted' : ''}>
258✔
148
      <RolloutSteps disabled={disabled} onStepChange={onStepChange} release={release} steps={steps} />
149
      {onStepChange && !disabled && (
635✔
150
        <InfoText>
151
          A &apos;pause&apos; means each device will pause its update after completing the previous step, and wait for approval before continuing. You can grant
152
          approval by clicking &quot;continue&quot; in the deployment progress UI.{' '}
153
          <a href={`https://docs.mender.io/${docsVersion}`} target="_blank" rel="noopener noreferrer">
154
            Learn more
155
          </a>
156
        </InfoText>
157
      )}
158
    </div>
159
    {disabled && (
394✔
160
      <InfoHint
161
        content={
162
          <>
163
            This feature is not available on <b>phased deployments</b>. If you&apos;d like to set pause states between update steps, go back and adjust the
164
            rollout schedule to a <b>single phase</b>.
165
          </>
166
        }
167
      />
168
    )}
169
  </div>
170
);
171

172
export default RolloutStepsContainer;
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