fix(ui) - dropdown fixes

This commit is contained in:
Shekar Siri 2022-06-22 17:58:58 +02:00
parent c8ec85c98e
commit 188e504bb7
29 changed files with 44 additions and 883 deletions

View file

@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import { tokenRE } from 'Types/integrations/bugsnagConfig';
import { edit } from 'Duck/integrations/actions';
import { Dropdown } from 'UI';
import Select from 'Shared/Select';
import { withRequest } from 'HOCs';
@connect(state => ({
@ -50,7 +50,7 @@ export default class ProjectListDropdown extends React.PureComponent {
this.fetchProjectList();
}
}
onChange = (e, target) => {
onChange = (target) => {
if (typeof this.props.onChange === 'function') {
this.props.onChange({ target });
}
@ -65,11 +65,11 @@ export default class ProjectListDropdown extends React.PureComponent {
} = this.props;
const options = projects.map(({ name, id }) => ({ text: name, value: id }));
return (
<Dropdown
selection
<Select
// selection
options={ options }
name={ name }
value={ value }
value={ options.find(o => o.value === value) }
placeholder={ placeholder }
onChange={ this.onChange }
loading={ loading }

View file

@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import { ACCESS_KEY_ID_LENGTH, SECRET_ACCESS_KEY_LENGTH } from 'Types/integrations/cloudwatchConfig';
import { edit } from 'Duck/integrations/actions';
import { Dropdown } from 'UI';
import Select from 'Shared/Select';
import { withRequest } from 'HOCs';
@connect(state => ({
@ -48,7 +48,7 @@ export default class LogGroupDropdown extends React.PureComponent {
this.fetchLogGroups();
}
}
onChange = (e, target) => {
onChange = (target) => {
if (typeof this.props.onChange === 'function') {
this.props.onChange({ target });
}
@ -63,11 +63,11 @@ export default class LogGroupDropdown extends React.PureComponent {
} = this.props;
const options = values.map(g => ({ text: g, value: g }));
return (
<Dropdown
selection
<Select
// selection
options={ options }
name={ name }
value={ value }
value={ options.find(o => o.value === value) }
placeholder={ placeholder }
onChange={ this.onChange }
loading={ loading }

View file

@ -4,7 +4,8 @@ import cn from 'classnames';
import withPageTitle from 'HOCs/withPageTitle';
import {
Form, IconButton, SlideModal, Input, Button, Loader,
NoContent, Popup, CopyButton, Dropdown } from 'UI';
NoContent, Popup, CopyButton } from 'UI';
import Select from 'Shared/Select';
import { init, save, edit, remove as deleteMember, fetchList, generateInviteLink } from 'Duck/member';
import { fetchList as fetchRoles } from 'Duck/roles';
import styles from './manageUsers.module.css';
@ -39,7 +40,7 @@ class ManageUsers extends React.PureComponent {
state = { showModal: false, remaining: this.props.account.limits.teamMember.remaining, invited: false }
// writeOption = (e, { name, value }) => this.props.edit({ [ name ]: value });
onChange = (e, { name, value }) => this.props.edit({ [ name ]: value });
onChange = ({ name, value }) => this.props.edit({ [ name ]: value.value });
onChangeCheckbox = ({ target: { checked, name } }) => this.props.edit({ [ name ]: checked });
setFocus = () => this.focusElement && this.focusElement.focus();
closeModal = () => this.setState({ showModal: false });
@ -138,12 +139,12 @@ class ManageUsers extends React.PureComponent {
{ isEnterprise && (
<Form.Field>
<label htmlFor="role">{ 'Role' }</label>
<Dropdown
<Select
placeholder="Role"
selection
options={ roles }
name="roleId"
value={ member.roleId }
value={ roles.find(r => r.value === member.roleId) }
onChange={ this.onChange }
/>
</Form.Field>

View file

@ -127,7 +127,7 @@ const RoleForm = (props: Props) => {
isSearchable
name="permissions"
options={ permissions }
onChange={ ({ value }: any) => writeOption({ name: 'permissions', value }) }
onChange={ ({ value }: any) => writeOption({ name: 'permissions', value: value.value }) }
value={null}
/>
{ role.permissions.size > 0 && (

View file

@ -37,9 +37,14 @@ function CustomMetricTableErrors(props: RouteComponentProps<Props>) {
}, [errorId])
return (
<NoContent show={metric.data.errors && metric.data.errors === 0}>
<NoContent
title="No data found"
subtext=""
show={metric.data.errors && metric.data.errors === 0}
size="small"
>
{metric.data.errors && metric.data.errors.map((error: any, index: any) => (
<ErrorListItem error={error} onClick={() => onErrorClick(error)} />
<ErrorListItem key={index} error={error} onClick={() => onErrorClick(error)} />
))}
{isEdit && (

View file

@ -1,14 +0,0 @@
.wrapper {
background-color: $gray-light;
/* border: solid thin $gray-medium; */
border-radius: 3px;
padding: 20px;
}
.innerWapper {
border-radius: 3px;
width: 70%;
margin: 0 auto;
background-color: white;
min-height: 220px;
}

View file

@ -1,169 +0,0 @@
import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux';
import { Loader, NoContent, SegmentSelection } from 'UI';
import { Styles } from '../../common';
import Period from 'Types/app/period';
import stl from './CustomMetricWidgetPreview.module.css';
import { remove } from 'Duck/customMetrics';
import DateRange from 'Shared/DateRange';
import { edit } from 'Duck/customMetrics';
import CustomMetriLineChart from '../CustomMetriLineChart';
import CustomMetricPercentage from '../CustomMetricPercentage';
import CustomMetricTable from '../CustomMetricTable';
import CustomMetricPieChart from '../CustomMetricPieChart';
const customParams = (rangeName: string) => {
const params = { density: 70 }
// if (rangeName === LAST_24_HOURS) params.density = 70
// if (rangeName === LAST_30_MINUTES) params.density = 70
// if (rangeName === YESTERDAY) params.density = 70
// if (rangeName === LAST_7_DAYS) params.density = 70
return params
}
interface Props {
metric: any;
data?: any;
onClickEdit?: (e) => void;
remove: (id) => void;
edit: (metric) => void;
}
function CustomMetricWidget(props: Props) {
const { metric } = props;
const [loading, setLoading] = useState(false)
const [data, setData] = useState<any>({ chart: [{}] })
const [period, setPeriod] = useState(Period({ rangeName: metric.rangeName, startDate: metric.startDate, endDate: metric.endDate }));
const colors = Styles.customMetricColors;
const params = customParams(period.rangeName)
const prevMetricRef = useRef<any>();
const isTimeSeries = metric.metricType === 'timeseries';
const isTable = metric.metricType === 'table';
useEffect(() => {
// Check for title change
if (prevMetricRef.current && prevMetricRef.current.name !== metric.name) {
prevMetricRef.current = metric;
return
};
prevMetricRef.current = metric;
setLoading(true);
}, [metric])
const onDateChange = (changedDates) => {
setPeriod({ ...changedDates, rangeName: changedDates.rangeValue })
props.edit({ ...changedDates, rangeName: changedDates.rangeValue });
}
const chagneViewType = (e, { name, value }) => {
props.edit({ [ name ]: value });
}
return (
<div className="mb-10">
<div className="flex items-center">
<div className="mr-auto font-medium">Preview</div>
<div className="flex items-center">
{isTimeSeries && (
<>
<span className="color-gray-medium mr-4">Visualization</span>
<SegmentSelection
name="viewType"
className="my-3"
primary
icons={true}
onSelect={ chagneViewType }
value={{ value: metric.viewType }}
list={ [
{ value: 'lineChart', name: 'Chart', icon: 'graph-up-arrow' },
{ value: 'progress', name: 'Progress', icon: 'hash' },
]}
/>
</>
)}
{isTable && (
<>
<span className="mr-1 color-gray-medium">Visualization</span>
<SegmentSelection
name="viewType"
className="my-3"
primary={true}
icons={true}
onSelect={ chagneViewType }
value={{ value: metric.viewType }}
list={[
{ value: 'table', name: 'Table', icon: 'table' },
{ value: 'pieChart', name: 'Chart', icon: 'pie-chart-fill' },
]}
/>
</>
)}
<div className="mx-4" />
<span className="mr-1 color-gray-medium">Time Range</span>
<DateRange
rangeValue={metric.rangeName}
startDate={metric.startDate}
endDate={metric.endDate}
onDateChange={onDateChange}
customRangeRight
direction="left"
/>
</div>
</div>
<div className={stl.wrapper}>
<div className={stl.innerWapper}>
<Loader loading={ loading } size="small">
<NoContent
size="small"
show={ data.length === 0 }
>
<div className="p-4 font-medium">
{metric.name}
</div>
<div className="px-4 pb-4">
{ isTimeSeries && (
<>
{ metric.viewType === 'progress' && (
<CustomMetricPercentage
data={data[0]}
colors={colors}
params={params}
/>
)}
{ metric.viewType === 'lineChart' && (
<CustomMetriLineChart
data={data}
// seriesMap={seriesMap}
colors={colors}
params={params}
/>
)}
</>
)}
{ isTable && (
<>
{ metric.viewType === 'table' ? (
<CustomMetricTable metric={metric} data={data[0]} />
) : (
<CustomMetricPieChart
metric={metric}
data={data[0]}
colors={colors}
/>
)}
</>
)}
</div>
</NoContent>
</Loader>
</div>
</div>
</div>
);
}
export default connect(null, { remove, edit })(CustomMetricWidget);

View file

@ -1 +0,0 @@
export { default } from './CustomMetricWidgetPreview';

View file

@ -1,47 +0,0 @@
import React from 'react';
import { Dropdown } from 'semantic-ui-react';
import { IconButton } from 'UI';
const sessionSortOptions = {
// '': 'All',
'open': 'Open',
'closed': 'Closed',
};
const sortOptions = Object.entries(sessionSortOptions)
.map(([ value, text ]) => ({ value, text }));
const IssuesSortDropdown = ({ onChange, value }) => {
// sort = (e, { value }) => {
// const [ sort, order ] = value.split('-');
// const sign = order === 'desc' ? -1 : 1;
// this.props.applyFilter({ order, sort });
// this.props.sort(sort, sign)
// setTimeout(() => this.props.sort(sort, sign), 3000);
// }
return (
<Dropdown
name="issueType"
value={ value || sortOptions[ 0 ].value}
trigger={
<IconButton
// outline
label=""
icon="filter"
size="medium"
// shadow
className="outline-none"
/>
}
pointing="top right"
options={ sortOptions }
onChange={ onChange }
// defaultValue={ sortOptions[ 0 ].value }
icon={ null }
/>
);
}
export default IssuesSortDropdown;

View file

@ -1,66 +0,0 @@
import React from 'react';
import { connect } from 'react-redux';
import { getRE } from 'App/utils';
import { Input } from 'UI';
import IssueListItem from './IssueListItem';
import IssuesSortDropdown from './IssuesSortDropdown';
class SessionIssuesPanel extends React.Component {
state = { search: '', closed: false, issueType: 'open' }
write = ({ target: { value, name } }) => this.setState({ [ name ]: value });
writeOption = (e, { name, value }) => this.setState({ [ name ]: value });
render() {
const { issueTypeIcons, users, activeIssue, issues = [], onIssueClick = () => null } = this.props;
const { search, closed, issueType } = this.state;
let filteredIssues = issues.filter(({ closed, title }) => getRE(search, 'i').test(title))
if (!issueType !== '') {
filteredIssues = filteredIssues.filter(({ closed }) => closed === ( this.state.issueType === 'closed'))
}
// .filter(({ closed }) => closed == this.state.closed);
filteredIssues = filteredIssues.map(issue => {
issue.user = users.filter(user => user.id === issue.assignee).first();
return issue;
});
return (
<div>
<div className="p-3 bg-white flex items-center justify-between">
<Input
name="search"
className="flex-1 mr-4"
icon="search"
iconPosition="left"
placeholder="Search"
onChange={ this.write }
/>
<IssuesSortDropdown
onChange={ this.writeOption }
value={ issueType }
/>
</div>
<div>
{ filteredIssues.map(issue => (
<IssueListItem
key={ issue.key }
onClick={ () => onIssueClick(issue) }
issue={ issue }
icon={ issueTypeIcons[issue.issueType] }
user={ issue.user }
active={ activeIssue && activeIssue.id === issue.id }
/>
))
}
</div>
</div>
);
}
}
export default connect(state => ({
issues: state.getIn(['assignments', 'list']),
issueTypeIcons: state.getIn(['assignments', 'issueTypeIcons']),
users: state.getIn(['assignments', 'users']),
}))(SessionIssuesPanel);

View file

@ -5,7 +5,6 @@ import IssueHeader from './IssueHeader';
import IssueComment from './IssueComment';
import IssueCommentForm from './IssueCommentForm';
import IssueDetails from './IssueDetails';
import SessionIssuesPanel from './SessionIssuesPanel';
import IssueForm from './IssueForm';
import IssueListItem from './IssueListItem';
import IssueDescription from './IssueDescription';
@ -298,13 +297,4 @@ storiesOf('Issues', module)
<IssueForm issueTypes={ List(issueTypes) } />
</div>
))
.add('SessionIssuesPanel', () => (
<div className="bg-white">
<SessionIssuesPanel
issues={ issues }
onIssueClick={ onIssueClick }
issueTypeIcons={ issueTypeIcons }
/>
</div>
))

View file

@ -1,9 +0,0 @@
.searchInput {
padding: 10px 6px !important;
&:focus {
border-color: $teal !important;
}
}

View file

@ -1,10 +1,11 @@
import React from 'react'
import { Form, Input, Icon, Button, Link, Dropdown, CircularLoader } from 'UI'
import { Form, Input, Icon, Button, Link, CircularLoader } from 'UI'
import { login } from 'App/routes'
import ReCAPTCHA from 'react-google-recaptcha'
import stl from './signup.module.css'
import { signup } from 'Duck/user';
import { connect } from 'react-redux'
import Select from 'Shared/Select'
const LOGIN_ROUTE = login()
const recaptchaRef = React.createRef()
@ -48,7 +49,7 @@ export default class SignupForm extends React.Component {
}
write = ({ target: { value, name } }) => this.setState({ [ name ]: value })
writeOption = (e, { name, value }) => this.setState({ [ name ]: value });
writeOption = ({ name, value }) => this.setState({ [ name ]: value.value });
onSubmit = (e) => {
e.preventDefault();
@ -82,7 +83,7 @@ export default class SignupForm extends React.Component {
{ tenants.length > 0 && (
<Form.Field>
<label>Existing Accounts</label>
<Dropdown
<Select
className="w-full"
placeholder="Select account"
selection

View file

@ -1,223 +0,0 @@
import React from 'react';
import { Form, Button, IconButton, HelpText } from 'UI';
import FilterSeries from '../FilterSeries';
import { connect } from 'react-redux';
import { edit as editMetric, save, addSeries, removeSeries, remove } from 'Duck/customMetrics';
import CustomMetricWidgetPreview from 'App/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview';
import { confirm } from 'UI';
import { toast } from 'react-toastify';
import cn from 'classnames';
import DropdownPlain from '../../DropdownPlain';
import { metricTypes, metricOf, issueOptions } from 'App/constants/filterOptions';
import { FilterKey } from 'Types/filter/filterType';
interface Props {
metric: any;
editMetric: (metric, shouldFetch?) => void;
save: (metric) => Promise<void>;
loading: boolean;
addSeries: (series?) => void;
onClose: () => void;
remove: (id) => Promise<void>;
removeSeries: (seriesIndex) => void;
}
function CustomMetricForm(props: Props) {
const { metric, loading } = props;
// const metricOfOptions = metricOf.filter(i => i.key === metric.metricType);
const timeseriesOptions = metricOf.filter(i => i.type === 'timeseries');
const tableOptions = metricOf.filter(i => i.type === 'table');
const isTable = metric.metricType === 'table';
const isTimeSeries = metric.metricType === 'timeseries';
const _issueOptions = [{ text: 'All', value: 'all' }].concat(issueOptions);
const addSeries = () => {
props.addSeries();
}
const removeSeries = (index) => {
props.removeSeries(index);
}
const write = ({ target: { value, name } }) => props.editMetric({ [ name ]: value }, false);
const writeOption = (e, { value, name }) => {
props.editMetric({ [ name ]: value }, false);
if (name === 'metricValue') {
props.editMetric({ metricValue: [value] }, false);
}
if (name === 'metricOf') {
if (value === FilterKey.ISSUE) {
props.editMetric({ metricValue: ['all'] }, false);
}
}
if (name === 'metricType') {
if (value === 'timeseries') {
props.editMetric({ metricOf: timeseriesOptions[0].value, viewType: 'lineChart' }, false);
} else if (value === 'table') {
props.editMetric({ metricOf: tableOptions[0].value, viewType: 'table' }, false);
}
}
};
// const changeConditionTab = (e, { name, value }) => {
// props.editMetric({[ 'viewType' ]: value });
// };
const save = () => {
props.save(metric).then(() => {
toast.success(metric.exists() ? 'Updated succesfully.' : 'Created succesfully.');
props.onClose()
});
}
const deleteHandler = async () => {
if (await confirm({
header: 'Custom Metric',
confirmButton: 'Delete',
confirmation: `Are you sure you want to delete ${metric.name}`
})) {
props.remove(metric.metricId).then(() => {
toast.success('Deleted succesfully.');
props.onClose();
});
}
}
return (
<Form
className="relative"
onSubmit={save}
>
<div className="p-5 pb-20" style={{ height: 'calc(100vh - 60px)', overflowY: 'auto' }}>
<div className="form-group">
<label className="font-medium">Metric Title</label>
<input
autoFocus={ true }
className="text-lg"
name="name"
style={{ fontSize: '18px', padding: '10px', fontWeight: 600}}
value={ metric.name }
onChange={ write }
placeholder="Metric Title"
id="name-field"
/>
</div>
<div className="form-group">
<label className="font-medium">Metric Type</label>
<div className="flex items-center">
<DropdownPlain
name="metricType"
options={metricTypes}
value={ metric.metricType }
onChange={ writeOption }
/>
{metric.metricType === 'timeseries' && (
<>
<span className="mx-3">of</span>
<DropdownPlain
name="metricOf"
options={timeseriesOptions}
value={ metric.metricOf }
onChange={ writeOption }
/>
</>
)}
{metric.metricType === 'table' && (
<>
<span className="mx-3">of</span>
<DropdownPlain
name="metricOf"
options={tableOptions}
value={ metric.metricOf }
onChange={ writeOption }
/>
</>
)}
{metric.metricOf === FilterKey.ISSUE && (
<>
<span className="mx-3">issue type</span>
<DropdownPlain
name="metricValue"
options={_issueOptions}
value={ metric.metricValue[0] }
onChange={ writeOption }
/>
</>
)}
{metric.metricType === 'table' && (
<>
<span className="mx-3">showing</span>
<DropdownPlain
name="metricFormat"
options={[
{ value: 'sessionCount', text: 'Session Count' },
]}
value={ metric.metricFormat }
onChange={ writeOption }
/>
</>
)}
</div>
</div>
<div className="form-group">
<label className="font-medium flex items-center">
{`${isTable ? 'Filter by' : 'Chart Series'}`}
{!isTable && <HelpText position="top left" text="Defines a series of data for the line in chart." className="pl-3" />}
</label>
{metric.series && metric.series.size > 0 && metric.series.take(isTable ? 1 : metric.series.size).map((series: any, index: number) => (
<div className="mb-2">
<FilterSeries
hideHeader={ isTable }
seriesIndex={index}
series={series}
onRemoveSeries={() => removeSeries(index)}
canDelete={metric.series.size > 1}
emptyMessage={isTable ?
'Filter data using any event or attribute. Use Add Step button below to do so.' :
'Add user event or filter to define the series by clicking Add Step.'
}
/>
</div>
))}
</div>
{ isTimeSeries && (
<div className={cn("flex justify-end -my-4", {'disabled' : metric.series.size > 2})}>
<IconButton hover type="button" onClick={addSeries} primaryText label="SERIES" icon="plus" />
</div>
)}
<div className="my-8" />
<CustomMetricWidgetPreview metric={metric} />
</div>
<div className="flex items-center fixed border-t w-full bottom-0 px-5 py-2 bg-white">
<div className="mr-auto">
<Button loading={loading} variant="primary" className="float-left mr-2" disabled={!metric.validate()}>
{ `${metric.exists() ? 'Update' : 'Create'}` }
</Button>
<Button type="button" onClick={props.onClose}>Cancel</Button>
</div>
<div>
{ metric.exists() && <Button variant="text" type="button" className="ml-3" outline hover plain onClick={deleteHandler}>Delete</Button> }
</div>
</div>
</Form>
);
}
export default connect(state => ({
metric: state.getIn(['customMetrics', 'instance']),
loading: state.getIn(['customMetrics', 'saveRequest', 'loading']),
}), { editMetric, save, addSeries, remove, removeSeries })(CustomMetricForm);

View file

@ -1 +0,0 @@
export { default } from './CustomMetricForm';

View file

@ -1,38 +0,0 @@
import React from 'react'
import { IconButton, SlideModal } from 'UI';
import CustomMetricForm from '../CustomMetricForm';
import { connect } from 'react-redux'
import { init } from 'Duck/customMetrics';
interface Props {
metric: any;
init: (instance?, setDefault?) => void;
}
function CustomMetricsModal(props: Props) {
const { metric } = props;
return (
<>
<SlideModal
title={
<div className="flex items-center">
<span className="mr-3">{ metric && metric.exists() ? 'Update Custom Metric' : 'Create Custom Metric' }</span>
</div>
}
isDisplayed={ !!metric }
onClose={ () => props.init(null, true)}
content={ (!!metric) && (
<div style={{ backgroundColor: '#f6f6f6' }}>
<CustomMetricForm metric={metric} onClose={() => props.init(null, true)} />
</div>
)}
/>
</>
)
}
export default connect(state => ({
metric: state.getIn(['customMetrics', 'instance']),
alertInstance: state.getIn(['alerts', 'instance']),
showModal: state.getIn(['customMetrics', 'showModal']),
}), { init })(CustomMetricsModal);

View file

@ -1 +0,0 @@
export { default } from './CustomMetricsModal';

View file

@ -1,124 +0,0 @@
import React from 'react';
import { Dropdown } from 'semantic-ui-react';
import cn from 'classnames';
import {
getDateRangeFromValue,
getDateRangeLabel,
dateRangeValues,
getDateRangeFromTs,
CUSTOM_RANGE,
DATE_RANGE_VALUES,
} from 'App/dateRange';
import { Icon } from 'UI';
import DateRangePopup from './DateRangePopup';
import DateOptionLabel from './DateOptionLabel';
import styles from './dateRangeDropdown.module.css';
const getDateRangeOptions = (customRange = getDateRangeFromValue(CUSTOM_RANGE)) => dateRangeValues.map(value => ({
value,
text: <DateOptionLabel range={ value === CUSTOM_RANGE ? customRange : getDateRangeFromValue(value) } />,
content: getDateRangeLabel(value),
}));
export default class DateRangeDropdown extends React.PureComponent {
state = {
showDateRangePopup: false,
range: null,
value: DATE_RANGE_VALUES.TODAY,
};
static getDerivedStateFromProps(props) {
const { rangeValue, startDate, endDate } = props;
if (rangeValue) {
const range = rangeValue === CUSTOM_RANGE
? getDateRangeFromTs(startDate, endDate)
: getDateRangeFromValue(rangeValue);
return {
value: rangeValue,
range,
};
}
return null;
}
onCancelDateRange = () => this.setState({ showDateRangePopup: false });
onApplyDateRange = (range, value) => {
this.setState({
showDateRangePopup: false,
range,
value,
});
this.props.onChange({
startDate: range.start.unix() * 1000,
endDate: range.end.unix() * 1000,
rangeValue: value,
});
}
onItemClick = (event, { value }) => {
if (value !== CUSTOM_RANGE) {
const range = getDateRangeFromValue(value);
this.onApplyDateRange(range, value);
} else {
this.setState({ showDateRangePopup: true });
}
}
render() {
const { customRangeRight, button = false, className, direction = 'right', customHidden=false, show30Minutes=false } = this.props;
const { showDateRangePopup, value, range } = this.state;
let options = getDateRangeOptions(range);
if (customHidden) {
options.pop();
}
if (!show30Minutes) {
options.shift()
}
return (
<div className={ cn(styles.dateRangeOptions, className) }>
<Dropdown
trigger={ button ?
<div className={ cn(styles.dropdownTrigger, 'flex items-center')}>
<span>{ value === CUSTOM_RANGE ? range.start.format('MMM Do YY, hh:mm A') + ' - ' + range.end.format('MMM Do YY, hh:mm A') : getDateRangeLabel(value) }</span>
<Icon name="chevron-down" color="gray-dark" size="14" className={styles.dropdownIcon} />
</div> : null
}
// selection={!button}
name="sessionDateRange"
direction={ direction }
className={ button ? "" : "customDropdown" }
// pointing="top left"
placeholder="Select..."
icon={ null }
>
<Dropdown.Menu>
{ options.map((props, i) =>
<Dropdown.Item
key={i}
{...props}
onClick={this.onItemClick}
active={props.value === value }
/>
) }
</Dropdown.Menu>
</Dropdown>
{
showDateRangePopup &&
<div className={ cn(styles.dateRangePopup, { [styles.customRangeRight] : customRangeRight}) }>
<DateRangePopup
onApply={ this.onApplyDateRange }
onCancel={ this.onCancelDateRange }
selectedDateRange={ range }
/>
</div>
}
</div>
);
}
}

View file

@ -1,69 +0,0 @@
.button {
padding: 0 4px;
border-radius: 3px;
color: $teal;
cursor: pointer;
display: flex !important;
align-items: center !important;
& span {
white-space: nowrap;
margin-right: 5px;
}
}
.dropdownTrigger {
padding: 4px;
&:hover {
background-color: $gray-light;
}
}
.dateRangeOptions {
position: relative;
display: flex !important;
border-radius: 3px;
color: $gray-darkest;
font-weight: 500;
& .dateRangePopup {
top: 38px;
bottom: 0;
z-index: 999;
position: absolute;
background-color: white;
border: solid thin $gray-light;
border-radius: 3px;
min-height: fit-content;
min-width: 773px;
box-shadow: 0px 2px 10px 0 $gray-light;
}
}
.dropdown {
display: flex !important;
padding: 4px 4px;
border-radius: 3px;
color: $gray-darkest;
font-weight: 500;
&:hover {
background-color: $gray-light;
}
}
.dropdownTrigger {
padding: 4px 4px;
border-radius: 3px;
&:hover {
background-color: $gray-light;
}
}
.dropdownIcon {
margin-top: 1px;
margin-left: 3px;
}
.customRangeRight {
right: 0 !important;
}

View file

@ -1,5 +1,4 @@
import React from 'react';
// import { Input, Label } from 'semantic-ui-react';
import styles from './FilterDuration.module.css';
import { Input } from 'UI'

View file

@ -1,8 +0,0 @@
import React from 'react';
import { Dropdown } from 'semantic-ui-react';
export default props => (
<Dropdown
{ ...props }
/>
);

View file

@ -1,8 +0,0 @@
import { storiesOf } from '@storybook/react';
import Dropdown from '.';
storiesOf('Dropdown', module)
.add('Pure', () => (
<Dropdown />
))

View file

@ -1 +0,0 @@
export { default } from './Dropdown';

View file

@ -1,31 +0,0 @@
import React from 'react'
import { Dropdown } from 'semantic-ui-react'
import { Icon } from 'UI';
import stl from './dropdownPlain.module.css'
const sessionSortOptions = {
'latest': 'Newest',
'editedAt': 'Last Modified'
};
const sortOptions = Object.entries(sessionSortOptions)
.map(([ value, text ]) => ({ value, text }));
function DropdownPlain({ name, label, options, onChange, defaultValue, wrapperStyle = {}, disabled = false }) {
return (
<div className="flex items-center" style={wrapperStyle}>
{ label && <span className="mr-2 color-gray-medium">{label}</span> }
<Dropdown
name={name}
className={ stl.dropdown }
// pointing="top right"
options={ options }
onChange={ onChange }
defaultValue={ defaultValue || options[ 0 ].value }
disabled={disabled}
icon={ <Icon name="chevron-down" color="gray-dark" size="14" className={stl.dropdownIcon} /> }
/>
</div>
)
}
export default DropdownPlain

View file

@ -1,23 +0,0 @@
.dropdown {
display: flex !important;
padding: 4px 6px;
border-radius: 3px;
color: $gray-darkest;
font-weight: 500;
&:hover {
background-color: $gray-light;
}
}
.dropdownTrigger {
padding: 4px 8px;
border-radius: 3px;
&:hover {
background-color: $gray-light;
}
}
.dropdownIcon {
margin-top: 2px;
margin-left: 3px;
}

View file

@ -1 +0,0 @@
export { default } from './DropdownPlain';

View file

@ -1,7 +1,6 @@
import React from 'react';
import { Popup } from 'semantic-ui-react';
import cn from 'classnames';
import { Icon } from 'UI';
import { Icon, Popup } from 'UI';
import styles from './textLabel.module.css';
export default function TextLabel({

View file

@ -1,6 +1,6 @@
export { default as Loader } from './Loader';
export { default as Link } from './Link';
export { default as Dropdown } from './Dropdown';
// export { default as Dropdown } from './Dropdown';
export { default as Button } from './Button';
export { default as Label } from './Label';
export { default as Popup } from './Popup';
@ -40,7 +40,6 @@ export { default as ErrorFrame } from './ErrorFrame';
export { default as ErrorDetails } from './ErrorDetails';
export { default as LoadMoreButton } from './LoadMoreButton';
export { default as EscapeButton } from './EscapeButton';
export { default as DropdownPlain } from './DropdownPlain';
export { default as TextLink } from './TextLink';
export { default as Information } from './Information';
export { default as QuestionMarkHint } from './QuestionMarkHint';

View file

@ -5,7 +5,7 @@ import { Configuration as WebpackDevServerConfiguration } from 'webpack-dev-serv
import CopyWebpackPlugin from 'copy-webpack-plugin';
import HtmlWebpackPlugin from "html-webpack-plugin";
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
// import CompressionPlugin from "compression-webpack-plugin";
import CompressionPlugin from "compression-webpack-plugin";
const dotenv = require('dotenv').config({ path: __dirname + '/.env' })
const isDevelopment = process.env.NODE_ENV !== 'production'
const stylesHandler = MiniCssExtractPlugin.loader;
@ -61,19 +61,19 @@ const config: Configuration = {
mode: "local",
auto: true,
localIdentName: "[name]__[local]--[hash:base64:5]",
},
url: {
filter: (url: string) => {
// Semantic-UI-CSS has an extra semi colon in one of the URL due to which CSS loader along
// with webpack 5 fails to generate a build.
// Below if condition is a hack. After Semantic-UI-CSS fixes this, one can replace use clause with just
// use: ['style-loader', 'css-loader']
if (url.includes('charset=utf-8;;')) {
return false;
}
return true;
},
}
}
// url: {
// filter: (url: string) => {
// // Semantic-UI-CSS has an extra semi colon in one of the URL due to which CSS loader along
// // with webpack 5 fails to generate a build.
// // Below if condition is a hack. After Semantic-UI-CSS fixes this, one can replace use clause with just
// // use: ['style-loader', 'css-loader']
// if (url.includes('charset=utf-8;;')) {
// return false;
// }
// return true;
// },
// }
},
},
'postcss-loader'
@ -106,6 +106,7 @@ const config: Configuration = {
},
},
plugins: [
new CompressionPlugin(),
new webpack.DefinePlugin({
// 'process.env': ENV_VARIABLES,
'window.env': ENV_VARIABLES,