Allow users to select multiple platforms for pack query (#1074)
This commit is contained in:
committed by
Jason Meller
parent
8749633b85
commit
3ec6b10324
@@ -11,7 +11,7 @@ import validate from 'components/forms/ConfigurePackQueryForm/validate';
|
||||
const baseClass = 'configure-pack-query-form';
|
||||
const fieldNames = ['query_id', 'interval', 'logging_type', 'platform', 'version'];
|
||||
const platformOptions = [
|
||||
{ label: 'All', value: '' },
|
||||
{ label: 'All', value: 'all' },
|
||||
{ label: 'Windows', value: 'windows' },
|
||||
{ label: 'Linux', value: 'linux' },
|
||||
{ label: 'macOS', value: 'darwin' },
|
||||
@@ -73,6 +73,7 @@ class ConfigurePackQueryForm extends Component {
|
||||
options={platformOptions}
|
||||
placeholder="- - -"
|
||||
label="Platform"
|
||||
multi
|
||||
wrapperClassName={`${baseClass}__form-field ${baseClass}__form-field--platform`}
|
||||
/>
|
||||
<Dropdown
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('ConfigurePackQueryForm - component', () => {
|
||||
expect(spy).toHaveBeenCalledWith({
|
||||
interval: 123,
|
||||
logging_type: 'differential',
|
||||
platform: '',
|
||||
platform: 'all',
|
||||
query_id: 1,
|
||||
version: '',
|
||||
});
|
||||
|
||||
@@ -16,11 +16,12 @@ class Dropdown extends Component {
|
||||
error: PropTypes.string,
|
||||
label: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
labelClassName: PropTypes.string,
|
||||
multi: PropTypes.bool,
|
||||
name: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
options: PropTypes.arrayOf(dropdownOptionInterface).isRequired,
|
||||
placeholder: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
value: PropTypes.string,
|
||||
value: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
wrapperClassName: PropTypes.string,
|
||||
};
|
||||
|
||||
@@ -28,14 +29,19 @@ class Dropdown extends Component {
|
||||
onChange: noop,
|
||||
clearable: false,
|
||||
disabled: false,
|
||||
multi: false,
|
||||
name: 'targets',
|
||||
placeholder: 'Select One...',
|
||||
};
|
||||
|
||||
handleChange = ({ value }) => {
|
||||
const { onChange } = this.props;
|
||||
handleChange = (selected) => {
|
||||
const { multi, onChange } = this.props;
|
||||
|
||||
return onChange(value);
|
||||
if (multi) {
|
||||
return onChange(selected.map(obj => obj.value).join(','));
|
||||
}
|
||||
|
||||
return onChange(selected.value);
|
||||
};
|
||||
|
||||
renderLabel = () => {
|
||||
@@ -62,7 +68,7 @@ class Dropdown extends Component {
|
||||
|
||||
render () {
|
||||
const { handleChange } = this;
|
||||
const { error, className, clearable, disabled, name, options, placeholder, value, wrapperClassName } = this.props;
|
||||
const { error, className, clearable, disabled, multi, name, options, placeholder, value, wrapperClassName } = this.props;
|
||||
|
||||
const formFieldProps = pick(this.props, ['hint', 'label', 'error', 'name']);
|
||||
const selectClasses = classnames(className, `${baseClass}__select`, {
|
||||
@@ -75,6 +81,7 @@ class Dropdown extends Component {
|
||||
className={selectClasses}
|
||||
clearable={clearable}
|
||||
disabled={disabled}
|
||||
multi={multi}
|
||||
name={`${name}-select`}
|
||||
onChange={handleChange}
|
||||
options={options}
|
||||
|
||||
@@ -36,6 +36,47 @@
|
||||
|
||||
.Select-value {
|
||||
font-size: $medium;
|
||||
border-radius: 2px;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 2px 0 0 #b8c2e3;
|
||||
border: solid 1px #b8c2e3;
|
||||
|
||||
.Select-value-icon {
|
||||
border: 0;
|
||||
float: right;
|
||||
visibility: hidden;
|
||||
position: relative;
|
||||
line-height: 28px;
|
||||
width: 25px;
|
||||
padding: 0;
|
||||
margin: 0 5px;
|
||||
|
||||
&::after {
|
||||
@extend %kolidecon;
|
||||
@include transition(color 150ms ease-in-out);
|
||||
@include transform(translate(-50%, -50%));
|
||||
content: '\f036';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
visibility: visible;
|
||||
font-size: 16px;
|
||||
color: $accent-dark;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
color: $accent-text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Select-value-label {
|
||||
font-size: 16px;
|
||||
font-weight: $normal;
|
||||
color: $text-dark;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
&--single {
|
||||
@@ -124,6 +165,21 @@
|
||||
}
|
||||
|
||||
&.Select--multi {
|
||||
.Select-control {
|
||||
@include display(flex);
|
||||
@include align-items(center);
|
||||
height: auto;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.Select-multi-value-wrapper {
|
||||
@include flex-grow(1);
|
||||
}
|
||||
|
||||
.Select-arrow-zone {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.Select-option {
|
||||
&.is-disabled {
|
||||
color: $text-dark;
|
||||
@@ -135,5 +191,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.Select-value {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.Select-value-label {
|
||||
padding: 0 0 0 1rem;
|
||||
}
|
||||
|
||||
&.has-value {
|
||||
.Select-multi-value-wrapper {
|
||||
padding: 5px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,10 @@ export class PlatformIcon extends Component {
|
||||
const { className, name, fw, size, title } = this.props;
|
||||
const iconClasses = classnames(baseClass, className);
|
||||
const iconName = platformIconClass(name);
|
||||
const properNameCase = name.charAt(0).toUpperCase() + name.slice(1);
|
||||
|
||||
if (!iconName) {
|
||||
return <span className={iconClasses}>{name || 'All'}</span>;
|
||||
return <span className={iconClasses}>{properNameCase || 'All'}</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
+14
-3
@@ -42,10 +42,21 @@ class ScheduledQueriesListItem extends Component {
|
||||
return 'bold-plus';
|
||||
}
|
||||
|
||||
renderPlatformIcon = () => {
|
||||
const { scheduledQuery: { platform } } = this.props;
|
||||
const platformArr = platform.split(',');
|
||||
|
||||
if (platformArr.includes('all')) {
|
||||
return <PlatformIcon name="" />;
|
||||
}
|
||||
|
||||
return platformArr.map((pltf, idx) => <PlatformIcon name={pltf} key={`${idx}-${pltf}`} />);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { checked, disabled, scheduledQuery } = this.props;
|
||||
const { onCheck } = this;
|
||||
const { id, name, interval, platform, version } = scheduledQuery;
|
||||
const { onCheck, renderPlatformIcon } = this;
|
||||
const { id, name, interval, version } = scheduledQuery;
|
||||
const { loggingTypeString } = this;
|
||||
|
||||
return (
|
||||
@@ -60,7 +71,7 @@ class ScheduledQueriesListItem extends Component {
|
||||
</td>
|
||||
<td className="scheduled-queries-list__query-name">{name}</td>
|
||||
<td>{interval}</td>
|
||||
<td><PlatformIcon name={platform} /></td>
|
||||
<td>{renderPlatformIcon()}</td>
|
||||
<td>{version ? `${version}+` : 'Any'}</td>
|
||||
<td><Icon name={loggingTypeString()} /></td>
|
||||
</tr>
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@ class SearchPackQuery extends Component {
|
||||
return (
|
||||
<div className={`${baseClass}__description`}>
|
||||
<h2>description</h2>
|
||||
<p>{selectedQuery.description}</p>
|
||||
<p>{selectedQuery.description || <em>No description available.</em>}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -160,6 +160,10 @@ export class EditPackPage extends Component {
|
||||
}
|
||||
|
||||
handleConfigurePackQuerySubmit = (formData) => {
|
||||
if (formData.platform.indexOf('all') !== -1) {
|
||||
formData.platform = '';
|
||||
}
|
||||
|
||||
const { create } = scheduledQueryActions;
|
||||
const { dispatch, packID } = this.props;
|
||||
const scheduledQueryData = {
|
||||
|
||||
Reference in New Issue
Block a user