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

mendersoftware / gui / 1057188406

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

Pull #4134

gitlab-ci

web-flow
chore: Bump uuid from 9.0.0 to 9.0.1

Bumps [uuid](https://github.com/uuidjs/uuid) from 9.0.0 to 9.0.1.
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v9.0.0...v9.0.1)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #4134: chore: Bump uuid from 9.0.0 to 9.0.1

4349 of 6284 branches covered (0.0%)

8313 of 10037 relevant lines covered (82.82%)

200.97 hits per line

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

79.1
/src/js/components/app.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
import React, { useCallback, useEffect, useState } from 'react';
15
import { useIdleTimer, workerTimers } from 'react-idle-timer';
16
import { useDispatch, useSelector } from 'react-redux';
17
import { useLocation, useNavigate } from 'react-router-dom';
18

19
import { CssBaseline } from '@mui/material';
20
import { ThemeProvider, createTheme } from '@mui/material/styles';
21
import withStyles from '@mui/styles/withStyles';
22
import { makeStyles } from 'tss-react/mui';
23

24
import Cookies from 'universal-cookie';
25

26
import { parseEnvironmentInfo, setSnackbar } from '../actions/appActions';
27
import { logoutUser, setAccountActivationCode, setShowConnectingDialog } from '../actions/userActions';
28
import { expirySet, getToken, updateMaxAge } from '../auth';
29
import SharedSnackbar from '../components/common/sharedsnackbar';
30
import { PrivateRoutes, PublicRoutes } from '../config/routes';
31
import ErrorBoundary from '../errorboundary';
32
import { isDarkMode, toggle } from '../helpers';
33
import { getUserSettings } from '../selectors';
34
import { dark as darkTheme, light as lightTheme } from '../themes/Mender';
35
import Tracking from '../tracking';
36
import ConfirmDismissHelptips from './common/dialogs/confirmdismisshelptips';
37
import DeviceConnectionDialog from './common/dialogs/deviceconnectiondialog';
38
import Footer from './footer';
39
import Header from './header/header';
40
import LeftNav from './leftnav';
41
import SearchResult from './search-result';
42
import Uploads from './uploads';
43

44
const activationPath = '/activate';
2✔
45
const trackingBlacklist = [/\/password\/.+/i];
2✔
46
export const timeout = 900000; // 15 minutes idle time
2✔
47
const cookies = new Cookies();
2✔
48

49
const reducePalette =
50
  prefix =>
2✔
51
  (accu, [key, value]) => {
460✔
52
    if (value instanceof Object) {
2,000✔
53
      return {
440✔
54
        ...accu,
55
        ...Object.entries(value).reduce(reducePalette(`${prefix}-${key}`), {})
56
      };
57
    } else {
58
      accu[`${prefix}-${key}`] = value;
1,560✔
59
    }
60
    return accu;
1,560✔
61
  };
62

63
const cssVariables = ({ palette }) => {
2✔
64
  const muiVariables = Object.entries(palette).reduce(reducePalette('--mui'), {});
20✔
65
  return {
20✔
66
    '@global': {
67
      ':root': {
68
        ...muiVariables,
69
        '--mui-overlay': palette.grey[400]
70
      }
71
    }
72
  };
73
};
74

75
const WrappedBaseline = withStyles(cssVariables)(CssBaseline);
2✔
76

77
const useStyles = makeStyles()(() => ({
4✔
78
  public: {
79
    display: 'grid',
80
    gridTemplateRows: 'max-content 1fr max-content',
81
    height: '100vh',
82
    '.content': {
83
      alignSelf: 'center',
84
      justifySelf: 'center'
85
    }
86
  }
87
}));
88

89
export const AppRoot = () => {
2✔
90
  const [showSearchResult, setShowSearchResult] = useState(false);
28✔
91
  const navigate = useNavigate();
28✔
92
  const { pathname = '', hash } = useLocation();
28!
93

94
  const dispatch = useDispatch();
28✔
95
  const currentUser = useSelector(state => state.users.currentUser);
1,132✔
96
  const showDismissHelptipsDialog = useSelector(state => !state.onboarding.complete && state.onboarding.showTipsDialog);
1,132✔
97
  const showDeviceConnectionDialog = useSelector(state => state.users.showConnectDeviceDialog);
1,132✔
98
  const snackbar = useSelector(state => state.app.snackbar);
1,132✔
99
  const trackingCode = useSelector(state => state.app.trackerCode);
1,132✔
100
  const { mode } = useSelector(getUserSettings);
28✔
101

102
  const trackLocationChange = useCallback(
28✔
103
    pathname => {
104
      let page = pathname;
5✔
105
      // if we're on page whose path might contain sensitive device/ group/ deployment names etc. we sanitize the sent information before submission
106
      if (page.includes('=') && (page.startsWith('/devices') || page.startsWith('/deployments'))) {
5!
107
        const splitter = page.lastIndexOf('/');
×
108
        const filters = page.slice(splitter + 1);
×
109
        const keyOnlyFilters = filters.split('&').reduce((accu, item) => `${accu}:${item.split('=')[0]}&`, ''); // assume the keys to filter by are not as revealing as the values things are filtered by
×
110
        page = `${page.substring(0, splitter)}?${keyOnlyFilters.substring(0, keyOnlyFilters.length - 1)}`; // cut off the last & of the reduced filters string
×
111
      } else if (page.startsWith(activationPath)) {
5!
112
        dispatch(setAccountActivationCode(page.substring(activationPath.length + 1)));
×
113
        navigate('/settings/my-profile', { replace: true });
×
114
      } else if (trackingBlacklist.some(item => !!page.match(item))) {
5!
115
        return;
×
116
      }
117
      Tracking.pageview(page);
5✔
118
    },
119
    [dispatch, navigate]
120
  );
121

122
  useEffect(() => {
28✔
123
    dispatch(parseEnvironmentInfo());
4✔
124
    if (!trackingCode) {
4✔
125
      return;
2✔
126
    }
127
    if (!cookies.get('_ga')) {
2!
128
      Tracking.cookieconsent().then(({ trackingConsentGiven }) => {
×
129
        if (trackingConsentGiven) {
×
130
          Tracking.initialize(trackingCode);
×
131
          Tracking.pageview();
×
132
        }
133
      });
134
    } else {
135
      Tracking.initialize(trackingCode);
2✔
136
    }
137
  }, [dispatch, trackingCode]);
138

139
  useEffect(() => {
28✔
140
    if (!(trackingCode && cookies.get('_ga'))) {
4✔
141
      return;
2✔
142
    }
143
    trackLocationChange(pathname);
2✔
144
  }, [pathname, trackLocationChange, trackingCode]);
145

146
  useEffect(() => {
28✔
147
    trackLocationChange(pathname);
3✔
148
    // the following is added to ensure backwards capability for hash containing routes & links (e.g. /ui/#/devices => /ui/devices)
149
    if (hash) {
3!
150
      navigate(hash.substring(1));
×
151
    }
152
  }, [hash, navigate, pathname, trackLocationChange]);
153

154
  const onIdle = () => {
28✔
155
    if (expirySet() && currentUser) {
2✔
156
      // logout user and warn
157
      return dispatch(logoutUser('Your session has expired. You have been automatically logged out due to inactivity.')).catch(updateMaxAge);
1✔
158
    }
159
  };
160

161
  useIdleTimer({ crossTab: true, onAction: updateMaxAge, onActive: updateMaxAge, onIdle, syncTimers: 400, timeout, timers: workerTimers });
28✔
162

163
  const onToggleSearchResult = () => setShowSearchResult(toggle);
28✔
164

165
  const theme = createTheme(isDarkMode(mode) ? darkTheme : lightTheme);
28!
166

167
  const { classes } = useStyles();
28✔
168

169
  return (
28✔
170
    <ThemeProvider theme={theme}>
171
      <WrappedBaseline enableColorScheme />
172
      <>
173
        {getToken() ? (
28✔
174
          <div id="app">
175
            <Header mode={mode} />
176
            <LeftNav />
177
            <div className="rightFluid container">
178
              <ErrorBoundary>
179
                <SearchResult onToggleSearchResult={onToggleSearchResult} open={showSearchResult} />
180
                <PrivateRoutes />
181
              </ErrorBoundary>
182
            </div>
183
            {showDismissHelptipsDialog && <ConfirmDismissHelptips />}
21!
184
            {showDeviceConnectionDialog && <DeviceConnectionDialog onCancel={() => dispatch(setShowConnectingDialog(false))} />}
×
185
          </div>
186
        ) : (
187
          <div className={classes.public}>
188
            <PublicRoutes />
189
            <Footer />
190
          </div>
191
        )}
192
        <SharedSnackbar snackbar={snackbar} setSnackbar={message => dispatch(setSnackbar(message))} />
×
193
        <Uploads />
194
      </>
195
    </ThemeProvider>
196
  );
197
};
198

199
export default AppRoot;
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