• 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

99.38
/frontend/src/js/components/helptips/BaseOnoardingTip.tsx
1
// Copyright 2019 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 React, { useEffect, useRef, useState } from 'react';
2✔
15
import { useDispatch, useSelector } from 'react-redux';
2✔
16

2✔
17
import {
2✔
18
  ArrowBack as ArrowBackIcon,
2✔
19
  ArrowDownward as ArrowDownwardIcon,
2✔
20
  ArrowForward as ArrowForwardIcon,
2✔
21
  ArrowUpward as ArrowUpwardIcon
2✔
22
} from '@mui/icons-material';
2✔
23
import { buttonBaseClasses, buttonClasses } from '@mui/material';
2✔
24
import { makeStyles } from 'tss-react/mui';
2✔
25

2✔
26
import storeActions from '@northern.tech/store/actions';
2✔
27
import { TIMEOUTS } from '@northern.tech/store/constants';
2✔
28
import { toggle } from '@northern.tech/utils/helpers';
2✔
29

2✔
30
import Tracking from '../../tracking';
2✔
31
import { OnboardingTooltip } from './MenderTooltip';
2✔
32

2✔
33
const { setShowDismissOnboardingTipsDialog } = storeActions;
24✔
34

2✔
35
const iconWidth = 30;
24✔
36

2✔
37
export const orientations = {
24✔
38
  top: {
2✔
39
    arrow: <ArrowUpwardIcon />,
2✔
40
    placement: 'bottom',
2✔
41
    offsetStyle: style => {
2✔
42
      style.left = style.left - iconWidth / 2;
7✔
43
      return style;
7✔
44
    }
2✔
45
  },
2✔
46
  right: {
2✔
47
    arrow: <ArrowBackIcon />,
2✔
48
    placement: 'right',
2✔
49
    offsetStyle: style => {
2✔
50
      style.top = style.top - iconWidth / 2;
3✔
51
      style.left = style.left + iconWidth / 2;
3✔
52
      return style;
3✔
53
    }
2✔
54
  },
2✔
55
  bottom: {
2✔
56
    arrow: <ArrowDownwardIcon />,
2✔
57
    placement: 'top',
2✔
58
    offsetStyle: style => {
2✔
59
      style.left = style.left - iconWidth / 2;
3✔
60
      return style;
3✔
61
    }
2✔
62
  },
2✔
63
  left: {
2✔
64
    arrow: <ArrowForwardIcon />,
2✔
65
    placement: 'left',
2✔
66
    offsetStyle: style => {
2✔
67
      style.top = style.top - iconWidth / 2;
3✔
68
      return style;
3✔
69
    }
2✔
70
  }
2✔
71
};
2✔
72

2✔
73
const useStyles = makeStyles()(theme => ({
24✔
74
  root: {
2✔
75
    [`.${buttonBaseClasses.root}.${buttonClasses.text}`]: { color: theme.palette.background.paper, paddingRight: 0 }
2✔
76
  }
2✔
77
}));
2✔
78

2✔
79
export const BaseOnboardingTooltip = ({ anchor = { left: 0, top: 0 }, icon, children, id = '1', place = 'top', ...props }) => {
24✔
80
  const [open, setOpen] = useState(false);
6✔
81
  const showDismissHelptipsDialog = useSelector(state => state.onboarding.showTipsDialog);
10✔
82
  const showDeviceConnectionDialog = useSelector(state => state.users.showConnectDeviceDialog);
10✔
83
  const delayTimer = useRef();
6✔
84

2✔
85
  const { classes } = useStyles();
6✔
86

2✔
87
  useEffect(() => {
6✔
88
    Tracking.event({ category: 'onboarding', action: id });
6✔
89
    clearTimeout(delayTimer.current);
6✔
90
    delayTimer.current = setTimeout(() => setOpen(true), TIMEOUTS.debounceShort);
6✔
91
    return () => {
6✔
92
      clearTimeout(delayTimer.current);
6✔
93
    };
2✔
94
  }, [id]);
2✔
95

2✔
96
  const toggleVisibility = () => setOpen(toggle);
6✔
97

2✔
98
  const hide = () => setOpen(false);
6✔
99

2✔
100
  if (showDismissHelptipsDialog || showDeviceConnectionDialog) {
6!
101
    return null;
2✔
102
  }
2✔
103

2✔
104
  const orientation = orientations[place];
6✔
105
  const style = orientation.offsetStyle({ left: anchor.left, top: anchor.top, overflow: 'initial' });
6✔
106
  return (
6✔
107
    <OnboardingTooltip
2✔
108
      disableFocusListener
2✔
109
      disableHoverListener
2✔
110
      disableTouchListener
2✔
111
      id={id}
2✔
112
      onClose={hide}
2✔
113
      open={open}
2✔
114
      placement={orientation.placement}
2✔
115
      PopperProps={{
2✔
116
        className: classes.root,
2✔
117
        disablePortal: true,
2✔
118
        popperOptions: {
2✔
119
          strategy: 'fixed',
2✔
120
          modifiers: [
2✔
121
            { name: 'flip', enabled: false },
2✔
122
            { name: 'preventOverflow', enabled: true, options: { boundary: window, altBoundary: false } }
2✔
123
          ]
2✔
124
        }
2✔
125
      }}
2✔
126
      title={children}
2✔
127
      className={classes.root}
2✔
128
      {...props}
2✔
129
    >
2✔
130
      <div className="onboard-tip" onClick={toggleVisibility} style={style}>
2✔
131
        <div className={`tooltip onboard-icon ${orientation.placement}`}>{icon ?? orientation.arrow}</div>
2✔
132
      </div>
2✔
133
    </OnboardingTooltip>
2✔
134
  );
2✔
135
};
2✔
136

2✔
137
export const BaseOnboardingTip = ({ anchor, icon, component, place, id, ...others }) => {
24✔
138
  const dispatch = useDispatch();
4✔
139
  return (
4✔
140
    <BaseOnboardingTooltip anchor={anchor} icon={icon} place={place} id={id}>
2✔
141
      <div className="content">
2✔
142
        {React.cloneElement(component, others)}
2✔
143
        <div>
2✔
UNCOV
144
          <b className="clickable" onClick={() => dispatch(setShowDismissOnboardingTipsDialog(true))}>
2✔
145
            Dismiss the tutorial
2✔
146
          </b>
2✔
147
        </div>
2✔
148
      </div>
2✔
149
    </BaseOnboardingTooltip>
2✔
150
  );
2✔
151
};
2✔
152

2✔
153
export default BaseOnboardingTip;
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