• 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

90.16
/src/js/components/deployments/deployment-wizard/rolloutoptions.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, { useEffect, useState } from 'react';
15

16
import { Autocomplete, Checkbox, Collapse, FormControl, FormControlLabel, FormGroup, TextField } from '@mui/material';
17
import { makeStyles } from 'tss-react/mui';
18

19
import { TIMEOUTS } from '../../../constants/appConstants';
20
import { toggle } from '../../../helpers';
21
import { useDebounce } from '../../../utils/debouncehook';
22
import EnterpriseNotification from '../../common/enterpriseNotification';
23
import MenderTooltip from '../../common/mendertooltip';
24
import RolloutSteps from './rolloutsteps';
25

26
const useStyles = makeStyles()(() => ({
18✔
27
  defaultBox: { marginTop: 0, marginBottom: -15 },
28
  heading: { marginBottom: 0 },
29
  retryInput: { maxWidth: 150, minWidth: 130 },
30
  wrapper: { minHeight: 300 }
31
}));
32

33
export const ForceDeploy = ({ deploymentObject, setDeploymentSettings }) => {
12✔
34
  const [forceDeploy, setForceDeploy] = useState(deploymentObject.forceDeploy ?? false);
255✔
35
  const { classes } = useStyles();
255✔
36

37
  useEffect(() => {
255✔
38
    setDeploymentSettings({ forceDeploy });
6✔
39
  }, [forceDeploy]);
40

41
  return (
255✔
42
    <div>
43
      <MenderTooltip
44
        title={
45
          <div style={{ whiteSpace: 'normal' }}>
46
            <h3>Force update</h3>
47
            <p>This will make the Mender client install the update even if the selected release is already installed.</p>
48
          </div>
49
        }
50
      >
51
        <FormControlLabel
52
          className={classes.heading}
UNCOV
53
          control={<Checkbox color="primary" checked={forceDeploy} onChange={() => setForceDeploy(toggle)} size="small" />}
×
54
          label={
55
            <>
56
              <b>Force update</b> (optional)
57
            </>
58
          }
59
        />
60
      </MenderTooltip>
61
    </div>
62
  );
63
};
64

65
export const RolloutOptions = ({ deploymentObject, docsVersion, isEnterprise, setDeploymentSettings }) => {
12✔
66
  const { phases = [], release = {} } = deploymentObject;
255✔
67
  const { classes } = useStyles();
255✔
68

69
  const { states = {} } = deploymentObject.update_control_map || {};
255✔
70
  const [isPaused, setIsPaused] = useState(!!Object.keys(states).length);
255✔
71

72
  const onStepChangeClick = step => {
255✔
UNCOV
73
    const { action } = step;
×
UNCOV
74
    setDeploymentSettings({ update_control_map: { states: { ...states, [step.state]: { action } } } });
×
75
  };
76

77
  const onIsPausedClick = () => setIsPaused(toggle);
255✔
78

79
  return (
255✔
80
    <>
81
      <FormControlLabel
82
        className={classes.heading}
83
        control={<Checkbox color="primary" checked={isPaused} disabled={!isEnterprise} onChange={onIsPausedClick} size="small" />}
84
        label={
85
          <>
86
            <b>Add pauses between update steps</b> (optional)
87
          </>
88
        }
89
      />
90
      <Collapse in={isPaused} className={classes.wrapper}>
91
        <RolloutSteps
92
          disabled={phases.length > 1 || !isEnterprise}
457✔
93
          docsVersion={docsVersion}
94
          isEnterprise={isEnterprise}
95
          onStepChange={onStepChangeClick}
96
          release={release}
97
          steps={states}
98
        />
99
      </Collapse>
100
      <EnterpriseNotification isEnterprise={isEnterprise} benefit="granular control about update rollout to allow synchronization across your fleet" />
101
    </>
102
  );
103
};
104

105
export const Retries = ({
12✔
106
  canRetry,
107
  commonClasses,
108
  deploymentObject,
109
  hasNewRetryDefault = false,
2✔
110
  onSaveRetriesSetting,
111
  previousRetries,
112
  setDeploymentSettings
113
}) => {
114
  const { retries } = deploymentObject;
257✔
115
  const { classes } = useStyles();
257✔
116

117
  const [currentAttempts, setCurrentAttempts] = useState(Number(retries ?? previousRetries ?? 0) + 1);
257!
118
  const debouncedAttempts = useDebounce(currentAttempts, TIMEOUTS.debounceShort);
257✔
119

120
  useEffect(() => {
257✔
121
    setDeploymentSettings({ retries: Number(debouncedAttempts) - 1 });
7✔
122
  }, [debouncedAttempts]);
123

124
  const formatValue = value => {
257✔
125
    const newValue = Math.max(0, Math.min(value, 100));
556✔
126
    return newValue ? `${newValue}` : '';
556✔
127
  };
128

129
  const onInputChange = (e, value, reason) => {
257✔
130
    if (reason === 'clear') {
7!
UNCOV
131
      return setDeploymentSettings({ retries: 0 });
×
132
    } else if ((reason === 'reset' && !e) || reason === 'blur') {
7✔
133
      return;
6✔
134
    }
135
    setCurrentAttempts(formatValue(value));
1✔
136
  };
137

138
  const onSaveRetriesSettingClick = (_, checked) => onSaveRetriesSetting(checked);
257✔
139

140
  return (
257✔
141
    <>
142
      <h4 className={`${classes.heading} ${canRetry ? '' : commonClasses.disabled}`}>
257✔
143
        Select the number of times each device will attempt to apply the update
144
      </h4>
145
      <FormControl className="margin-top-none" disabled={!canRetry}>
146
        <FormGroup row>
147
          <Autocomplete
148
            autoSelect
149
            autoHighlight
150
            className={`margin-right ${classes.retryInput}`}
151
            freeSolo
152
            disabled={!canRetry}
153
            getOptionLabel={formatValue}
154
            handleHomeEndKeys
155
            id="deployment-retries-selection"
156
            options={[1, 2, 3, 4]}
157
            onInputChange={onInputChange}
158
            renderInput={params => (
159
              <TextField
263✔
160
                {...params}
161
                className={classes.retryInput}
162
                inputProps={{ ...params.inputProps, value: formatValue(params.inputProps.value) }}
163
                InputProps={{ ...params.InputProps }}
164
                type="number"
165
              />
166
            )}
167
            value={currentAttempts}
168
          />
169
          <FormControlLabel
170
            className={classes.defaultBox}
171
            control={<Checkbox checked={hasNewRetryDefault} onChange={onSaveRetriesSettingClick} />}
172
            label="Save as default"
173
          />
174
        </FormGroup>
175
      </FormControl>
176
      <EnterpriseNotification isEnterprise={canRetry} benefit="optional retries for failed rollout attempts" />
177
    </>
178
  );
179
};
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