Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[materialite] A more filters to the repliear app [2/n] #161

Open
wants to merge 3 commits into
base: mlaw/materialite-1-base
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix status filter selection to behave more like linear when in specif…
…ic views (backlog, active)
  • Loading branch information
tantaman committed Dec 19, 2023
commit af3256f5fc392ab1add1e3e8364d336e8716ce35
23 changes: 16 additions & 7 deletions client/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
getStatusFilter,
getViewFilter,
getViewStatuses,
hasNonViewFilters as doesHaveNonViewFilters,
} from './filters';

type AppProps = {
Expand Down Expand Up @@ -95,6 +96,7 @@ const App = ({rep, undoManager}: AppProps) => {
const [createdFilter] = useCreatedFilterState();
const [creatorFilter] = useCreatorFilterState();
const [modifiedFilter] = useModifiedFilterState();
const [hasNonViewFilters, setHasNonViewFilters] = useState(false);

const issueOrder = getIssueOrder(view, orderBy);

Expand All @@ -104,14 +106,21 @@ const App = ({rep, undoManager}: AppProps) => {

const viewStatuses = getViewStatuses(view);
const statuses = getStatuses(statusFilter);
const statusFilterFn = getStatusFilter(viewStatuses, statuses);
const filterFns = [
getStatusFilter(viewStatuses, statuses),
statusFilterFn,
getPriorityFilter(getPriorities(priorityFilter)),
getCreatorFilter(getCreators(creatorFilter)),
getCreatedFilter(createdFilter),
getModifiedFilter(modifiedFilter),
];

const hasNonViewFilters = !!(
doesHaveNonViewFilters(viewStatuses, statuses) ||
filterFns.filter(f => f !== null && f !== statusFilterFn).length > 0
);
setHasNonViewFilters(hasNonViewFilters);

let {stream} = source;
for (const filter of filterFns) {
if (filter !== null) {
Expand All @@ -125,11 +134,11 @@ const App = ({rep, undoManager}: AppProps) => {
}, [
view,
issueOrder,
priorityFilter,
statusFilter,
createdFilter,
creatorFilter,
modifiedFilter,
priorityFilter?.join(),
statusFilter?.join(),
createdFilter?.join(),
creatorFilter?.join(),
modifiedFilter?.join(),
]);

const [, viewIssueCount] = useQuery(() => {
Expand Down Expand Up @@ -279,7 +288,7 @@ const App = ({rep, undoManager}: AppProps) => {
viewIssueCount={viewIssueCount || 0}
filteredIssues={filterdIssues}
rep={rep}
hasNonViewFilters={false}
hasNonViewFilters={hasNonViewFilters}
onCloseMenu={handleCloseMenu}
onToggleMenu={handleToggleMenu}
onUpdateIssues={handleUpdateIssues}
Expand Down
18 changes: 12 additions & 6 deletions client/src/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function hasNonViewFilters(
statuses: Set<Status>,
) {
for (const s of statuses) {
if (!viewStatuses.has(s)) {
if (viewStatuses.has(s)) {
return true;
}
}
Expand Down Expand Up @@ -50,11 +50,11 @@ export function getStatusFilter(
viewStatuses: Set<Status>,
statuses: Set<Status>,
): null | ((issue: Issue) => boolean) {
const allStatuses = new Set<Status>([...viewStatuses, ...statuses]);
if (allStatuses.size === 0) {
const filterStatuses = statuses.size === 0 ? viewStatuses : statuses;
if (filterStatuses.size === 0) {
return null;
}
return issue => allStatuses.has(issue.status);
return issue => filterStatuses.has(issue.status);
}

export function getCreatorFilter(
Expand All @@ -75,13 +75,19 @@ export function getViewFilter(

export function getModifiedFilter(
args: DateQueryArg[] | null,
): (issue: Issue) => boolean {
): ((issue: Issue) => boolean) | null {
if (args === null) {
return null;
}
return createTimeFilter('modified', args);
}

export function getCreatedFilter(
args: DateQueryArg[] | null,
): (issue: Issue) => boolean {
): null | ((issue: Issue) => boolean) {
if (args === null) {
return null;
}
return createTimeFilter('created', args);
}

Expand Down
25 changes: 22 additions & 3 deletions client/src/layout/left-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ import IssueModal from '../issue/issue-modal';
import ReactLogo from '../assets/images/logo.svg?react';
import AboutModal from '../about-modal';
import {noop} from 'lodash';
import {useIssueDetailState, useViewState} from '../hooks/query-state-hooks';
import {
useIssueDetailState,
useStatusFilterState,
useViewState,
} from '../hooks/query-state-hooks';
import useQueryState, {identityProcessor} from '../hooks/useQueryState';
import {Description, Issue} from 'shared';
import {getViewStatuses} from '../filters';

interface Props {
// Show menu (for small screen only)
Expand All @@ -32,6 +37,7 @@ const LeftMenu = ({menuVisible, onCloseMenu = noop, onCreateIssue}: Props) => {
const ref = useRef<HTMLDivElement>() as RefObject<HTMLDivElement>;
const [issueModalVisible, setIssueModalVisible] = useState(false);
const [aboutModalVisible, setAboutModalVisible] = useState(true);
const [statusFilter, setStatusFilter] = useStatusFilterState();

const classes = classnames(
'absolute lg:static inset-0 lg:relative lg:translate-x-0 flex flex-col flex-shrink-0 w-56 font-sans text-sm border-r lg:shadow-none justify-items-start bg-gray border-gray-850 text-white bg-opacity-1',
Expand All @@ -49,6 +55,11 @@ const LeftMenu = ({menuVisible, onCloseMenu = noop, onCreateIssue}: Props) => {
}
});

function pruneStatuses(view: string) {
const viewStatuses = getViewStatuses(view);
return statusFilter?.filter(s => viewStatuses.has(s)) ?? null;
}

return (
<>
<div className={classes} ref={ref}>
Expand Down Expand Up @@ -108,7 +119,11 @@ const LeftMenu = ({menuVisible, onCloseMenu = noop, onCreateIssue}: Props) => {
<div
className="flex items-center pl-9 rounded cursor-pointer group h-8 hover:bg-gray-900"
onMouseDown={async () => {
await Promise.all([setView('active'), setIss(null)]);
await Promise.all([
setView('active'),
setStatusFilter(pruneStatuses('active')),
setIss(null),
]);
onCloseMenu && onCloseMenu();
}}
>
Expand All @@ -118,7 +133,11 @@ const LeftMenu = ({menuVisible, onCloseMenu = noop, onCreateIssue}: Props) => {
<div
className="flex items-center pl-9 rounded cursor-pointer group h-8 hover:bg-gray-900"
onMouseDown={async () => {
await Promise.all([setView('backlog'), setIss(null)]);
await Promise.all([
setView('backlog'),
setStatusFilter(pruneStatuses('backlog')),
setIss(null),
]);
onCloseMenu && onCloseMenu();
}}
>
Expand Down
45 changes: 26 additions & 19 deletions client/src/widgets/filter-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import {Filter} from '../issue/issue';
import {useClickOutside} from '../hooks/useClickOutside';
import SignalStrongIcon from '../assets/icons/signal-strong.svg?react';
import TodoIcon from '../assets/icons/circle.svg?react';
import UserIcon from '../assets/icons/avatar.svg?react';
import DateIcon from '../assets/icons/due-date.svg?react';
import {statusOpts} from './priority-menu';
import {statuses} from './status-menu';
import {Priority, Status} from 'shared';
import UserIcon from './assets/icons/avatar.svg';
import DateIcon from './assets/icons/due-date.svg';
import useId from '@mui/utils/useId';
import {useViewState} from '../hooks/query-state-hooks';
import {getViewStatuses} from '../filters';

type DateCallback = (date: Date) => void;
interface Props {
Expand All @@ -35,6 +37,7 @@ const FilterMenu = ({
const [popperRef, setPopperRef] = useState<HTMLDivElement | null>(null);
const [filter, setFilter] = useState<Filter | null>(null);
const [filterDropDownVisible, setFilterDropDownVisible] = useState(false);
const [view] = useViewState();

const {styles, attributes, update} = usePopper(filterRef, popperRef, {
placement: 'bottom-start',
Expand Down Expand Up @@ -83,23 +86,27 @@ const FilterMenu = ({
);
});

case Filter.STATUS:
return statuses.map(([Icon, status, label], idx) => {
return (
<div
key={idx}
className="flex items-center h-8 px-3 text-gray focus:outline-none hover:text-gray-800 hover:bg-gray-300"
onMouseDown={() => {
onSelectStatus(status as Status);
setFilter(null);
setFilterDropDownVisible(false);
}}
>
<Icon className="mr-4" />
{label}
</div>
);
});
case Filter.STATUS: {
const viewStatuses = getViewStatuses(view);
return statuses
.filter(s => viewStatuses.size === 0 || viewStatuses.has(s[1]))
.map(([Icon, status, label], idx) => {
return (
<div
key={idx}
className="flex items-center h-8 px-3 text-gray focus:outline-none hover:text-gray-800 hover:bg-gray-300"
onMouseDown={() => {
onSelectStatus(status as Status);
setFilter(null);
setFilterDropDownVisible(false);
}}
>
<Icon className="mr-4" />
{label}
</div>
);
});
}
case Filter.CREATOR:
return [
<CreatorInput
Expand Down