Skip to content

Commit

Permalink
feat: completed unit of time in filter (#1304)
Browse files Browse the repository at this point in the history
* feat: completed unit of time in filter

* chore: replace label and set default value
  • Loading branch information
ZeRego committed Feb 9, 2022
1 parent 411fa0d commit 0480459
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 14 deletions.
16 changes: 14 additions & 2 deletions packages/backend/src/queryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,26 @@ const renderDateFilterSql = (
filter.values?.[0],
)}')`;
case FilterOperator.IN_THE_PAST:
const unitOfTime = filter.settings?.unitOfTime || UnitOfTime.days;
return `(${dimensionSql}) >= ('${dateFormatter(
const unitOfTime: UnitOfTime =
filter.settings?.unitOfTime || UnitOfTime.days;
const completed: boolean = !!filter.settings?.completed;
const sinceDateSql = `(${dimensionSql}) >= ('${dateFormatter(
moment(
moment(new Date())
.subtract(filter.values?.[0], unitOfTime)
.format(unitOfTimeFormat[unitOfTime]),
).toDate(),
)}')`;
const untilDateSql = `(${dimensionSql}) < ('${dateFormatter(
moment(
moment()
.startOf(unitOfTime)
.format(unitOfTimeFormat[unitOfTime]),
).toDate(),
)}')`;
return completed
? `(${sinceDateSql} AND ${untilDateSql})`
: sinceDateSql;
default:
throw Error(
`No function implemented to render sql for filter type ${filterType} on dimension of date type`,
Expand Down
3 changes: 2 additions & 1 deletion packages/common/src/types/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export type DateFilterRule = FilterRule<
FilterOperator,
any,
{
unitOfTime: UnitOfTime;
unitOfTime?: UnitOfTime;
completed?: boolean;
}
>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HTMLSelect, NumericInput } from '@blueprintjs/core';
import { NumericInput } from '@blueprintjs/core';
import { DateInput, TimePrecision } from '@blueprintjs/datetime';
import {
DateFilterRule,
Expand All @@ -12,6 +12,7 @@ import {
} from 'common';
import React, { FC } from 'react';
import DefaultFilterInputs, { FilterInputsProps } from './DefaultFilterInputs';
import UnitOfTimeAutoComplete from './UnitOfTimeAutoComplete';

const DateFilterInputs: FC<FilterInputsProps<DateFilterRule>> = (props) => {
const { field, filterRule, onChange } = props;
Expand Down Expand Up @@ -52,28 +53,28 @@ const DateFilterInputs: FC<FilterInputsProps<DateFilterRule>> = (props) => {
<>
<NumericInput
fill
value={filterRule.values?.[0]}
value={filterRule.values?.[0] || 1}
onValueChange={(value) =>
onChange({
...filterRule,
values: [value],
})
}
/>
<HTMLSelect
fill
onChange={(e) =>
<UnitOfTimeAutoComplete
unitOfTime={
filterRule.settings?.unitOfTime || UnitOfTime.days
}
completed={filterRule.settings?.completed || false}
onChange={(value) =>
onChange({
...filterRule,
settings: {
unitOfTime: e.currentTarget.value,
unitOfTime: value.unitOfTime,
completed: value.completed,
},
})
}
options={Object.values(UnitOfTime)}
value={
filterRule.settings?.unitOfTime || UnitOfTime.days
}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { Button, MenuItem } from '@blueprintjs/core';
import { ItemRenderer, Select } from '@blueprintjs/select';
import { UnitOfTime } from 'common';
import React, { FC } from 'react';
import { createGlobalStyle } from 'styled-components';

type UnitOfTimeOption = {
label: string;
unitOfTime: UnitOfTime;
completed: boolean;
};

const UnitOfTimeOptions = Object.values(UnitOfTime)
.reverse()
.reduce<UnitOfTimeOption[]>(
(sum, unitOfTime) => [
...sum,
{
label: unitOfTime,
unitOfTime,
completed: false,
},
{
label: `completed ${unitOfTime}`,
unitOfTime,
completed: true,
},
],
[],
);

const FieldSuggest = Select.ofType<UnitOfTimeOption>();

const AutocompleteMaxHeight = createGlobalStyle`
.autocomplete-max-height {
max-height: 400px;
overflow-y: auto;
}
`;

const renderItem: ItemRenderer<UnitOfTimeOption> = (
field,
{ modifiers, handleClick },
) => {
if (!modifiers.matchesPredicate) {
return null;
}
return (
<MenuItem
active={modifiers.active}
key={`${field.completed}_${field.unitOfTime}`}
text={field.label}
onClick={handleClick}
shouldDismissPopover={false}
/>
);
};

type Props = {
unitOfTime: UnitOfTime;
completed: boolean;
onChange: (value: UnitOfTimeOption) => void;
onClosed?: () => void;
};

const UnitOfTimeAutoComplete: FC<Props> = ({
unitOfTime,
completed,
onChange,
onClosed,
}) => (
<>
<AutocompleteMaxHeight />
<FieldSuggest
items={UnitOfTimeOptions}
itemsEqual={(value, other) =>
value.unitOfTime === other.unitOfTime &&
value.completed === other.completed
}
popoverProps={{
fill: true,
minimal: true,
onClosed,
popoverClassName: 'autocomplete-max-height',
}}
itemRenderer={renderItem}
activeItem={{
label: completed ? `completed ${unitOfTime}` : unitOfTime,
unitOfTime,
completed,
}}
noResults={<MenuItem disabled text="No results." />}
onItemSelect={onChange}
itemPredicate={(
query: string,
field: UnitOfTimeOption,
index?: undefined | number,
exactMatch?: undefined | false | true,
) => {
if (exactMatch) {
return query.toLowerCase() === field.label.toLowerCase();
}
return field.label.toLowerCase().includes(query.toLowerCase());
}}
>
<Button
rightIcon="caret-down"
text={completed ? `completed ${unitOfTime}` : unitOfTime}
fill
style={{
display: 'inline-flex',
justifyContent: 'space-between',
whiteSpace: 'nowrap',
}}
/>
</FieldSuggest>
</>
);

export default UnitOfTimeAutoComplete;
2 changes: 1 addition & 1 deletion packages/frontend/src/components/common/Filters/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const filterOperatorLabel: Record<FilterOperator, string> = {
[FilterOperator.LESS_THAN_OR_EQUAL]: 'is less than or equal',
[FilterOperator.GREATER_THAN]: 'is greater than',
[FilterOperator.GREATER_THAN_OR_EQUAL]: 'is greater than or equal',
[FilterOperator.IN_THE_PAST]: 'is in the past',
[FilterOperator.IN_THE_PAST]: 'in the last',
};

const getFilterOptions = <T extends FilterOperator>(
Expand Down

0 comments on commit 0480459

Please sign in to comment.