• 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

88.89
/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 { getCurrentUser, getFeatures, getOrganization, getTenantCapabilities, getUserCapabilities, getUserRoles } from '../../selectors';
25
import LeftNav from '../common/left-nav';
26
import SelfUserManagement from '../settings/user-management/selfusermanagement';
27
import UserManagement from '../settings/user-management/usermanagement';
28
import Global from './global';
29
import Integrations from './integrations';
30
import Organization from './organization/organization';
31
import Roles from './roles';
32
import Upgrade from './upgrade';
33

34
let stripePromise = null;
3✔
35

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

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

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

93
  const checkDenyAccess = item => currentUser.id && !item.canAccess({ currentUser, hasMultitenancy, isTrial, tenantCapabilities, userCapabilities, userRoles });
8✔
94

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

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

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

132
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