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

mendersoftware / gui / 963002358

pending completion
963002358

Pull #3870

gitlab-ci

mzedel
chore: cleaned up left over onboarding tooltips & aligned with updated design

Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #3870: MEN-5413

4348 of 6319 branches covered (68.81%)

95 of 122 new or added lines in 24 files covered. (77.87%)

1734 existing lines in 160 files now uncovered.

8174 of 9951 relevant lines covered (82.14%)

178.12 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);
274✔
35
  const { classes } = useStyles();
274✔
36

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

41
  return (
274✔
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, isEnterprise, setDeploymentSettings }) => {
12✔
66
  const { phases = [], release = {} } = deploymentObject;
274✔
67
  const { classes } = useStyles();
274✔
68

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

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

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

79
  return (
274✔
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 disabled={phases.length > 1 || !isEnterprise} onStepChange={onStepChangeClick} release={release} steps={states} />
503✔
92
      </Collapse>
93
      <EnterpriseNotification isEnterprise={isEnterprise} benefit="granular control about update rollout to allow synchronization across your fleet" />
94
    </>
95
  );
96
};
97

98
export const Retries = ({
12✔
99
  canRetry,
100
  commonClasses,
101
  deploymentObject,
102
  hasNewRetryDefault = false,
2✔
103
  onSaveRetriesSetting,
104
  previousRetries,
105
  setDeploymentSettings
106
}) => {
107
  const { retries } = deploymentObject;
276✔
108
  const { classes } = useStyles();
276✔
109

110
  const [currentAttempts, setCurrentAttempts] = useState(Number(retries ?? previousRetries ?? 0) + 1);
276!
111
  const debouncedAttempts = useDebounce(currentAttempts, TIMEOUTS.debounceShort);
276✔
112

113
  useEffect(() => {
276✔
114
    setDeploymentSettings({ retries: Number(debouncedAttempts) - 1 });
7✔
115
  }, [debouncedAttempts, setDeploymentSettings]);
116

117
  const formatValue = value => {
276✔
118
    const newValue = Math.max(0, Math.min(value, 100));
594✔
119
    return newValue ? `${newValue}` : '';
594✔
120
  };
121

122
  const onInputChange = (e, value, reason) => {
276✔
123
    if (reason === 'clear') {
7!
UNCOV
124
      return setDeploymentSettings({ retries: 0 });
×
125
    } else if ((reason === 'reset' && !e) || reason === 'blur') {
7✔
126
      return;
6✔
127
    }
128
    setCurrentAttempts(formatValue(value));
1✔
129
  };
130

131
  const onSaveRetriesSettingClick = (_, checked) => onSaveRetriesSetting(checked);
276✔
132

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