Fixing bug in Query Table sidebar dropdown (#691)
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { Component, PropTypes } from 'react';
|
||||
import { noop } from 'lodash';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
|
||||
class Rocker extends Component {
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import Button from 'components/buttons/Button';
|
||||
import Dropdown from 'components/forms/fields/Dropdown';
|
||||
import Form from 'components/forms/Form';
|
||||
|
||||
@@ -3,7 +3,7 @@ import classnames from 'classnames';
|
||||
|
||||
import Button from 'components/buttons/Button';
|
||||
import formDataInterface from 'interfaces/registration_form_data';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import Checkbox from 'components/forms/fields/Checkbox';
|
||||
|
||||
const baseClass = 'confirm-user-reg';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import InputField from '../InputField';
|
||||
|
||||
const baseClass = 'input-icon-field';
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import AceEditor from 'react-ace';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import hostHelpers from 'components/hosts/HostDetails/helpers';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import targetInterface from 'interfaces/target';
|
||||
|
||||
const baseClass = 'target-details';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import targetInterface from 'interfaces/target';
|
||||
|
||||
const baseClass = 'target-option';
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import targetInterface from 'interfaces/target';
|
||||
import TargetIcon from './TargetIcon';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { noop } from 'lodash';
|
||||
|
||||
import EllipsisMenu from 'components/buttons/EllipsisMenu';
|
||||
import hostInterface from 'interfaces/host';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import { humanMemory, humanUptime, platformIconClass } from './helpers';
|
||||
|
||||
const baseClass = 'host-details';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import hostInterface from 'interfaces/host';
|
||||
import { platformIconClass, statusIconClass } from 'utilities/icon_class';
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Icon from 'components/icons/Icon';
|
||||
|
||||
const baseClass = 'platform-icon';
|
||||
|
||||
export class PlatformIcon extends Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
fw: PropTypes.bool,
|
||||
name: PropTypes.string.isRequired,
|
||||
size: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
};
|
||||
|
||||
findIcon = () => {
|
||||
const { name } = this.props;
|
||||
|
||||
switch (name.toLowerCase()) {
|
||||
case 'macos': return 'apple';
|
||||
case 'mac os x': return 'apple';
|
||||
case 'mac osx': return 'apple';
|
||||
case 'mac os': return 'apple';
|
||||
case 'darwin': return 'apple';
|
||||
case 'centos': return 'centos';
|
||||
case 'centos linux': return 'centos';
|
||||
case 'ubuntu': return 'ubuntu';
|
||||
case 'ubuntu linux': return 'ubuntu';
|
||||
case 'linux': return 'linux';
|
||||
case 'windows': return 'windows';
|
||||
case 'ms windows': return 'windows';
|
||||
default: return false;
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { findIcon } = this;
|
||||
const { className, fw, name, size, title } = this.props;
|
||||
const iconClasses = classnames(baseClass, className);
|
||||
const iconName = findIcon();
|
||||
|
||||
if (!iconName) {
|
||||
return <span className={iconClasses}>{name}</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Icon
|
||||
className={iconClasses}
|
||||
fw={fw}
|
||||
name={iconName}
|
||||
size={size}
|
||||
title={title}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PlatformIcon;
|
||||
@@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import expect from 'expect';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import PlatformIcon from './PlatformIcon';
|
||||
|
||||
describe('PlatformIcon - component', () => {
|
||||
it('renders', () => {
|
||||
expect(mount(<PlatformIcon name="linux" />).length).toEqual(1);
|
||||
});
|
||||
|
||||
it('renders text if no icon', () => {
|
||||
const component = mount(<PlatformIcon name="blah" />);
|
||||
|
||||
expect(component.find('span').length).toEqual(1);
|
||||
expect(component.text()).toInclude('blah');
|
||||
expect(component.find('Icon').length).toEqual(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
export default from './PlatformIcon';
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
|
||||
const baseClass = 'modal';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { noop } from 'lodash';
|
||||
|
||||
import Button from 'components/buttons/Button';
|
||||
import EditPackForm from 'components/forms/packs/EditPackForm';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import packInterface from 'interfaces/pack';
|
||||
import SelectTargetsDropdown from 'components/forms/fields/SelectTargetsDropdown';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import classnames from 'classnames';
|
||||
import { includes, size } from 'lodash';
|
||||
|
||||
import queryInterface from 'interfaces/query';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import QueriesListItem from 'components/queries/QueriesList/QueriesListItem';
|
||||
import Checkbox from 'components/forms/fields/Checkbox';
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import Checkbox from 'components/forms/fields/Checkbox';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import PlatformIcon from 'components/icons/PlatformIcon';
|
||||
import { isEqual } from 'lodash';
|
||||
import { platformIconClass } from 'utilities/icon_class';
|
||||
import scheduledQueryInterface from 'interfaces/scheduled_query';
|
||||
|
||||
class QueriesListItem extends Component {
|
||||
@@ -60,7 +60,7 @@ class QueriesListItem extends Component {
|
||||
</td>
|
||||
<td>{name}</td>
|
||||
<td>{interval}</td>
|
||||
<td><Icon name={platformIconClass(platform)} /></td>
|
||||
<td><PlatformIcon name={platform} /></td>
|
||||
<td>{version}</td>
|
||||
<td><Icon name={loggingTypeString()} /></td>
|
||||
</tr>
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('QueriesListItem - component', () => {
|
||||
const component = mount(<QueriesListItem checked={false} onSelect={noop} scheduledQuery={scheduledQueryStub} />);
|
||||
expect(component.text()).toInclude(scheduledQueryStub.name);
|
||||
expect(component.text()).toInclude(scheduledQueryStub.interval);
|
||||
expect(component.find('.kolidecon-apple').length).toEqual(1);
|
||||
expect(component.find('PlatformIcon').length).toEqual(1);
|
||||
});
|
||||
|
||||
it('renders a Checkbox component', () => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { get, keys, omit, values } from 'lodash';
|
||||
|
||||
import campaignInterface from 'interfaces/campaign';
|
||||
import filterArrayByHash from 'utilities/filter_array_by_hash';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import InputField from 'components/forms/fields/InputField';
|
||||
import ProgressBar from 'components/ProgressBar';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { filter } from 'lodash';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import InputField from 'components/forms/fields/InputField';
|
||||
import labelInterface from 'interfaces/label';
|
||||
import PanelGroup from 'components/side_panels/HostSidePanel/PanelGroup';
|
||||
@@ -50,18 +50,21 @@ class HostSidePanel extends Component {
|
||||
groupItems={allHostLabels}
|
||||
onLabelClick={onLabelClick}
|
||||
selectedLabel={selectedLabel}
|
||||
type="all-hosts"
|
||||
/>
|
||||
<hr className={`${baseClass}__hr`} />
|
||||
<PanelGroup
|
||||
groupItems={hostStatusLabels}
|
||||
onLabelClick={onLabelClick}
|
||||
selectedLabel={selectedLabel}
|
||||
type="status"
|
||||
/>
|
||||
<hr className={`${baseClass}__hr`} />
|
||||
<PanelGroup
|
||||
groupItems={hostPlatformLabels}
|
||||
onLabelClick={onLabelClick}
|
||||
selectedLabel={selectedLabel}
|
||||
type="platform"
|
||||
/>
|
||||
<hr className={`${baseClass}__hr`} />
|
||||
<div className={`${baseClass}__panel-group-item`}>
|
||||
@@ -82,6 +85,7 @@ class HostSidePanel extends Component {
|
||||
groupItems={customLabels}
|
||||
onLabelClick={onLabelClick}
|
||||
selectedLabel={selectedLabel}
|
||||
type="label"
|
||||
/>
|
||||
<hr className={`${baseClass}__hr`} />
|
||||
<button className={`${baseClass}__add-label-btn button button--unstyled`} onClick={onAddLabelClick}>
|
||||
|
||||
@@ -9,6 +9,7 @@ class PanelGroup extends Component {
|
||||
groupItems: PropTypes.arrayOf(labelInterface),
|
||||
onLabelClick: PropTypes.func,
|
||||
selectedLabel: labelInterface,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
@@ -19,6 +20,7 @@ class PanelGroup extends Component {
|
||||
const {
|
||||
onLabelClick,
|
||||
selectedLabel,
|
||||
type,
|
||||
} = this.props;
|
||||
const selected = isEqual(selectedLabel, item);
|
||||
|
||||
@@ -28,6 +30,7 @@ class PanelGroup extends Component {
|
||||
item={item}
|
||||
key={item.display_text}
|
||||
onLabelClick={onLabelClick(item)}
|
||||
type={type}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import iconClassForLabel from 'utilities/icon_class_for_label';
|
||||
import PlatformIcon from 'components/icons/PlatformIcon';
|
||||
|
||||
const baseClass = 'panel-group-item';
|
||||
|
||||
@@ -16,9 +17,21 @@ class PanelGroupItem extends Component {
|
||||
}).isRequired,
|
||||
onLabelClick: PropTypes.func,
|
||||
isSelected: PropTypes.bool,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
renderIcon = () => {
|
||||
const { item, type } = this.props;
|
||||
|
||||
if (type === 'platform') {
|
||||
return <PlatformIcon name={item.display_text} className={`${baseClass}__icon`} />;
|
||||
}
|
||||
|
||||
return <Icon name={iconClassForLabel(item)} className={`${baseClass}__icon`} />;
|
||||
}
|
||||
|
||||
render () {
|
||||
const { renderIcon } = this;
|
||||
const { item, onLabelClick, isSelected } = this.props;
|
||||
const {
|
||||
count,
|
||||
@@ -40,7 +53,7 @@ class PanelGroupItem extends Component {
|
||||
return (
|
||||
<button className={wrapperClassName} onClick={onLabelClick}>
|
||||
<div className={`${baseClass}__flexy`}>
|
||||
<Icon name={iconClassForLabel(item)} className={`${baseClass}__icon`} />
|
||||
{renderIcon()}
|
||||
<span className={`${baseClass}__name`}>
|
||||
{displayText}
|
||||
{description && <span className={`${baseClass}__description`}>{description}</span>}
|
||||
|
||||
+11
-6
@@ -11,21 +11,26 @@ describe('PanelGroupItem - component', () => {
|
||||
type: 'all',
|
||||
};
|
||||
|
||||
const component = mount(
|
||||
const labelComponent = mount(
|
||||
<PanelGroupItem item={validPanelGroupItem} />
|
||||
);
|
||||
|
||||
it('renders the icon', () => {
|
||||
const icon = component.find('i.kolidecon-hosts');
|
||||
const platformComponent = mount(
|
||||
<PanelGroupItem item={validPanelGroupItem} type="platform" />
|
||||
);
|
||||
|
||||
expect(icon.length).toEqual(1);
|
||||
it('renders the appropriate icon', () => {
|
||||
expect(labelComponent.find('PlatformIcon').length).toEqual(0);
|
||||
expect(labelComponent.find('Icon').length).toEqual(1);
|
||||
|
||||
expect(platformComponent.find('PlatformIcon').length).toEqual(1);
|
||||
});
|
||||
|
||||
it('renders the item text', () => {
|
||||
expect(component.text()).toContain(validPanelGroupItem.display_text);
|
||||
expect(labelComponent.text()).toContain(validPanelGroupItem.display_text);
|
||||
});
|
||||
|
||||
it('renders the item count', () => {
|
||||
expect(component.text()).toContain(validPanelGroupItem.count);
|
||||
expect(labelComponent.text()).toContain(validPanelGroupItem.count);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import SecondarySidePanelContainer from '../SecondarySidePanelContainer';
|
||||
|
||||
const baseClass = 'pack-info-side-panel';
|
||||
|
||||
@@ -2,9 +2,9 @@ import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import osqueryTableInterface from 'interfaces/osquery_table';
|
||||
import { osqueryTableNames } from 'utilities/osquery_tables';
|
||||
import iconClassForLabel from 'utilities/icon_class_for_label';
|
||||
import Dropdown from 'components/forms/fields/Dropdown';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import PlatformIcon from 'components/icons/PlatformIcon';
|
||||
import SecondarySidePanelContainer from '../SecondarySidePanelContainer';
|
||||
|
||||
import {
|
||||
@@ -43,7 +43,7 @@ class QuerySidePanel extends Component {
|
||||
return false;
|
||||
}
|
||||
|
||||
onSelectTable = ({ value }) => {
|
||||
onSelectTable = (value) => {
|
||||
const { onOsqueryTableSelect } = this.props;
|
||||
|
||||
onOsqueryTableSelect(value);
|
||||
@@ -140,7 +140,11 @@ class QuerySidePanel extends Component {
|
||||
<h2 className={`${baseClass}__header`}>OS Availability</h2>
|
||||
<ul className={`${baseClass}__platforms`}>
|
||||
{platformArr.map((os, idx) => {
|
||||
return <li key={idx}><Icon name={iconClassForLabel(os)} /> {os.display_text}</li>;
|
||||
if (os.type === 'all') {
|
||||
return <li key={idx}><Icon name="hosts" /> {os.display_text}</li>;
|
||||
}
|
||||
|
||||
return <li key={idx}><PlatformIcon name={os.type} /> {os.display_text}</li>;
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('QuerySidePanel - component', () => {
|
||||
|
||||
it('calls the onOsqueryTableSelect prop when a new table is selected in the dropdown', () => {
|
||||
const component = mount(<QuerySidePanel {...props} />);
|
||||
component.node.onSelectTable({ value: 'groups' });
|
||||
component.node.onSelectTable('groups');
|
||||
|
||||
expect(onOsqueryTableSelect).toHaveBeenCalledWith('groups');
|
||||
});
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import React, { Component, PropTypes } from 'react';
|
||||
import AceEditor from 'react-ace';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import queryInterface from 'interfaces/query';
|
||||
import Dropdown from 'components/forms/fields/Dropdown';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import classnames from 'classnames';
|
||||
|
||||
import configInterface from 'interfaces/config';
|
||||
import userInterface from 'interfaces/user';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
|
||||
import kolideLogo from '../../../../assets/images/kolide-logo.svg';
|
||||
import UserMenu from './UserMenu';
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import Avatar from 'components/Avatar';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
|
||||
class UserMenu extends Component {
|
||||
static propTypes = {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import userInterface from 'interfaces/user';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
|
||||
import navItems from './navItems';
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from 'redux/nodes/components/ForgotPasswordPage/actions';
|
||||
import debounce from 'utilities/debounce';
|
||||
import ForgotPasswordForm from 'components/forms/ForgotPasswordForm';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import StackedWhiteBoxes from 'components/StackedWhiteBoxes';
|
||||
|
||||
export class ForgotPasswordPage extends Component {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
|
||||
class LoginSuccessfulPage extends Component {
|
||||
static propTypes = {
|
||||
|
||||
@@ -6,7 +6,7 @@ import moment from 'moment';
|
||||
import Avatar from 'components/Avatar';
|
||||
import Button from 'components/buttons/Button';
|
||||
import ChangePasswordForm from 'components/forms/ChangePasswordForm';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import { logoutUser } from 'redux/nodes/auth/actions';
|
||||
import Modal from 'components/modals/Modal';
|
||||
import { renderFlash } from 'redux/nodes/notifications/actions';
|
||||
|
||||
@@ -12,7 +12,7 @@ import HostDetails from 'components/hosts/HostDetails';
|
||||
import hostInterface from 'interfaces/host';
|
||||
import HostSidePanel from 'components/side_panels/HostSidePanel';
|
||||
import HostsTable from 'components/hosts/HostsTable';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import osqueryTableInterface from 'interfaces/osquery_table';
|
||||
import paths from 'router/paths';
|
||||
import QueryComposer from 'components/queries/QueryComposer';
|
||||
|
||||
@@ -4,7 +4,7 @@ import { noop } from 'lodash';
|
||||
import classnames from 'classnames';
|
||||
|
||||
import { renderFlash } from 'redux/nodes/notifications/actions';
|
||||
import Icon from 'components/Icon';
|
||||
import Icon from 'components/icons/Icon';
|
||||
import { copyText } from './helpers';
|
||||
import AnsibleImage from '../../../../assets/images/Ansible.png';
|
||||
import ChefImage from '../../../../assets/images/Chef.png';
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
content: '\f060'
|
||||
}
|
||||
|
||||
.kolidecon-penguin:before {
|
||||
.kolidecon-linux:before {
|
||||
content: '\f061'
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,6 @@ export const iconClassForLabel = (label) => {
|
||||
case 'offline': return 'offline';
|
||||
case 'online': return 'success-check';
|
||||
case 'mia': return 'mia';
|
||||
case 'macos': return 'apple';
|
||||
case 'centos': return 'centos';
|
||||
case 'ubuntu': return 'ubuntu';
|
||||
case 'windows': return 'windows';
|
||||
case 'unknown': return 'single-host';
|
||||
default: return 'label';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user