Refactor form fields (#636)
This commit is contained in:
@@ -110,10 +110,10 @@ $base-class: 'button';
|
||||
padding: $medium;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
box-shadow: inset 0 -3px 0px 0 rgba(0, 0, 0, 0.25), 0 -2px 3px 0 rgba(0, 0, 0, 0.15);
|
||||
box-shadow: inset 0 -3px 0 0 rgba(0, 0, 0, 0.25), 0 -2px 3px 0 rgba(0, 0, 0, 0.15);
|
||||
|
||||
&:active {
|
||||
box-shadow: 0 1px 0 #734893, 0 -2px 0 #D1D9E9;
|
||||
box-shadow: 0 1px 0 #734893, 0 -2px 0 #d1d9e9;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,43 +8,54 @@ class Rocker extends Component {
|
||||
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
handleChange: PropTypes.func,
|
||||
name: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
options: PropTypes.shape({
|
||||
aText: PropTypes.string,
|
||||
aIcon: PropTypes.string,
|
||||
bText: PropTypes.string,
|
||||
bIcon: PropTypes.string,
|
||||
rightText: PropTypes.string,
|
||||
rightIcon: PropTypes.string,
|
||||
leftText: PropTypes.string,
|
||||
leftIcon: PropTypes.string,
|
||||
}),
|
||||
value: PropTypes.string,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
handleChange: noop,
|
||||
onChange: noop,
|
||||
};
|
||||
|
||||
handleChange = (evt) => {
|
||||
const { onChange, options: { rightText, leftText }, value } = this.props;
|
||||
evt.preventDefault();
|
||||
|
||||
const newOption = value === leftText ? rightText : leftText;
|
||||
|
||||
onChange(newOption);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { className, handleChange, name, options, value } = this.props;
|
||||
const { aText, aIcon, bText, bIcon } = options;
|
||||
const { handleChange } = this;
|
||||
const { className, options, value } = this.props;
|
||||
const { rightText, rightIcon, leftText, leftIcon } = options;
|
||||
const baseClass = 'kolide-rocker';
|
||||
|
||||
const rockerClasses = classnames(baseClass, className);
|
||||
const buttonClasses = classnames(`${baseClass}__button`, 'button', 'button--unstyled', {
|
||||
[`${baseClass}__button--checked`]: value === leftText,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={rockerClasses}>
|
||||
<label className={`${baseClass}__label`} htmlFor={name}>
|
||||
<input className={`${baseClass}__checkbox`} type="checkbox" value={value} name={name} id={name} onChange={handleChange} checked={value === bText} />
|
||||
<span className={`${baseClass}__switch ${baseClass}__switch--opt-b`}>
|
||||
<button className={buttonClasses} onClick={handleChange}>
|
||||
<span className={`${baseClass}__switch ${baseClass}__switch--left`}>
|
||||
<span className={`${baseClass}__text`}>
|
||||
<Icon name={bIcon} /> {bText}
|
||||
<Icon name={leftIcon} /> {leftText}
|
||||
</span>
|
||||
</span>
|
||||
<span className={`${baseClass}__switch ${baseClass}__switch--opt-a`}>
|
||||
<span className={`${baseClass}__switch ${baseClass}__switch--right`}>
|
||||
<span className={`${baseClass}__text`}>
|
||||
<Icon name={aIcon} /> {aText}
|
||||
<Icon name={rightIcon} /> {rightText}
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
.kolide-rocker {
|
||||
box-shadow: 0 0 9px 0 rgba(72, 81, 109, 0.1);
|
||||
|
||||
&__label {
|
||||
&__button {
|
||||
@include transform(translateY(-19px));
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
width: 180px;
|
||||
@@ -10,13 +11,10 @@
|
||||
background-color: #9fa5ab;
|
||||
display: block;
|
||||
padding: 0 2px;
|
||||
box-shadow: inset 0 -3px 3px #aab3bd;
|
||||
}
|
||||
background: transparent;
|
||||
border: 0;
|
||||
|
||||
&__checkbox {
|
||||
display: none;
|
||||
|
||||
&:checked ~ .kolide-rocker__switch--opt-b {
|
||||
&--checked > .kolide-rocker__switch--left {
|
||||
span {
|
||||
@include transform(skewX(0) rotateZ(0));
|
||||
top: 3px;
|
||||
@@ -31,7 +29,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:checked ~ .kolide-rocker__switch--opt-a {
|
||||
&--checked > .kolide-rocker__switch--right {
|
||||
span {
|
||||
@include transform(skewX(-6deg) rotateZ(-6deg));
|
||||
top: -6px;
|
||||
@@ -92,7 +90,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&--opt-b {
|
||||
&--left {
|
||||
@include linear-gradient(-180deg, #eaedfb 81%, #aab3bd 100%);
|
||||
left: 2px;
|
||||
|
||||
@@ -113,7 +111,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&--opt-a {
|
||||
&--right {
|
||||
@include linear-gradient(-180deg, #9651ca 81%, #6e3c93 100%);
|
||||
right: 2px;
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const Slider = ({ onClick, engaged }) => {
|
||||
const baseClass = 'slider-wrap';
|
||||
|
||||
const sliderBtnClass = classnames(
|
||||
baseClass,
|
||||
{ [`${baseClass}--active`]: engaged }
|
||||
);
|
||||
|
||||
const sliderDotClass = classnames(
|
||||
`${baseClass}__dot`,
|
||||
{ [`${baseClass}__dot--active`]: engaged }
|
||||
);
|
||||
|
||||
return (
|
||||
<button className={`button button--unstyled ${sliderBtnClass}`} onClick={onClick}>
|
||||
<div className={sliderDotClass} />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
Slider.propTypes = {
|
||||
engaged: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Slider;
|
||||
@@ -1,29 +0,0 @@
|
||||
.slider-wrap {
|
||||
@include transition(background-color 400ms ease-in-out);
|
||||
background-color: $text-medium;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #eaeaea;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 22px;
|
||||
min-width: 40px;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
|
||||
&--active {
|
||||
background-color: $brand;
|
||||
}
|
||||
|
||||
&__dot {
|
||||
@include transition(lest 300ms ease-in-out);
|
||||
@include size(14px);
|
||||
@include position(absolute, 0 null null 5px);
|
||||
margin-top: 3px;
|
||||
border-radius: 50%;
|
||||
background-color: $white;
|
||||
|
||||
&--active {
|
||||
left: 21px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
const baseClass = 'form-field';
|
||||
|
||||
class FormField extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.element,
|
||||
className: PropTypes.string,
|
||||
error: PropTypes.string,
|
||||
hint: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
label: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
renderLabel = () => {
|
||||
const { error, label, name } = this.props;
|
||||
const labelWrapperClasses = classnames(
|
||||
`${baseClass}__label`,
|
||||
{ [`${baseClass}__label--error`]: error }
|
||||
);
|
||||
|
||||
if (!label) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
<label className={labelWrapperClasses} htmlFor={name}>
|
||||
{error || label}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
||||
renderHint = () => {
|
||||
const { hint } = this.props;
|
||||
|
||||
if (hint) {
|
||||
return <span className={`${baseClass}__hint`}>{hint}</span>;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
render () {
|
||||
const { renderLabel, renderHint } = this;
|
||||
const { children, className, type } = this.props;
|
||||
|
||||
const formFieldClass = classnames(baseClass, className, {
|
||||
[`${baseClass}--${type}`]: type,
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={formFieldClass}>
|
||||
{renderLabel()}
|
||||
{children}
|
||||
{renderHint()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default FormField;
|
||||
@@ -0,0 +1,33 @@
|
||||
.form-field {
|
||||
margin-bottom: $pad-small;
|
||||
|
||||
&__label {
|
||||
font-size: 16px;
|
||||
font-weight: $bold;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
letter-spacing: -0.5px;
|
||||
color: $text-dark;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
|
||||
&--error {
|
||||
color: $alert;
|
||||
}
|
||||
}
|
||||
|
||||
&__hint {
|
||||
font-size: 14px;
|
||||
font-weight: $normal;
|
||||
line-height: 1.57;
|
||||
letter-spacing: 1px;
|
||||
color: $accent-text;
|
||||
|
||||
code {
|
||||
color: $brand-light;
|
||||
background-color: $accent-light;
|
||||
padding: 2px;
|
||||
font-family: 'SourceCodePro', $monospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export default from './FormField';
|
||||
@@ -135,6 +135,7 @@ class InviteUserForm extends Component {
|
||||
autofocus
|
||||
error={errors.name}
|
||||
name="name"
|
||||
iconName="username"
|
||||
onChange={onInputChange('name')}
|
||||
placeholder="Name"
|
||||
value={name}
|
||||
@@ -142,6 +143,7 @@ class InviteUserForm extends Component {
|
||||
<InputFieldWithIcon
|
||||
error={errors.email}
|
||||
name="email"
|
||||
iconName="email"
|
||||
onChange={onInputChange('email')}
|
||||
placeholder="Email"
|
||||
value={email}
|
||||
|
||||
@@ -1,33 +1,50 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { noop } from 'lodash';
|
||||
import { noop, pick } from 'lodash';
|
||||
|
||||
import FormField from 'components/forms/FormField';
|
||||
|
||||
const baseClass = 'kolide-checkbox';
|
||||
|
||||
class InputField extends Component {
|
||||
class Checkbox extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
error: PropTypes.string,
|
||||
hint: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
label: PropTypes.string,
|
||||
value: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onChange: noop,
|
||||
};
|
||||
|
||||
handleChange = () => {
|
||||
const { onChange, value } = this.props;
|
||||
|
||||
return onChange(!value);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { children, className, name, onChange } = this.props;
|
||||
const { handleChange } = this;
|
||||
const { children, className, name, value } = this.props;
|
||||
const checkBoxClass = classnames(baseClass, className);
|
||||
|
||||
const formFieldProps = pick(this.props, ['hint', 'label', 'error', 'name']);
|
||||
|
||||
return (
|
||||
<label htmlFor={name} className={checkBoxClass}>
|
||||
<input type="checkbox" name={name} id={name} className={`${checkBoxClass}__input`} onChange={onChange} />
|
||||
<span className={`${checkBoxClass}__tick`} />
|
||||
{children}
|
||||
</label>
|
||||
<FormField {...formFieldProps} type="checkbox">
|
||||
<label htmlFor={name} className={checkBoxClass}>
|
||||
<input type="checkbox" name={name} id={name} className={`${checkBoxClass}__input`} onChange={handleChange} checked={value} />
|
||||
<span className={`${checkBoxClass}__tick`} />
|
||||
<div className={`${checkBoxClass}__label`}>{children}</div>
|
||||
</label>
|
||||
</FormField>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default InputField;
|
||||
export default Checkbox;
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
.kolide-checkbox {
|
||||
@include clearfix;
|
||||
position: relative;
|
||||
|
||||
&__input {
|
||||
visibility: hidden;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
|
||||
&:checked + .kolide-checkbox__tick {
|
||||
&::after {
|
||||
@@ -42,4 +46,15 @@
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 13px;
|
||||
font-weight: $normal;
|
||||
line-height: 20px;
|
||||
letter-spacing: 0.5px;
|
||||
color: $text-medium;
|
||||
display: inline-block;
|
||||
padding-left: 15px;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,55 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import Select from 'react-select';
|
||||
import { noop } from 'lodash';
|
||||
import { noop, pick } from 'lodash';
|
||||
|
||||
import dropdownOptionInterface from 'interfaces/dropdownOption';
|
||||
import FormField from 'components/forms/FormField';
|
||||
|
||||
const baseClass = 'input-dropdown';
|
||||
|
||||
class Dropdown extends Component {
|
||||
static propTypes = {
|
||||
options: PropTypes.arrayOf(dropdownOptionInterface).isRequired,
|
||||
onSelect: PropTypes.func,
|
||||
onChange: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
error: PropTypes.string,
|
||||
hint: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
label: PropTypes.string,
|
||||
placeholder: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
clearable: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onSelect: noop,
|
||||
onChange: noop,
|
||||
clearable: false,
|
||||
placeholder: 'Select One...',
|
||||
};
|
||||
|
||||
handleChange = ({ value }) => {
|
||||
const { onChange } = this.props;
|
||||
|
||||
return onChange(value);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { options, className, placeholder, value, clearable, onSelect } = this.props;
|
||||
const { handleChange } = this;
|
||||
const { options, className, placeholder, value, clearable } = this.props;
|
||||
|
||||
const formFieldProps = pick(this.props, ['hint', 'label', 'error', 'name']);
|
||||
|
||||
return (
|
||||
<Select
|
||||
className={className}
|
||||
name="targets"
|
||||
options={options}
|
||||
onChange={onSelect}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
clearable={clearable}
|
||||
/>
|
||||
<FormField {...formFieldProps} type="dropdown">
|
||||
<Select
|
||||
className={`${baseClass}__select ${className}`}
|
||||
name="targets"
|
||||
options={options}
|
||||
onChange={handleChange}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
clearable={clearable}
|
||||
/>
|
||||
</FormField>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,3 +87,24 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-dropdown {
|
||||
&__wrapper {
|
||||
margin-bottom: $pad-base;
|
||||
}
|
||||
|
||||
&__hint {
|
||||
font-size: 14px;
|
||||
font-weight: $normal;
|
||||
line-height: 1.57;
|
||||
letter-spacing: 1px;
|
||||
color: $accent-text;
|
||||
|
||||
code {
|
||||
color: $brand-light;
|
||||
background-color: $accent-light;
|
||||
padding: 2px;
|
||||
font-family: 'SourceCodePro', $monospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { pick } from 'lodash';
|
||||
|
||||
import FormField from 'components/forms/FormField';
|
||||
|
||||
const baseClass = 'input-field';
|
||||
|
||||
@@ -7,6 +10,7 @@ class InputField extends Component {
|
||||
static propTypes = {
|
||||
autofocus: PropTypes.bool,
|
||||
error: PropTypes.string,
|
||||
hint: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
inputClassName: PropTypes.string, // eslint-disable-line react/forbid-prop-types
|
||||
inputWrapperClass: PropTypes.string,
|
||||
inputOptions: PropTypes.object, // eslint-disable-line react/forbid-prop-types
|
||||
@@ -49,43 +53,21 @@ class InputField extends Component {
|
||||
return onChange(value);
|
||||
}
|
||||
|
||||
renderLabel = () => {
|
||||
const { error, label, labelClassName, name } = this.props;
|
||||
const labelWrapperClasses = classnames(
|
||||
`${baseClass}__label`,
|
||||
labelClassName,
|
||||
{ [`${baseClass}__label--error`]: error }
|
||||
);
|
||||
|
||||
if (!label) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
<label
|
||||
className={labelWrapperClasses}
|
||||
htmlFor={name}
|
||||
>
|
||||
{error || label}
|
||||
</label>
|
||||
);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { error, inputClassName, inputOptions, inputWrapperClass, name, placeholder, type, value } = this.props;
|
||||
const { onInputChange, renderLabel } = this;
|
||||
const { onInputChange } = this;
|
||||
const shouldShowPasswordClass = type === 'password';
|
||||
const inputClasses = classnames(baseClass, inputClassName, {
|
||||
[`${baseClass}--password`]: shouldShowPasswordClass,
|
||||
[`${baseClass}--error`]: error,
|
||||
[`${baseClass}__textarea`]: type === 'textarea',
|
||||
});
|
||||
const inputWrapperClasses = classnames(`${baseClass}__wrapper`, inputWrapperClass);
|
||||
|
||||
const formFieldProps = pick(this.props, ['hint', 'label', 'error', 'name']);
|
||||
|
||||
if (type === 'textarea') {
|
||||
return (
|
||||
<div className={inputWrapperClasses}>
|
||||
{renderLabel()}
|
||||
<FormField {...formFieldProps} type="textarea" className={inputWrapperClass}>
|
||||
<textarea
|
||||
name={name}
|
||||
onChange={onInputChange}
|
||||
@@ -96,13 +78,12 @@ class InputField extends Component {
|
||||
{...inputOptions}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={inputWrapperClasses}>
|
||||
{renderLabel()}
|
||||
<FormField {...formFieldProps} type="input" className={inputWrapperClass}>
|
||||
<input
|
||||
name={name}
|
||||
onChange={onInputChange}
|
||||
@@ -113,7 +94,7 @@ class InputField extends Component {
|
||||
{...inputOptions}
|
||||
value={value}
|
||||
/>
|
||||
</div>
|
||||
</FormField>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
background-color: $white;
|
||||
border: solid 1px $accent-medium;
|
||||
font-size: 16px;
|
||||
padding: $pad-xsmall $pad-base;
|
||||
padding: $pad-xsmall 12px;
|
||||
color: $text-dark;
|
||||
font-family: 'Oxygen', sans-serif;
|
||||
box-sizing: border-box;
|
||||
@@ -18,6 +18,7 @@
|
||||
&:focus {
|
||||
outline: none;
|
||||
box-shadow: inset 0 0 8px 0 rgba($black, 0.1);
|
||||
border-color: $link-light;
|
||||
border-bottom-color: $brand;
|
||||
}
|
||||
|
||||
@@ -60,4 +61,19 @@
|
||||
&__wrapper {
|
||||
margin-bottom: $pad-base;
|
||||
}
|
||||
|
||||
&__hint {
|
||||
font-size: 14px;
|
||||
font-weight: $normal;
|
||||
line-height: 1.57;
|
||||
letter-spacing: 1px;
|
||||
color: $accent-text;
|
||||
|
||||
code {
|
||||
color: $brand-light;
|
||||
background-color: $accent-light;
|
||||
padding: 2px;
|
||||
font-family: 'SourceCodePro', $monospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { pick } from 'lodash';
|
||||
|
||||
import FormField from 'components/forms/FormField';
|
||||
|
||||
const Slider = ({ onChange, value, inactiveText = 'Off', activeText = 'On' }) => {
|
||||
const baseClass = 'kolide-slider';
|
||||
|
||||
const sliderBtnClass = classnames(
|
||||
baseClass,
|
||||
{ [`${baseClass}--active`]: value }
|
||||
);
|
||||
|
||||
const sliderDotClass = classnames(
|
||||
`${baseClass}__dot`,
|
||||
{ [`${baseClass}__dot--active`]: value }
|
||||
);
|
||||
|
||||
const handleClick = (evt) => {
|
||||
evt.preventDefault();
|
||||
|
||||
return onChange(!value);
|
||||
};
|
||||
|
||||
const formFieldProps = pick(this.props, ['hint', 'label', 'error', 'name']);
|
||||
|
||||
return (
|
||||
<FormField {...formFieldProps} type="slider">
|
||||
<span className={`${baseClass}__label ${baseClass}__label--inactive`}>{inactiveText}</span>
|
||||
<button className={`button button--unstyled ${sliderBtnClass}`} onClick={handleClick}>
|
||||
<div className={sliderDotClass} />
|
||||
</button>
|
||||
<span className={`${baseClass}__label ${baseClass}__label--active`}>{activeText}</span>
|
||||
</FormField>
|
||||
);
|
||||
};
|
||||
|
||||
Slider.propTypes = {
|
||||
value: PropTypes.bool,
|
||||
onChange: PropTypes.func,
|
||||
inactiveText: PropTypes.string,
|
||||
activeText: PropTypes.string,
|
||||
error: PropTypes.string,
|
||||
hint: PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
||||
label: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Slider;
|
||||
@@ -0,0 +1,60 @@
|
||||
.kolide-slider {
|
||||
@include transition(background-color 150ms ease-in-out);
|
||||
background-color: $text-medium;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #eaeaea;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 22px;
|
||||
min-width: 40px;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
box-shadow: inset 0 1px 6px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
&:hover {
|
||||
background-color: $text-medium;
|
||||
box-shadow: inset 0 1px 6px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
&--active {
|
||||
background-color: $brand-light;
|
||||
|
||||
&:hover {
|
||||
background-color: $brand-light;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&__wrapper {
|
||||
margin-bottom: $pad-base;
|
||||
}
|
||||
|
||||
&__dot {
|
||||
@include transition(left 150ms ease-in-out);
|
||||
@include size(14px);
|
||||
@include position(absolute, 0 null null 5px);
|
||||
margin-top: 3px;
|
||||
border-radius: 50%;
|
||||
background-color: $white;
|
||||
box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.25);
|
||||
|
||||
&--active {
|
||||
left: 21px;
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 18px;
|
||||
font-weight: $light;
|
||||
letter-spacing: 1.3px;
|
||||
text-align: left;
|
||||
vertical-align: text-bottom;
|
||||
text-transform: uppercase;
|
||||
margin: 0 10px;
|
||||
color: $text-light;
|
||||
|
||||
&--active {
|
||||
color: $brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,7 +226,7 @@ class QueryForm extends Component {
|
||||
return (
|
||||
<Dropdown
|
||||
options={platformOptions}
|
||||
onSelect={onFieldChange('platform')}
|
||||
onChange={onFieldChange('platform')}
|
||||
value={platform.value}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -9,20 +9,25 @@
|
||||
}
|
||||
|
||||
&__select-targets {
|
||||
font-size: $base;
|
||||
float: left;
|
||||
}
|
||||
|
||||
&__target-label {
|
||||
margin: 0;
|
||||
font-size: $base;
|
||||
font-weight: $light;
|
||||
font-size: 16px;
|
||||
font-weight: $bold;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
letter-spacing: -0.5px;
|
||||
color: $text-dark;
|
||||
margin-bottom: $pad-xsmall;
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&__targets-count {
|
||||
font-size: $small;
|
||||
margin-left: $xsmall;
|
||||
color: $brand;
|
||||
}
|
||||
|
||||
&__text-editor-wrapper {
|
||||
|
||||
@@ -129,7 +129,7 @@ class QuerySidePanel extends Component {
|
||||
<Dropdown
|
||||
options={tableNames}
|
||||
value={selectedOsqueryTable.name}
|
||||
onSelect={onSelectTable}
|
||||
onChange={onSelectTable}
|
||||
placeholder="Choose Table..."
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -91,7 +91,7 @@ class UserBlock extends Component {
|
||||
<Dropdown
|
||||
options={userActionOptions}
|
||||
placeholder="Actions..."
|
||||
onSelect={onUserActionSelect}
|
||||
onChange={onUserActionSelect}
|
||||
className={invite ? 'revoke-invite' : ''}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -2,16 +2,16 @@ import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { first, isEqual, size } from 'lodash';
|
||||
|
||||
import entityGetter from '../../../redux/utilities/entityGetter';
|
||||
import Button from '../../../components/buttons/Button';
|
||||
import inviteActions from '../../../redux/nodes/entities/invites/actions';
|
||||
import inviteInterface from '../../../interfaces/invite';
|
||||
import InviteUserForm from '../../../components/forms/InviteUserForm';
|
||||
import Modal from '../../../components/modals/Modal';
|
||||
import userActions from '../../../redux/nodes/entities/users/actions';
|
||||
import entityGetter from 'redux/utilities/entityGetter';
|
||||
import Button from 'components/buttons/Button';
|
||||
import inviteActions from 'redux/nodes/entities/invites/actions';
|
||||
import inviteInterface from 'interfaces/invite';
|
||||
import InviteUserForm from 'components/forms/InviteUserForm';
|
||||
import Modal from 'components/modals/Modal';
|
||||
import userActions from 'redux/nodes/entities/users/actions';
|
||||
import userInterface from 'interfaces/user';
|
||||
import { renderFlash } from 'redux/nodes/notifications/actions';
|
||||
import UserBlock from './UserBlock';
|
||||
import userInterface from '../../../interfaces/user';
|
||||
import { renderFlash } from '../../../redux/nodes/notifications/actions';
|
||||
|
||||
class UserManagementPage extends Component {
|
||||
static propTypes = {
|
||||
|
||||
@@ -18,7 +18,7 @@ export class HomePage extends Component {
|
||||
const baseClass = 'home-page';
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<div className={`${baseClass} body-wrap`}>
|
||||
{user && <Avatar size="small" className={`${baseClass}__avatar`} user={user} />}
|
||||
<span>You are successfully logged in! </span>
|
||||
{user && <Link to={LOGOUT}>Logout</Link>}
|
||||
|
||||
@@ -156,11 +156,10 @@ export class ManageHostsPage extends Component {
|
||||
return false;
|
||||
}
|
||||
|
||||
onToggleDisplay = () => {
|
||||
const { dispatch, display } = this.props;
|
||||
const newDisplay = display === 'Grid' ? 'List' : 'Grid';
|
||||
onToggleDisplay = (val) => {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(setDisplay(newDisplay));
|
||||
dispatch(setDisplay(val));
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -175,10 +174,10 @@ export class ManageHostsPage extends Component {
|
||||
const { count, description, display_text: displayText, query } = selectedLabel;
|
||||
const { onToggleDisplay } = this;
|
||||
const buttonOptions = {
|
||||
aIcon: 'grid-select',
|
||||
aText: 'Grid',
|
||||
bIcon: 'list-select',
|
||||
bText: 'List',
|
||||
rightIcon: 'grid-select',
|
||||
rightText: 'Grid',
|
||||
leftIcon: 'list-select',
|
||||
leftText: 'List',
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -214,8 +213,7 @@ export class ManageHostsPage extends Component {
|
||||
<div className={`${baseClass}__topper`}>
|
||||
<p className={`${baseClass}__host-count`}>{count} Hosts Total</p>
|
||||
<Rocker
|
||||
handleChange={onToggleDisplay}
|
||||
name="host-display-toggle"
|
||||
onChange={onToggleDisplay}
|
||||
options={buttonOptions}
|
||||
value={display}
|
||||
/>
|
||||
|
||||
@@ -91,7 +91,7 @@ describe('ManageHostsPage - component', () => {
|
||||
const ownProps = { location: {}, params: {} };
|
||||
const component = connectedComponent(ConnectedManageHostsPage, { props: ownProps, mockStore });
|
||||
const page = mount(component);
|
||||
const button = page.find('Rocker').find('input');
|
||||
const button = page.find('Rocker').find('button');
|
||||
const toggleDisplayAction = {
|
||||
type: 'SET_DISPLAY',
|
||||
payload: {
|
||||
@@ -99,7 +99,7 @@ describe('ManageHostsPage - component', () => {
|
||||
},
|
||||
};
|
||||
|
||||
button.simulate('change');
|
||||
button.simulate('click');
|
||||
|
||||
expect(mockStore.getActions()).toInclude(toggleDisplayAction);
|
||||
});
|
||||
|
||||
@@ -76,7 +76,7 @@ button {
|
||||
font-family: 'Oxygen', sans-serif;
|
||||
|
||||
&:-webkit-autofill {
|
||||
-webkit-box-shadow: 0 0 0px 1000px white inset;
|
||||
-webkit-box-shadow: 0 0 0 1000px #fff inset;
|
||||
-webkit-text-fill-color: $text-dark !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user