• 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.74
/src/js/components/settings/artifactgeneration.js
1
// Copyright 2022 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, useMemo, useRef, useState } from 'react';
15
import { useDispatch, useSelector } from 'react-redux';
16

17
// material ui
18
import { InfoOutlined as InfoOutlinedIcon } from '@mui/icons-material';
19
import { Checkbox, FormControlLabel, TextField, Typography, formControlLabelClasses, textFieldClasses } from '@mui/material';
20
import { makeStyles } from 'tss-react/mui';
21

22
import DeltaIcon from '../../../assets/img/deltaicon.svg';
23
import { getDeploymentsConfig, saveDeltaDeploymentsConfig } from '../../actions/deploymentActions';
24
import { BENEFITS, TIMEOUTS } from '../../constants/appConstants';
25
import { useDebounce } from '../../utils/debouncehook';
26
import EnterpriseNotification from '../common/enterpriseNotification';
27
import InfoText from '../common/infotext';
28
import Loader from '../common/loader';
29

30
const useStyles = makeStyles()(theme => ({
5✔
31
  deviceLimitBar: { backgroundColor: theme.palette.grey[500], margin: '15px 0' },
32
  wrapper: {
33
    backgroundColor: theme.palette.background.lightgrey,
34
    display: 'flex',
35
    flexDirection: 'column',
36
    marginTop: theme.spacing(6),
37
    padding: theme.spacing(2),
38
    paddingTop: 0,
39
    '&>h5': { marginTop: 0, marginBottom: 0 },
40
    '.flexbox>span': { alignSelf: 'flex-end' },
41
    [`.${textFieldClasses.root}`]: { maxWidth: 200, minWidth: 100 },
42
    [`.${formControlLabelClasses.root}`]: { marginTop: theme.spacing() }
43
  }
44
}));
45

46
const numberFields = {
5✔
47
  compressionLevel: { key: 'compressionLevel', title: 'Compression level' },
48
  sourceWindow: { key: 'sourceWindow', title: 'Source window size' },
49
  inputWindow: { key: 'inputWindow', title: 'Input window size' },
50
  duplicatesWindow: { key: 'duplicatesWindow', title: 'Compression duplicates window' },
51
  instructionBuffer: { key: 'instructionBuffer', title: 'Instruction buffer size' }
52
};
53

54
const NumberInputLimited = ({ limit, onChange, value: propsValue, ...remainder }) => {
5✔
55
  const [value, setValue] = useState(propsValue);
42✔
56
  const debouncedValue = useDebounce(value, TIMEOUTS.oneSecond);
42✔
57
  const { default: defaultValue, max, min } = limit;
42✔
58

59
  useEffect(() => {
42✔
60
    const minimum = Math.max(min, debouncedValue);
12✔
61
    const allowedValue = Math.min(max ?? minimum, minimum);
12✔
62
    if (allowedValue !== debouncedValue) {
12✔
63
      setValue(allowedValue);
6✔
64
      return;
6✔
65
    }
66
    onChange(allowedValue);
6✔
67
  }, [debouncedValue, max, min, onChange]);
68

69
  return (
42✔
70
    <TextField
71
      inputProps={{ step: 1, type: 'numeric', pattern: '[0-9]*', autoComplete: 'off' }}
72
      InputLabelProps={{ shrink: true }}
73
      error={min || max ? min > value || value > max : false}
156✔
74
      value={value}
75
      onChange={({ target: { value } }) => setValue(Number(value) || 0)}
×
76
      helperText={defaultValue !== undefined ? `Defaults to: ${defaultValue}` : null}
42✔
77
      {...remainder}
78
    />
79
  );
80
};
81

82
export const ArtifactGenerationSettings = () => {
5✔
83
  const { binaryDelta: deltaConfig = {}, binaryDeltaLimits: deltaLimits = {}, hasDelta: deltaEnabled } = useSelector(state => state.deployments.config) ?? {};
12!
84
  const dispatch = useDispatch();
8✔
85
  const [timeoutValue, setTimeoutValue] = useState(deltaConfig.timeout);
8✔
86
  const [disableChecksum, setDisableChecksum] = useState(deltaConfig.disableChecksum);
8✔
87
  const [disableDecompression, setDisableDecompression] = useState(deltaConfig.disableChecksum);
8✔
88
  const [compressionLevel, setCompressionLevel] = useState(deltaConfig.compressionLevel);
8✔
89
  const [sourceWindow, setSourceWindow] = useState(deltaConfig.sourceWindow);
8✔
90
  const [inputWindow, setInputWindow] = useState(deltaConfig.inputWindow);
8✔
91
  const [duplicatesWindow, setDuplicatesWindow] = useState(deltaConfig.duplicatesWindow);
8✔
92
  const [instructionBuffer, setInstructionBuffer] = useState(deltaConfig.instructionBuffer);
8✔
93
  const isInitialized = useRef(false);
8✔
94

95
  const { classes } = useStyles();
8✔
96

97
  useEffect(() => {
8✔
98
    dispatch(getDeploymentsConfig());
1✔
99
  }, [dispatch]);
100

101
  useEffect(() => {
8✔
102
    if (deltaConfig.timeout === -1) {
2!
103
      return;
×
104
    }
105
    const { timeout, duplicatesWindow, compressionLevel, disableChecksum, disableDecompression, inputWindow, instructionBuffer, sourceWindow } = deltaConfig;
2✔
106
    setDisableChecksum(disableChecksum);
2✔
107
    setDisableDecompression(disableDecompression);
2✔
108
    setCompressionLevel(compressionLevel);
2✔
109
    setTimeoutValue(timeout);
2✔
110
    setSourceWindow(sourceWindow);
2✔
111
    setInputWindow(inputWindow);
2✔
112
    setDuplicatesWindow(duplicatesWindow);
2✔
113
    setInstructionBuffer(instructionBuffer);
2✔
114
    setTimeout(() => (isInitialized.current = true), TIMEOUTS.fiveSeconds);
2✔
115
    // eslint-disable-next-line react-hooks/exhaustive-deps
116
  }, [JSON.stringify(deltaConfig), JSON.stringify(deltaLimits)]);
117

118
  const debouncedConfig = useDebounce(
8✔
119
    {
120
      timeout: timeoutValue,
121
      duplicatesWindow,
122
      compressionLevel,
123
      disableChecksum,
124
      disableDecompression,
125
      inputWindow,
126
      instructionBuffer,
127
      sourceWindow
128
    },
129
    TIMEOUTS.threeSeconds
130
  );
131

132
  useEffect(() => {
8✔
133
    if (!isInitialized.current) {
1!
134
      return;
1✔
135
    }
136
    dispatch(saveDeltaDeploymentsConfig(debouncedConfig));
×
137
    // eslint-disable-next-line react-hooks/exhaustive-deps
138
  }, [dispatch, JSON.stringify(debouncedConfig)]);
139

140
  const numberInputs = useMemo(() => {
8✔
141
    return [
3✔
142
      { ...numberFields.compressionLevel, setter: setCompressionLevel, value: compressionLevel, ...deltaLimits.compressionLevel },
143
      { ...numberFields.sourceWindow, setter: setSourceWindow, value: sourceWindow, ...deltaLimits.sourceWindow },
144
      { ...numberFields.inputWindow, setter: setInputWindow, value: inputWindow, ...deltaLimits.inputWindow },
145
      { ...numberFields.duplicatesWindow, setter: setDuplicatesWindow, value: duplicatesWindow, ...deltaLimits.duplicatesWindow },
146
      { ...numberFields.instructionBuffer, setter: setInstructionBuffer, value: instructionBuffer, ...deltaLimits.instructionBuffer }
147
    ];
148
    // eslint-disable-next-line react-hooks/exhaustive-deps
149
  }, [
150
    compressionLevel,
151
    setCompressionLevel,
152
    setSourceWindow,
153
    sourceWindow,
154
    inputWindow,
155
    setInputWindow,
156
    setDuplicatesWindow,
157
    duplicatesWindow,
158
    setInstructionBuffer,
159
    instructionBuffer,
160
    // eslint-disable-next-line react-hooks/exhaustive-deps
161
    JSON.stringify(deltaLimits)
162
  ]);
163

164
  return (
8✔
165
    <div className={`flexbox column ${classes.wrapper}`}>
166
      <div className="flexbox center-aligned">
167
        <DeltaIcon />
168
        <h5 className="margin-left-small">Delta artifacts generation configuration</h5>
169
        <EnterpriseNotification className="margin-left-small" id={BENEFITS.deltaGeneration.id} />
170
      </div>
171
      {deltaEnabled ? (
8!
172
        <>
173
          {isInitialized.current ? (
8✔
174
            <div className="margin-small margin-top-none">
175
              <div className="flexbox">
176
                <NumberInputLimited
177
                  limit={{ default: deltaLimits.timeout.default, min: deltaLimits.timeout.min, max: deltaLimits.timeout.max }}
178
                  label="Timeout"
179
                  onChange={setTimeoutValue}
180
                  value={timeoutValue}
181
                />
182
                <span className="margin-left-small muted slightly-smaller">seconds</span>
183
              </div>
184
              <Typography className="margin-top-small" display="block" variant="caption">
185
                xDelta3 arguments
186
              </Typography>
187
              <div className="flexbox column margin-left">
188
                <FormControlLabel
189
                  control={
190
                    <Checkbox color="primary" checked={disableChecksum} onChange={({ target: { checked } }) => setDisableChecksum(checked)} size="small" />
×
191
                  }
192
                  label="Disable checksum"
193
                />
194
                <FormControlLabel
195
                  control={
196
                    <Checkbox
197
                      color="primary"
198
                      checked={disableDecompression}
199
                      onChange={({ target: { checked } }) => setDisableDecompression(checked)}
×
200
                      size="small"
201
                    />
202
                  }
203
                  label="Disable external decompression"
204
                />
205
                {numberInputs.map(({ default: defaultValue, key, setter, title, value, min = 0, max }) => (
5✔
206
                  <NumberInputLimited key={key} limit={{ default: defaultValue, max, min }} label={title} value={value} onChange={setter} />
25✔
207
                ))}
208
              </div>
209
            </div>
210
          ) : (
211
            <Loader show />
212
          )}
213
        </>
214
      ) : (
215
        <InfoText>
216
          <InfoOutlinedIcon style={{ fontSize: 14, margin: '0 4px 4px 0', verticalAlign: 'middle' }} />
217
          Automatic delta artifacts generation is not enabled in your account. If you want to start using this feature,{' '}
218
          <a href="mailto:support@mender.io" target="_blank" rel="noopener noreferrer">
219
            contact our team
220
          </a>
221
          .
222
        </InfoText>
223
      )}
224
    </div>
225
  );
226
};
227

228
export default ArtifactGenerationSettings;
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