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

mendersoftware / gui / 988636826

01 Sep 2023 04:04AM UTC coverage: 82.384% (-17.6%) from 99.964%
988636826

Pull #3969

gitlab-ci

web-flow
chore: Bump autoprefixer from 10.4.14 to 10.4.15

Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from 10.4.14 to 10.4.15.
- [Release notes](https://github.com/postcss/autoprefixer/releases)
- [Changelog](https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/autoprefixer/compare/10.4.14...10.4.15)

---
updated-dependencies:
- dependency-name: autoprefixer
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #3969: chore: Bump autoprefixer from 10.4.14 to 10.4.15

4346 of 6321 branches covered (0.0%)

8259 of 10025 relevant lines covered (82.38%)

192.73 hits per line

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

88.57
/src/js/components/devices/device-details/connection.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
import { Link } from 'react-router-dom';
16

17
import { ImportExport as ImportExportIcon, InfoOutlined as InfoIcon, Launch as LaunchIcon } from '@mui/icons-material';
18
import { Button, Typography } from '@mui/material';
19
import { useTheme } from '@mui/material/styles';
20

21
import { mdiConsole as ConsoleIcon } from '@mdi/js';
22

23
import { BEGINNING_OF_TIME, BENEFITS } from '../../../constants/appConstants';
24
import { ALL_DEVICES, DEVICE_CONNECT_STATES } from '../../../constants/deviceConstants';
25
import { AUDIT_LOGS_TYPES } from '../../../constants/organizationConstants';
26
import { checkPermissionsObject, uiPermissionsById } from '../../../constants/userConstants';
27
import { formatAuditlogs } from '../../../utils/locationutils';
28
import DocsLink from '../../common/docslink';
29
import EnterpriseNotification from '../../common/enterpriseNotification';
30
import MaterialDesignIcon from '../../common/materialdesignicon';
31
import MenderTooltip from '../../common/mendertooltip';
32
import Time from '../../common/time';
33
import Troubleshootdialog from '../dialogs/troubleshootdialog';
34
import DeviceDataCollapse from './devicedatacollapse';
35

36
const buttonStyle = { textTransform: 'none', textAlign: 'left' };
11✔
37
export const PortForwardLink = () => (
11✔
38
  <MenderTooltip
3✔
39
    arrow
40
    title={
41
      <div style={{ whiteSpace: 'normal' }}>
42
        <h3>Port forwarding</h3>
43
        <p>Port forwarding allows you to troubleshoot or use services on or via the device, without opening any ports on the device itself.</p>
44
        <p>
45
          To enable port forwarding you will need to install and configure the necessary software on the device and your workstation. Follow the link to learn
46
          more.
47
        </p>
48
      </div>
49
    }
50
  >
51
    <DocsLink className="flexbox centered margin-left" path="add-ons/port-forward">
52
      Enable port forwarding
53
      <LaunchIcon className="margin-left-small" fontSize="small" />
54
    </DocsLink>
55
  </MenderTooltip>
56
);
57

58
export const DeviceConnectionNote = ({ children, style = buttonStyle }) => {
11✔
59
  const theme = useTheme();
7✔
60
  return (
7✔
61
    <div className="flexbox muted">
62
      <InfoIcon fontSize="small" style={{ marginRight: theme.spacing() }} />
63
      <Typography variant="body1" style={style}>
64
        {children}
65
      </Typography>
66
    </div>
67
  );
68
};
69

70
export const DeviceConnectionMissingNote = () => (
11✔
71
  <DeviceConnectionNote>
3✔
72
    The troubleshoot add-on does not seem to be enabled on this device.
73
    <br />
74
    Please <DocsLink path="add-ons/remote-terminal" title="see the documentation" /> for a description on how it works and how to enable it.
75
  </DeviceConnectionNote>
76
);
77

78
export const DeviceDisconnectedNote = ({ lastConnectionTs }) => (
11✔
79
  <DeviceConnectionNote>
3✔
80
    The troubleshoot add-on is not currently connected on this device, it was last connected on <Time value={lastConnectionTs} />.
81
    <br />
82
    Please <DocsLink path="add-ons/remote-terminal" title="see the documentation" /> for more information.
83
  </DeviceConnectionNote>
84
);
85

86
export const TroubleshootButton = ({ disabled, item, onClick }) => {
11✔
87
  const theme = useTheme();
4✔
88
  return (
4✔
89
    <Button onClick={() => onClick(item.key)} disabled={disabled} startIcon={item.icon} style={{ marginRight: theme.spacing(2) }}>
×
90
      <Typography variant="subtitle2" style={buttonStyle}>
91
        {item.title}
92
      </Typography>
93
    </Button>
94
  );
95
};
96

97
const troubleshootingTools = [
11✔
98
  {
99
    key: 'terminal',
100
    title: 'Launch a new Remote Terminal session',
101
    icon: <MaterialDesignIcon path={ConsoleIcon} />,
102
    needsWriteAccess: true,
103
    needsTroubleshoot: true
104
  },
105
  { key: 'transfer', title: 'Launch File Transfer', icon: <ImportExportIcon />, needsWriteAccess: false, needsTroubleshoot: false },
106
  { key: 'portForward', component: PortForwardLink, needsWriteAccess: false, needsTroubleshoot: true }
107
];
108

109
const deviceAuditlogType = AUDIT_LOGS_TYPES.find(type => type.value === 'device');
33✔
110

111
export const DeviceConnection = ({ className = '', device, hasAuditlogs, socketClosed, startTroubleshoot, userCapabilities }) => {
11✔
112
  const [availableTabs, setAvailableTabs] = useState(troubleshootingTools);
6✔
113

114
  const { canAuditlog, canTroubleshoot, canWriteDevices: hasWriteAccess, groupsPermissions } = userCapabilities;
6✔
115

116
  useEffect(() => {
6✔
117
    const allowedTabs = troubleshootingTools.reduce((accu, tab) => {
3✔
118
      if (
9!
119
        (tab.needsWriteAccess && (!hasWriteAccess || !checkPermissionsObject(groupsPermissions, uiPermissionsById.connect.value, device.group, ALL_DEVICES))) ||
30✔
120
        (tab.needsTroubleshoot && !canTroubleshoot)
121
      ) {
122
        return accu;
×
123
      }
124
      accu.push(tab);
9✔
125
      return accu;
9✔
126
    }, []);
127
    setAvailableTabs(allowedTabs);
3✔
128
    // eslint-disable-next-line react-hooks/exhaustive-deps
129
  }, [hasWriteAccess, canTroubleshoot, JSON.stringify(groupsPermissions), device.group]);
130

131
  const { connect_status = DEVICE_CONNECT_STATES.unknown, connect_updated_ts } = device;
6✔
132
  return (
6✔
133
    <DeviceDataCollapse
134
      header={
135
        <div className={`flexbox ${className}`}>
136
          {connect_status === DEVICE_CONNECT_STATES.unknown && <DeviceConnectionMissingNote />}
8✔
137
          {connect_status === DEVICE_CONNECT_STATES.disconnected && <DeviceDisconnectedNote lastConnectionTs={connect_updated_ts} />}
8✔
138
          {connect_status === DEVICE_CONNECT_STATES.connected &&
8✔
139
            availableTabs.map(item => {
140
              let Component = TroubleshootButton;
6✔
141
              if (item.component) {
6✔
142
                Component = item.component;
2✔
143
              }
144
              return <Component key={item.key} onClick={startTroubleshoot} disabled={socketClosed} item={item} />;
6✔
145
            })}
146
          {canAuditlog && hasAuditlogs && connect_status !== DEVICE_CONNECT_STATES.unknown && (
16✔
147
            <Link
148
              className="flexbox center-aligned margin-left"
149
              to={`/auditlog?${formatAuditlogs({ pageState: { type: deviceAuditlogType, detail: device.id, startDate: BEGINNING_OF_TIME } }, {})}`}
150
            >
151
              List all log entries for this device
152
            </Link>
153
          )}
154
        </div>
155
      }
156
      isAddOn
157
      title={
158
        <div className="flexbox center-aligned">
159
          <h4>Troubleshoot</h4>
160
          <EnterpriseNotification className="margin-left-small" id={BENEFITS.deviceTroubleshoot.id} />
161
        </div>
162
      }
163
    ></DeviceDataCollapse>
164
  );
165
};
166

167
export default DeviceConnection;
168

169
export const TroubleshootTab = ({
11✔
170
  classes,
171
  device,
172
  launchTroubleshoot,
173
  setSocketClosed,
174
  setTroubleshootType,
175
  socketClosed,
176
  tenantCapabilities,
177
  troubleshootType,
178
  userCapabilities
179
}) => (
180
  <>
×
181
    <DeviceConnection
182
      className={classes.deviceConnection}
183
      device={device}
184
      socketClosed={socketClosed}
185
      startTroubleshoot={launchTroubleshoot}
186
      userCapabilities={userCapabilities}
187
      tenantCapabilities={tenantCapabilities}
188
    />
189
    <Troubleshootdialog
190
      device={device}
191
      open={Boolean(troubleshootType)}
192
      onCancel={() => setTroubleshootType()}
×
193
      setSocketClosed={setSocketClosed}
194
      type={troubleshootType}
195
    />
196
  </>
197
);
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