UNPKG

3.1 kBJavaScriptView Raw
1import React, {PureComponent} from 'react';
2import PropTypes from 'prop-types';
3import servicesIcon from '@jetbrains/icons/services-20px.svg';
4
5import Dropdown from '../dropdown/dropdown';
6import Popup from '../popup/popup';
7
8import TrayIcon from './tray-icon';
9import ServicesLink from './services-link';
10import styles from './services.css';
11
12const makeAnchor = loading => {
13 const Anchor = ({active}) => (
14 <TrayIcon
15 loader={loading}
16 active={active}
17 icon={servicesIcon}
18 aria-label="Services"
19 />
20 );
21
22 Anchor.propTypes = {
23 active: PropTypes.bool
24 };
25
26 return Anchor;
27};
28
29export default class Services extends PureComponent {
30 static Link = ServicesLink;
31 static sort = (a, b) => {
32 const aApplicationName = a.applicationName || '';
33 const bApplicationName = b.applicationName || '';
34
35 return aApplicationName.localeCompare(bApplicationName) ||
36 a.name.localeCompare(b.name);
37 };
38
39 static propTypes = {
40 className: PropTypes.string,
41 clientId: PropTypes.string,
42 initShown: PropTypes.bool,
43 loading: PropTypes.bool,
44 onClick: PropTypes.func,
45 services: PropTypes.arrayOf(ServicesLink.propTypes.service)
46 };
47
48 serviceIsActive = service => service.id === this.props.clientId;
49
50 render() {
51 // eslint-disable-next-line no-unused-vars
52 const {clientId, loading, services, initShown, ...props} = this.props;
53
54 if (!services) {
55 return (
56 <TrayIcon
57 {...props}
58 loader={loading}
59 active={loading}
60 icon={servicesIcon}
61 aria-label="Services"
62 />
63 );
64 }
65
66 const sortedServices = services.sort(Services.sort);
67 const servicesWithIcons = sortedServices.filter(service => service.iconUrl);
68 const servicesWithOutIcons = sortedServices.filter(service => !service.iconUrl);
69 const separatorIsRequired = servicesWithIcons.length !== 0 && servicesWithOutIcons.length !== 0;
70
71 return (
72 <Dropdown
73 {...props}
74 anchor={makeAnchor(loading)}
75 initShown={initShown}
76 >
77 <Popup
78 className={styles.services}
79 top={-3}
80 >
81 {servicesWithIcons.map(service => {
82 const isActive = this.serviceIsActive(service);
83
84 return (
85 <Services.Link
86 active={isActive}
87 className={isActive ? styles.activeItem : styles.item}
88 key={service.id}
89 service={service}
90 />
91 );
92 })}
93 {separatorIsRequired && (
94 <div
95 className={styles.line}
96 key="separator"
97 />
98 )}
99 {servicesWithOutIcons.map(service => {
100 const isActive = this.serviceIsActive(service);
101
102 return (
103 <Services.Link
104 active={isActive}
105 className={isActive ? styles.activeItemStacked : styles.itemStacked}
106 key={service.id}
107 service={service}
108 />
109 );
110 })}
111 </Popup>
112 </Dropdown>
113 );
114 }
115}