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

mendersoftware / gui / 1057181131

01 Nov 2023 04:10AM UTC coverage: 82.824% (-17.1%) from 99.964%
1057181131

Pull #4125

gitlab-ci

web-flow
chore: Bump axios from 1.5.1 to 1.6.0 in /tests/e2e_tests

Bumps [axios](https://github.com/axios/axios) from 1.5.1 to 1.6.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.5.1...v1.6.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #4125: chore: Bump axios from 1.5.1 to 1.6.0 in /tests/e2e_tests

4349 of 6284 branches covered (0.0%)

8313 of 10037 relevant lines covered (82.82%)

202.07 hits per line

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

84.62
/src/js/components/deployments/deployments.js
1
// Copyright 2015 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

15
/* eslint-disable react-hooks/exhaustive-deps */
16
import React, { useCallback, useEffect, useRef, useState } from 'react';
17
import { useDispatch, useSelector } from 'react-redux';
18
import { Link, useNavigate } from 'react-router-dom';
19

20
import { Button, Tab, Tabs } from '@mui/material';
21

22
import { setSnackbar } from '../../actions/appActions';
23
import { abortDeployment, setDeploymentsState } from '../../actions/deploymentActions';
24
import { getDynamicGroups, getGroups } from '../../actions/deviceActions';
25
import { advanceOnboarding } from '../../actions/onboardingActions';
26
import { DEPLOYMENT_ROUTES, DEPLOYMENT_STATES, listDefaultsByState } from '../../constants/deploymentConstants';
27
import { ALL_DEVICES } from '../../constants/deviceConstants';
28
import { onboardingSteps } from '../../constants/onboardingConstants';
29
import { getISOStringBoundaries } from '../../helpers';
30
import { getDevicesById, getGroupsByIdWithoutUngrouped, getIsEnterprise, getOnboardingState, getReleasesById, getUserCapabilities } from '../../selectors';
31
import { useLocationParams } from '../../utils/liststatehook';
32
import { getOnboardingComponentFor } from '../../utils/onboardingmanager';
33
import useWindowSize from '../../utils/resizehook';
34
import CreateDeployment from './createdeployment';
35
import Progress from './inprogressdeployments';
36
import Past from './pastdeployments';
37
import Report from './report';
38
import Scheduled from './scheduleddeployments';
39

40
const routes = {
7✔
41
  [DEPLOYMENT_ROUTES.active.key]: {
42
    ...DEPLOYMENT_ROUTES.active,
43
    component: Progress
44
  },
45
  [DEPLOYMENT_ROUTES.scheduled.key]: {
46
    ...DEPLOYMENT_ROUTES.scheduled,
47
    component: Scheduled
48
  },
49
  [DEPLOYMENT_ROUTES.finished.key]: {
50
    ...DEPLOYMENT_ROUTES.finished,
51
    component: Past
52
  }
53
};
54

55
export const defaultRefreshDeploymentsLength = 30000;
7✔
56

57
export const Deployments = () => {
7✔
58
  const groupsById = useSelector(getGroupsByIdWithoutUngrouped);
209✔
59
  const devicesById = useSelector(getDevicesById);
208✔
60
  const isEnterprise = useSelector(getIsEnterprise);
208✔
61
  const onboardingState = useSelector(getOnboardingState);
208✔
62
  const pastCount = useSelector(state => state.deployments.byStatus.finished.total);
499✔
63
  const releases = useSelector(getReleasesById);
208✔
64
  const selectionState = useSelector(state => state.deployments.selectionState);
499✔
65
  const userCapabilities = useSelector(getUserCapabilities);
208✔
66
  const dispatch = useDispatch();
208✔
67

68
  const [deploymentObject, setDeploymentObject] = useState({});
208✔
69
  // eslint-disable-next-line no-unused-vars
70
  const size = useWindowSize();
208✔
71
  const tabsRef = useRef();
208✔
72
  const isInitialized = useRef(false);
208✔
73
  const navigate = useNavigate();
208✔
74
  const { reportType, showCreationDialog: createDialog, showReportDialog: reportDialog, state } = selectionState.general;
208✔
75
  const { canDeploy, canReadReleases } = userCapabilities;
208✔
76

77
  const [date] = useState(getISOStringBoundaries(new Date()));
208✔
78
  const { start: today, end: tonight } = date;
208✔
79

80
  const [locationParams, setLocationParams] = useLocationParams('deployments', { today, tonight, defaults: listDefaultsByState });
208✔
81

82
  useEffect(() => {
208✔
83
    if (!isInitialized.current) {
69✔
84
      return;
5✔
85
    }
86
    setLocationParams({ deploymentObject, pageState: selectionState });
64✔
87
  }, [
88
    JSON.stringify(deploymentObject),
89
    selectionState.selectedId,
90
    selectionState.general.state,
91
    selectionState.general.showCreationDialog,
92
    selectionState.general.showReportDialog,
93
    selectionState.general.reportType,
94
    selectionState[DEPLOYMENT_STATES.finished].endDate,
95
    selectionState[DEPLOYMENT_STATES.finished].search,
96
    selectionState[DEPLOYMENT_STATES.finished].startDate,
97
    selectionState[DEPLOYMENT_STATES.finished].page,
98
    selectionState[DEPLOYMENT_STATES.finished].perPage,
99
    selectionState[DEPLOYMENT_STATES.finished].type,
100
    selectionState[DEPLOYMENT_STATES.inprogress].page,
101
    selectionState[DEPLOYMENT_STATES.inprogress].perPage,
102
    selectionState[DEPLOYMENT_STATES.pending].page,
103
    selectionState[DEPLOYMENT_STATES.pending].perPage,
104
    setLocationParams
105
  ]);
106

107
  useEffect(() => {
208✔
108
    dispatch(getGroups());
5✔
109
    if (isEnterprise) {
5✔
110
      dispatch(getDynamicGroups());
2✔
111
    }
112
    const { deploymentObject = {}, id: selectedId = [], ...remainder } = locationParams;
5!
113
    const { devices: selectedDevices = [], release: releaseName } = deploymentObject;
5✔
114
    const release = releaseName ? { ...(releases[releaseName] ?? { name: releaseName }) } : undefined;
5!
115
    const devices = selectedDevices.length ? selectedDevices.map(device => ({ ...device, ...devicesById[device.id] })) : [];
5!
116
    setDeploymentObject({ devices, release, releaseSelectionLocked: !!release });
5✔
117
    dispatch(setDeploymentsState({ selectedId: selectedId[0], ...remainder }));
5✔
118
    isInitialized.current = true;
5✔
119
  }, [dispatch, isEnterprise]);
120

121
  const retryDeployment = (deployment, deploymentDeviceIds) => {
208✔
122
    const { artifact_name, name, update_control_map = {} } = deployment;
×
123
    const release = releases[artifact_name];
×
124
    const enterpriseSettings = isEnterprise
×
125
      ? {
126
          phases: [{ batch_size: 100, start_ts: undefined, delay: 0 }],
127
          update_control_map: { states: update_control_map.states || {} }
×
128
        }
129
      : {};
130
    const targetDevicesConfig = name === ALL_DEVICES || groupsById[name] ? { group: name } : { devices: [devicesById[name]] };
×
131
    const deploymentObject = {
×
132
      deploymentDeviceIds,
133
      release,
134
      deploymentDeviceCount: deploymentDeviceIds.length,
135
      ...targetDevicesConfig,
136
      ...enterpriseSettings
137
    };
138
    setDeploymentObject(deploymentObject);
×
139
    dispatch(setDeploymentsState({ general: { showCreationDialog: true, showReportDialog: false } }));
×
140
  };
141

142
  const onScheduleSubmit = () => {
208✔
143
    dispatch(setDeploymentsState({ general: { showCreationDialog: false, showReportDialog: false } }));
2✔
144
    setDeploymentObject({});
2✔
145
    // successfully retrieved new deployment
146
    if (routes.active.key !== state) {
2✔
147
      navigate(routes.active.route);
1✔
148
      changeTab(undefined, routes.active.key);
1✔
149
    }
150
  };
151

152
  const onAbortDeployment = id =>
208✔
153
    dispatch(abortDeployment(id)).then(() => {
×
154
      dispatch(setDeploymentsState({ general: { showCreationDialog: false, showReportDialog: false } }));
×
155
      return Promise.resolve();
×
156
    });
157

158
  const changeTab = (_, tabIndex) => {
208✔
159
    dispatch(setDeploymentsState({ general: { state: tabIndex } }));
5✔
160
    dispatch(setSnackbar(''));
5✔
161
    if (pastCount && !onboardingState.complete) {
5!
162
      dispatch(advanceOnboarding(onboardingSteps.DEPLOYMENTS_PAST));
×
163
    }
164
  };
165

166
  const showReport = (reportType, selectedId) => {
208✔
167
    if (!onboardingState.complete) {
1!
168
      dispatch(advanceOnboarding(onboardingSteps.DEPLOYMENTS_INPROGRESS));
×
169
    }
170
    dispatch(setDeploymentsState({ general: { reportType, showCreationDialog: false, showReportDialog: true }, selectedId }));
1✔
171
  };
172

173
  const closeReport = () => dispatch(setDeploymentsState({ general: { reportType: undefined, showReportDialog: false }, selectedId: undefined }));
208✔
174

175
  const onCreationDismiss = () => {
208✔
176
    dispatch(setDeploymentsState({ general: { showCreationDialog: false } }));
1✔
177
    setDeploymentObject({});
1✔
178
  };
179

180
  const onCreationShow = () => dispatch(setDeploymentsState({ general: { showCreationDialog: true } }));
208✔
181

182
  const setDeploymentSettings = useCallback(change => setDeploymentObject(current => ({ ...current, ...change })), []);
208✔
183

184
  let onboardingComponent = null;
208✔
185
  // the pastCount prop is needed to trigger the rerender as the change in past deployments would otherwise not be noticed on this view
186
  if (pastCount && tabsRef.current && !reportDialog) {
208✔
187
    const tabs = tabsRef.current.getElementsByClassName('MuiTab-root');
163✔
188
    const finishedTab = tabs[tabs.length - 1];
163✔
189
    onboardingComponent = getOnboardingComponentFor(onboardingSteps.DEPLOYMENTS_PAST, onboardingState, {
163✔
190
      anchor: {
191
        left: tabsRef.current.offsetLeft + tabsRef.current.offsetWidth - finishedTab.offsetWidth / 2,
192
        top: tabsRef.current.parentElement.offsetTop + finishedTab.offsetHeight
193
      }
194
    });
195
  }
196

197
  const ComponentToShow = routes[state].component;
208✔
198
  return (
208✔
199
    <>
200
      <div className="margin-left-small margin-top" style={{ maxWidth: '80vw' }}>
201
        <div className="flexbox space-between">
202
          <Tabs value={state} onChange={changeTab} ref={tabsRef}>
203
            {Object.values(routes).map(route => (
204
              <Tab component={Link} key={route.route} label={route.title} to={route.route} value={route.key} />
624✔
205
            ))}
206
          </Tabs>
207
          {canDeploy && canReadReleases && (
624✔
208
            <Button color="secondary" variant="contained" onClick={onCreationShow} style={{ height: '100%' }}>
209
              Create a deployment
210
            </Button>
211
          )}
212
        </div>
213
        <ComponentToShow abort={onAbortDeployment} createClick={onCreationShow} openReport={showReport} isShowingDetails={reportDialog} />
214
      </div>
215
      {reportDialog && <Report abort={onAbortDeployment} onClose={closeReport} retry={retryDeployment} type={reportType} />}
211✔
216
      {createDialog && (
342✔
217
        <CreateDeployment
218
          open={createDialog}
219
          onDismiss={onCreationDismiss}
220
          deploymentObject={deploymentObject}
221
          onScheduleSubmit={onScheduleSubmit}
222
          setDeploymentSettings={setDeploymentSettings}
223
        />
224
      )}
225
      {!reportDialog && onboardingComponent}
413✔
226
    </>
227
  );
228
};
229

230
export default Deployments;
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