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

mendersoftware / mender-server / 10423

11 Nov 2025 04:53PM UTC coverage: 74.435% (-0.1%) from 74.562%
10423

push

gitlab-ci

web-flow
Merge pull request #1071 from mendersoftware/dependabot/npm_and_yarn/frontend/main/development-dependencies-92732187be

3868 of 5393 branches covered (71.72%)

Branch coverage included in aggregate %.

5 of 5 new or added lines in 2 files covered. (100.0%)

176 existing lines in 95 files now uncovered.

64605 of 86597 relevant lines covered (74.6%)

7.74 hits per line

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

95.07
/frontend/src/js/components/subscription/SubscriptionConfirmation.tsx
1
// Copyright 2025 Northern.tech AS
2✔
2
//
2✔
3
//    Licensed under the Apache License, Version 2.0 (the "License");
2✔
4
//    you may not use this file except in compliance with the License.
2✔
5
//    You may obtain a copy of the License at
2✔
6
//
2✔
7
//        http://www.apache.org/licenses/LICENSE-2.0
2✔
8
//
2✔
9
//    Unless required by applicable law or agreed to in writing, software
2✔
10
//    distributed under the License is distributed on an "AS IS" BASIS,
2✔
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2✔
12
//    See the License for the specific language governing permissions and
2✔
13
//    limitations under the License.
2✔
14
import { useEffect, useState } from 'react';
2✔
15
import { useSelector } from 'react-redux';
2✔
16

2✔
17
import { TaskAlt as TaskAltIcon } from '@mui/icons-material';
2✔
18
import { Alert, AlertTitle, Button, DialogContent, IconButton, Typography } from '@mui/material';
2✔
19

2✔
20
import { BaseDialog } from '@northern.tech/common-ui/dialogs/BaseDialog';
2✔
21
import { cleanUp } from '@northern.tech/store/auth';
2✔
22
import { ADDONS, AvailableAddon, Plan } from '@northern.tech/store/constants';
2✔
23
import { getOrganization } from '@northern.tech/store/organizationSlice/selectors';
2✔
24

2✔
25
import { formatPrice } from './utils';
2✔
26

2✔
27
interface SubscriptionConfirmationProps {
2✔
28
  devices: number;
2✔
29
  orderedAddons: { name: AvailableAddon }[];
2✔
30
  plan: Plan;
2✔
31
  price: number;
2✔
32
}
2✔
33
export const SubscriptionConfirmation = (props: SubscriptionConfirmationProps) => {
9✔
34
  const { plan, devices, price, orderedAddons } = props;
3✔
35
  const { addons: enabledAddons, plan: currentPlan } = useSelector(getOrganization);
3✔
36

2✔
37
  const [addonList] = useState(orderedAddons.map(addon => addon.name));
3✔
38

2✔
39
  const previousAddonsList = enabledAddons.filter(addon => addon.enabled);
3✔
40
  const willLogout = addonList.length > previousAddonsList.length || currentPlan !== plan.id;
3✔
41
  const [count, setCount] = useState<number>(60);
3✔
42
  const logOut = () => {
3✔
43
    cleanUp();
2✔
44
    window.location.replace('/ui/');
2✔
45
  };
2✔
46

2✔
47
  useEffect(() => {
3✔
48
    if (!willLogout) {
3!
49
      return;
2✔
50
    }
2✔
51
    const timer = setInterval(() => {
3✔
52
      setCount(prevCount => {
2✔
53
        if (prevCount === 1) {
2!
54
          clearInterval(timer);
2✔
55
          logOut();
2✔
56
          return 0;
2✔
57
        }
2✔
58
        return prevCount - 1;
2✔
59
      });
2✔
60
    }, 1000);
2✔
61

2✔
62
    return () => clearInterval(timer);
3✔
63
  }, [willLogout]);
2✔
64

2✔
65
  return (
3✔
66
    <BaseDialog
2✔
67
      open
2✔
68
      maxWidth="xs"
2✔
69
      title={
2✔
70
        <div className="flexbox center-aligned">
2✔
71
          <IconButton size="large">
2✔
72
            <TaskAltIcon selected className="green" />
2✔
73
          </IconButton>
2✔
74
          <Typography variant="h6">Payment successful!</Typography>
2✔
75
        </div>
2✔
76
      }
2✔
77
    >
2✔
78
      <DialogContent>
2✔
79
        <Typography variant="body1">
2✔
80
          {willLogout
2!
81
            ? `Your subscription has been successfully updated${currentPlan !== plan.id ? ` to Mender ${plan.name}.` : '.'}`
2!
82
            : 'Your device limit has been successfully updated.'}
2✔
83
        </Typography>
2✔
84
        <div className="margin-top-small margin-bottom-small">
2✔
85
          <Typography variant="subtitle1"> Subscription details: </Typography>
2✔
86
          <Typography> Plan: {plan.name} </Typography>
2✔
87
          <Typography> Devices: {devices} </Typography>
2✔
UNCOV
88
          {addonList.length > 0 && <Typography>Add-ons: {addonList.map(addon => ADDONS[addon].title).join(', ')}</Typography>}
2!
89
          <Typography>Monthly cost: {formatPrice(price)}</Typography>
2✔
90
        </div>
2✔
91
        {willLogout ? (
2!
92
          <Alert severity="info" icon={false}>
2✔
93
            <AlertTitle textAlign="center">Automatic logout in {count} seconds</AlertTitle>
2✔
94
            <div className="flexbox column centered">
2✔
95
              <Typography className="margin-bottom-x-small" textAlign="center" variant="body2">
2✔
96
                You will be logged out automatically, for your new subscription to take effect.
2✔
97
              </Typography>
2✔
98
              <Button variant="contained" onClick={logOut}>
2✔
99
                Log out now
2✔
100
              </Button>
2✔
101
            </div>
2✔
102
          </Alert>
2✔
103
        ) : (
2✔
104
          <Alert
2✔
105
            severity="success"
2✔
106
            icon={false}
2✔
107
            sx={{
2✔
108
              '& .MuiAlert-message': {
2✔
109
                width: '100%'
2✔
110
              }
2✔
111
            }}
2✔
112
            className="flexbox space-between"
2✔
113
          >
2✔
114
            <AlertTitle textAlign="center">Subscription Active</AlertTitle>
2✔
115
            <div className="flexbox column centered">
2✔
116
              <Typography className="margin-bottom-x-small" textAlign="center" variant="body2">
2✔
117
                Your updated subscription is ready to use.{' '}
2✔
118
              </Typography>
2✔
119
              <Button variant="outlined" onClick={() => window.location.replace('/ui/')}>
2✔
120
                Close
2✔
121
              </Button>
2✔
122
            </div>
2✔
123
          </Alert>
2✔
124
        )}
2✔
125
      </DialogContent>
2✔
126
    </BaseDialog>
2✔
127
  );
2✔
128
};
2✔
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