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

mendersoftware / gui / 1015445845

25 Sep 2023 09:43AM UTC coverage: 82.537% (-17.4%) from 99.964%
1015445845

Pull #4028

gitlab-ci

mzedel
chore: aligned release retrieval with v2 api models

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

4355 of 6315 branches covered (0.0%)

184 of 206 new or added lines in 19 files covered. (89.32%)

1724 existing lines in 164 files now uncovered.

8323 of 10084 relevant lines covered (82.54%)

208.49 hits per line

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

89.36
/src/js/components/settings/settings.js
1
// Copyright 2017 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
import { useSelector } from 'react-redux';
16
import { Navigate, useParams } from 'react-router-dom';
17

18
// material ui
19
import { Payment as PaymentIcon } from '@mui/icons-material';
20

21
import { Elements } from '@stripe/react-stripe-js';
22

23
import { TIMEOUTS, canAccess } from '../../constants/appConstants';
24
import { versionCompare } from '../../helpers';
25
import { getCurrentUser, getFeatures, getOrganization, getTenantCapabilities, getUserCapabilities, getUserRoles, getVersionInformation } from '../../selectors';
26
import LeftNav from '../common/left-nav';
27
import SelfUserManagement from '../settings/user-management/selfusermanagement';
28
import UserManagement from '../settings/user-management/usermanagement';
29
import Global from './global';
30
import Integrations from './integrations';
31
import Organization from './organization/organization';
32
import Roles from './roles';
33
import Upgrade from './upgrade';
34

35
let stripePromise = null;
4✔
36

37
const sectionMap = {
4✔
38
  'global-settings': { component: Global, text: () => 'Global settings', canAccess },
1✔
39
  'my-profile': { component: SelfUserManagement, text: () => 'My profile', canAccess },
1✔
40
  'organization-and-billing': {
41
    component: Organization,
42
    text: () => 'Organization and billing',
1✔
43
    canAccess: ({ hasMultitenancy }) => hasMultitenancy
1✔
44
  },
45
  'user-management': {
46
    component: UserManagement,
47
    text: () => 'User management',
1✔
48
    canAccess: ({ userCapabilities: { canManageUsers } }) => canManageUsers
1✔
49
  },
50
  'role-management': {
51
    component: Roles,
52
    text: () => 'Roles',
1✔
53
    canAccess: ({ currentUser, userRoles: { isAdmin } }) => currentUser && isAdmin
1✔
54
  },
55
  integrations: {
56
    component: Integrations,
57
    text: () => 'Integrations',
1✔
58
    canAccess: ({ userRoles: { isAdmin }, version }) => isAdmin && versionCompare(version, '3.2') > -1
1✔
59
  },
60
  upgrade: {
61
    component: Upgrade,
62
    icon: <PaymentIcon />,
63
    text: ({ isTrial }) => (isTrial ? 'Upgrade to a plan' : 'Upgrades and add-ons'),
1!
64
    canAccess: ({ hasMultitenancy }) => hasMultitenancy
1✔
65
  }
66
};
67

68
export const Settings = () => {
4✔
69
  const currentUser = useSelector(getCurrentUser);
1✔
70
  const { hasMultitenancy } = useSelector(getFeatures);
1✔
71
  const { trial: isTrial = false } = useSelector(getOrganization);
1✔
72
  const stripeAPIKey = useSelector(state => state.app.stripeAPIKey);
2✔
73
  const tenantCapabilities = useSelector(getTenantCapabilities);
1✔
74
  const userCapabilities = useSelector(getUserCapabilities);
1✔
75
  const userRoles = useSelector(getUserRoles);
1✔
76
  const { Integration: version } = useSelector(getVersionInformation);
1✔
77
  const [loadingFinished, setLoadingFinished] = useState(!stripeAPIKey);
1✔
78
  const { section: sectionParam } = useParams();
1✔
79

80
  useEffect(() => {
1✔
81
    // Make sure to call `loadStripe` outside of a component’s render to avoid recreating
82
    // the `Stripe` object on every render - but don't initialize twice.
83
    if (!stripePromise) {
1!
84
      import(/* webpackChunkName: "stripe" */ '@stripe/stripe-js').then(({ loadStripe }) => {
1✔
85
        if (stripeAPIKey) {
1!
UNCOV
86
          stripePromise = loadStripe(stripeAPIKey).finally(() => setLoadingFinished(true));
×
87
        }
88
      });
89
    } else {
UNCOV
90
      const notStripePromise = new Promise(resolve => setTimeout(resolve, TIMEOUTS.debounceDefault));
×
UNCOV
91
      Promise.race([stripePromise, notStripePromise]).then(result => setLoadingFinished(result !== notStripePromise));
×
92
    }
93
  }, [stripeAPIKey]);
94

95
  const checkDenyAccess = item =>
1✔
96
    currentUser.id && !item.canAccess({ currentUser, hasMultitenancy, isTrial, tenantCapabilities, userCapabilities, userRoles, version });
8✔
97

98
  const getCurrentSection = (sections, section = sectionParam) => {
1!
99
    if (!sections.hasOwnProperty(section) || checkDenyAccess(sections[section])) {
1!
UNCOV
100
      return;
×
101
    }
102
    return sections[section];
1✔
103
  };
104

105
  const links = Object.entries(sectionMap).reduce((accu, [key, item]) => {
1✔
106
    if (!checkDenyAccess(item)) {
7!
107
      accu.push({
7✔
108
        path: `/settings/${key}`,
109
        icon: item.icon,
110
        title: item.text({ isTrial })
111
      });
112
    }
113
    return accu;
7✔
114
  }, []);
115

116
  const section = getCurrentSection(sectionMap, sectionParam);
1✔
117
  if (!section) {
1!
UNCOV
118
    return <Navigate to="/settings/my-profile" replace />;
×
119
  }
120
  const Component = section.component;
1✔
121
  return (
1✔
122
    <div className="tab-container with-sub-panels" style={{ minHeight: '95%' }}>
123
      <LeftNav sections={[{ itemClass: 'settingsNav', items: links, title: 'Settings' }]} />
124
      <div className="rightFluid padding-right">
125
        {loadingFinished && (
2✔
126
          <Elements stripe={stripePromise}>
127
            <Component />
128
          </Elements>
129
        )}
130
      </div>
131
    </div>
132
  );
133
};
134

135
export default Settings;
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