• 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

86.49
/src/js/components/common/mendertooltip.js
1
// Copyright 2021 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

16
import { Help as HelpIcon } from '@mui/icons-material';
17
import { ClickAwayListener, Tooltip } from '@mui/material';
18
import { makeStyles, withStyles } from 'tss-react/mui';
19

20
import { TIMEOUTS } from '../../constants/appConstants';
21
import { READ_STATES } from '../../constants/userConstants';
22
import { toggle } from '../../helpers';
23
import { useDebounce } from '../../utils/debouncehook';
24

25
const useStyles = makeStyles()(theme => ({
183✔
26
  icon: {
27
    '&.read': {
28
      color: theme.palette.text.disabled
29
    }
30
  },
31
  iconAura: {
32
    position: 'absolute',
33
    top: -5,
34
    bottom: 0,
35
    left: -5,
36
    right: -5,
37
    border: `1px dashed ${theme.palette.primary.main}`,
38
    borderRadius: '50%',
39
    '&.read': {
40
      borderColor: theme.palette.text.disabled
41
    }
42
  }
43
}));
44

45
export const MenderTooltip = withStyles(Tooltip, ({ palette, shadows, spacing }) => ({
5,852✔
46
  arrow: {
47
    color: palette.background.paper
48
  },
49
  tooltip: {
50
    backgroundColor: palette.background.paper,
51
    boxShadow: shadows[1],
52
    color: palette.text.primary,
53
    padding: spacing(2),
54
    fontSize: 'small',
55
    maxWidth: 600,
56
    info: {
57
      maxWidth: 300,
58
      color: palette.text.hint,
59
      backgroundColor: palette.grey[500]
60
    }
61
  }
62
}));
63

64
export const MenderTooltipClickable = ({
183✔
65
  children,
66
  onboarding,
67
  startOpen = false,
4,860✔
68
  visibility = startOpen,
1,273✔
69
  onOpenChange,
70
  tooltipComponent = MenderTooltip,
3,466✔
71
  ...remainingProps
72
}) => {
73
  const [open, setOpen] = useState(startOpen || false);
4,861✔
74

75
  useEffect(() => {
4,861✔
76
    setOpen(visibility);
162✔
77
  }, [visibility]);
78

79
  useEffect(() => {
4,861✔
80
    if (!onOpenChange) {
162✔
81
      return;
47✔
82
    }
83
    onOpenChange(open);
115✔
84
  }, [open, onOpenChange]);
85

86
  const toggleVisibility = () => setOpen(toggle);
4,861✔
87

88
  const hide = () => setOpen(false);
4,861✔
89

90
  const Component = onboarding ? OnboardingTooltip : tooltipComponent;
4,861✔
91
  const extraProps = onboarding
4,861✔
92
    ? {
93
        PopperProps: {
94
          disablePortal: true,
95
          popperOptions: {
96
            strategy: 'fixed',
97
            modifiers: [
98
              { name: 'flip', enabled: false },
99
              { name: 'preventOverflow', enabled: true, options: { boundary: window, altBoundary: false } }
100
            ]
101
          }
102
        }
103
      }
104
    : {};
105
  return (
4,861✔
106
    <ClickAwayListener onClickAway={hide}>
107
      <Component
108
        arrow={!onboarding}
109
        open={open}
110
        disableFocusListener
111
        disableHoverListener
112
        disableTouchListener
113
        onOpen={() => setOpen(true)}
×
114
        {...extraProps}
115
        {...remainingProps}
116
      >
117
        <div onClick={toggleVisibility}>{children}</div>
118
      </Component>
119
    </ClickAwayListener>
120
  );
121
};
122

123
const iconWidth = 30;
183✔
124

125
export const OnboardingTooltip = withStyles(Tooltip, theme => ({
183✔
126
  arrow: {
127
    color: theme.palette.primary.main
128
  },
129
  tooltip: {
130
    backgroundColor: theme.palette.primary.main,
131
    boxShadow: theme.shadows[1],
132
    color: theme.palette.grey[500],
133
    fontSize: 14,
134
    maxWidth: 350,
135
    padding: '12px 18px',
136
    width: 350,
137
    '& a': {
138
      color: theme.palette.grey[500]
139
    },
140
    '&.MuiTooltip-tooltipPlacementTop': { marginLeft: iconWidth, marginBottom: 0, marginTop: `calc(${iconWidth} + ${theme.spacing(1.5)})` },
141
    '&.MuiTooltip-tooltipPlacementRight': { marginTop: iconWidth / 2 },
142
    '&.MuiTooltip-tooltipPlacementBottom': { marginLeft: iconWidth },
143
    '&.MuiTooltip-tooltipPlacementLeft': { marginTop: iconWidth / 2 }
144
  },
145
  popper: {
146
    opacity: 0.9
147
  }
148
}));
149
export default MenderTooltip;
150

151
const tooltipStateStyleMap = {
183✔
152
  [READ_STATES.read]: 'read muted',
153
  default: ''
154
};
155

156
const TooltipWrapper = ({ content, onClose, onReadAll }) => (
183✔
157
  <div>
×
158
    {content}
159
    <div className="flexbox space-between margin-top-small">
160
      <span className="link" onClick={onReadAll}>
161
        Mark all help tips as read
162
      </span>
163
      <span className="link" onClick={onClose}>
164
        Close
165
      </span>
166
    </div>
167
  </div>
168
);
169

170
export const HelpTooltip = ({ icon = undefined, id, contentProps = {}, tooltip, device, setAllTooltipsReadState, setTooltipReadState, ...props }) => {
183✔
171
  const [isOpen, setIsOpen] = useState(false);
2,194✔
172
  const debouncedIsOpen = useDebounce(isOpen, TIMEOUTS.threeSeconds);
2,194✔
173
  const { classes } = useStyles();
2,194✔
174
  const { Component, SpecialComponent, isRelevant, readState } = tooltip;
2,194✔
175

176
  useEffect(() => {
2,194✔
177
    if (!debouncedIsOpen) {
68!
178
      return;
68✔
179
    }
180
    setTooltipReadState(id, READ_STATES.read, true);
×
181
  }, [debouncedIsOpen, id, setTooltipReadState]);
182

183
  const onReadAllClick = () => setAllTooltipsReadState(READ_STATES.read);
2,194✔
184

185
  const title = SpecialComponent ? (
2,194✔
186
    <SpecialComponent device={device} {...contentProps} />
187
  ) : (
188
    <TooltipWrapper content={<Component device={device} {...contentProps} />} onClose={() => setIsOpen(false)} onReadAll={onReadAllClick} />
×
189
  );
190

191
  if (!isRelevant({ device, ...contentProps })) {
2,194!
192
    return null;
×
193
  }
194

195
  const className = tooltipStateStyleMap[readState] ?? tooltipStateStyleMap.default;
2,194✔
196
  return (
2,194✔
197
    <MenderTooltipClickable className={isOpen ? 'muted' : ''} title={title} visibility={isOpen} onOpenChange={setIsOpen} {...props}>
2,194!
198
      <div className="relative">
199
        {icon || <HelpIcon className={`${classes.icon} ${className}`} color="primary" />}
4,388✔
200
        <div className={`${classes.iconAura} ${className}`} />
201
      </div>
202
    </MenderTooltipClickable>
203
  );
204
};
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