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

mendersoftware / gui / 988636826

01 Sep 2023 04:04AM UTC coverage: 82.384% (-17.6%) from 99.964%
988636826

Pull #3969

gitlab-ci

web-flow
chore: Bump autoprefixer from 10.4.14 to 10.4.15

Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.14 to 10.4.15.
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.14...10.4.15)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #3969: chore: Bump autoprefixer from 10.4.14 to 10.4.15

4346 of 6321 branches covered (0.0%)

8259 of 10025 relevant lines covered (82.38%)

192.73 hits per line

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

79.69
/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
export const timeout = 900000; // 15 minutes idle time
2✔
46
const cookies = new Cookies();
2✔
47

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

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

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

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

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

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

101
  const trackLocationChange = useCallback(
28✔
102
    pathname => {
103
      let page = pathname;
5✔
104
      // if we're on page whose path might contain sensitive device/ group/ deployment names etc. we sanitize the sent information before submission
105
      if (page.includes('=') && (page.startsWith('/devices') || page.startsWith('/deployments'))) {
5!
106
        const splitter = page.lastIndexOf('/');
×
107
        const filters = page.slice(splitter + 1);
×
108
        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
×
109
        page = `${page.substring(0, splitter)}?${keyOnlyFilters.substring(0, keyOnlyFilters.length - 1)}`; // cut off the last & of the reduced filters string
×
110
      } else if (page.startsWith(activationPath)) {
5!
111
        dispatch(setAccountActivationCode(page.substring(activationPath.length + 1)));
×
112
        navigate('/settings/my-profile', { replace: true });
×
113
      }
114
      Tracking.pageview(page);
5✔
115
    },
116
    [dispatch, navigate]
117
  );
118

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

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

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

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

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

160
  const onToggleSearchResult = () => setShowSearchResult(toggle);
28✔
161

162
  const theme = createTheme(isDarkMode(mode) ? darkTheme : lightTheme);
28!
163

164
  const { classes } = useStyles();
28✔
165

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

196
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