Skip to content

Commit

Permalink
feat: add the ability to filter tasks by marker or priority level.
Browse files Browse the repository at this point in the history
  • Loading branch information
ahonn committed Feb 26, 2023
1 parent eb8c41b commit 412415f
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 32 deletions.
6 changes: 5 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import 'mousetrap-global-bind';
import getNextNDaysTaskQuery from './querys/next-n-days';
import { fixPreferredDateFormat } from './utils';
import './style.css';
import { markerFilterState, priorityFilterState } from './state/filter';

dayjs.extend(advancedFormat);

Expand Down Expand Up @@ -50,6 +51,8 @@ function App(props: IAppProps) {
const themeStyle = useRecoilValue(themeStyleState);
const themeMode = useRecoilValue(themeModeState);
const settings = useRecoilValue(settingsState);
const marker = useRecoilValue(markerFilterState);
const priority = useRecoilValue(priorityFilterState);

const refreshAll = useRecoilCallback(
({ snapshot, refresh }) =>
Expand Down Expand Up @@ -124,7 +127,8 @@ function App(props: IAppProps) {
const { whereToPlaceNewTask } = settings;
const date = dayjs().format(fixPreferredDateFormat(preferredDateFormat!));
await api.createNewTask(date, content, {
preferredTodo,
marker: marker.value || preferredTodo,
priority: priority.value,
whereToPlaceNewTask,
});
refreshAll();
Expand Down
16 changes: 9 additions & 7 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export const MARKER_GROUPS: Record<string, TaskMarker[]> = {
};

export interface ITaskOptions {
preferredTodo: string;
marker: string;
priority: string;
whereToPlaceNewTask?: string;
}

Expand All @@ -23,7 +24,8 @@ export async function createNewTask(
content: string,
opts: ITaskOptions,
) {
const { preferredTodo, whereToPlaceNewTask } = opts;
const { marker, priority, whereToPlaceNewTask } = opts;
const rawContent = `${marker} ${priority ? `[#${priority}]` : ''} ${content}`;
let page = await window.logseq.Editor.getPage(date);
if (page === null) {
page = await window.logseq.Editor.createPage(date, {
Expand All @@ -43,12 +45,12 @@ export async function createNewTask(
}
await window.logseq.Editor.insertBlock(
parentBlock!.uuid,
`${preferredTodo} ${content}`,
rawContent,
);
} else {
await window.logseq.Editor.appendBlockInPage(
page!.name,
`${preferredTodo} ${content}`,
rawContent,
);
}

Expand All @@ -64,7 +66,7 @@ export async function toggleTaskStatus(
options: ITaskOptions,
) {
const { uuid, completed, marker } = task;
const nextMarker = completed ? options.preferredTodo : TaskMarker.DONE;
const nextMarker = completed ? options.marker : TaskMarker.DONE;
await window.logseq.Editor.updateBlock(
uuid,
task.rawContent.replace(marker, nextMarker),
Expand Down Expand Up @@ -102,11 +104,11 @@ export async function toggleTaskMarker(
let newMarker = marker;
if (marker === TaskMarker.WAITING) {
newMarker =
options.preferredTodo === TaskMarker.LATER
options.marker === TaskMarker.LATER
? TaskMarker.LATER
: TaskMarker.TODO;
} else {
const markerGroup = MARKER_GROUPS[options.preferredTodo];
const markerGroup = MARKER_GROUPS[options.marker];
const currentMarkIndex = markerGroup.findIndex((m) => m === marker);
newMarker = markerGroup[(currentMarkIndex + 1) % markerGroup.length];
}
Expand Down
95 changes: 80 additions & 15 deletions src/components/TaskFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import React from 'react';
import Select from 'react-select';
import Select, { Theme } from 'react-select';
import { useRecoilState, useRecoilValue } from 'recoil';
import { CircleOff } from 'tabler-icons-react';
import { userConfigsState } from '../state/user-configs';
import { TaskMarker, TaskPriority } from '../models/TaskEntity';
import { markerFilterState, priorityFilterState } from '../state/filter';
import {
DEFAULT_OPTION,
markerFilterState,
priorityFilterState,
} from '../state/filter';
import { themeStyleState } from '../state/theme';

const PRIORITY_OPTIONS = [
TaskPriority.HIGH,
Expand All @@ -16,6 +22,7 @@ const TaskFilter: React.FC = () => {
const { preferredWorkflow } = useRecoilValue(userConfigsState);
const [marker, setMarker] = useRecoilState(markerFilterState);
const [priority, setPriority] = useRecoilState(priorityFilterState);
const themeStyle = useRecoilValue(themeStyleState);

const workflow = React.useMemo(() => {
return preferredWorkflow === 'now'
Expand All @@ -28,24 +35,82 @@ const TaskFilter: React.FC = () => {
(options, marker) => {
return [...options, { label: marker, value: marker }];
},
[{ label: 'ALL', value: '' }],
[DEFAULT_OPTION],
);
}, [workflow]);

const priorityOptions = React.useMemo(() => {
return PRIORITY_OPTIONS.reduce(
(options, marker) => {
return [...options, { label: marker, value: marker }];
},
[DEFAULT_OPTION],
);
}, []);

const selectClassNames = React.useMemo(
() => ({
container: () => 'text-xs',
control: () =>
'!h-6 !min-h-6 w-14 !border-none !shadow-none !bg-transparent ',
valueContainer: () => '!py-0 !px-1 cursor-pointer bg-transparent',
singleValue: () => `!text-gray-600 !dark:text-gray-300`,
indicatorsContainer: () => '!hidden',
menu: () => `!-mt-0.5`,
option: () => `!py-1 !px-2`,
}),
[],
);

const selectTheme = React.useCallback((theme: Theme) => ({
...theme,
colors: {
...theme.colors,
primary: themeStyle.sectionTitleColor,
primary25: themeStyle.secondaryBackgroundColor,
neutral0: themeStyle.primaryBackgroundColor,
}
}), [themeStyle]);

const handleReset = () => {
setMarker(DEFAULT_OPTION);
setPriority(DEFAULT_OPTION);
};

return (
<div className="flex flex-row">
<div className="flex flex-row mr-2 items-center">
<span className="text-xs">Marker:</span>
<Select
classNames={{
container: () => 'text-xs',
control: () => '!h-6 !min-h-6 w-16 !border-none !shadow-none',
valueContainer: () => '!py-0 !px-2',
indicatorsContainer: () => '!hidden',
}}
options={markerOptions}
/>
<div
className="flex flex-row text-gray-600 dark:text-gray-300 px-2 rounded-b-md items-center justify-between"
style={{
backgroundColor: themeStyle.secondaryBackgroundColor,
}}
>
<div className="flex flex-row">
<div className="flex flex-row items-center">
<span className="text-xs">Marker:</span>
<Select
classNames={selectClassNames}
theme={selectTheme}
isSearchable={false}
options={markerOptions}
value={marker}
onChange={(option) => setMarker(option!)}
/>
</div>
<div className="flex flex-row items-center">
<span className="text-xs">Priority:</span>
<Select
classNames={selectClassNames}
theme={selectTheme}
isSearchable={false}
options={priorityOptions}
value={priority}
onChange={(option) => setPriority(option!)}
/>
</div>
</div>
{(marker.value || priority.value) && (
<CircleOff size={14} className="stroke-gray-600 dark:stroke-gray-200" onClick={handleReset} />
)}
</div>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/components/TaskInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ const TaskInput: React.ForwardRefRenderFunction<
}));

return (
<div className="flex mb-2">
<div className="flex border-b-1 border-dashed dark:border-gray-400 border-gray-300">
<div
className="px-2 h-9 flex items-center flex-1 inline rounded-lg"
className="px-2 h-9 flex items-center flex-1 inline rounded-t-md"
style={{
backgroundColor: themeStyle.secondaryBackgroundColor,
}}
Expand Down
4 changes: 2 additions & 2 deletions src/components/TaskItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ const TaskItem: React.FC<ITaskItemProps> = (props) => {
};

const toggleStatus = async () => {
await toggleTaskStatus(task, { preferredTodo });
await toggleTaskStatus(task, { marker: preferredTodo });
setChecked(!checked);
};

const toggleMarker = () => {
toggleTaskMarker(task, { preferredTodo });
toggleTaskMarker(task, { marker: preferredTodo });
onChange();
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/TaskSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from 'recoil';
import { groupBy } from 'lodash-es';
import { TaskEntityObject } from '../models/TaskEntity';
import { tasksState } from '../state/tasks';
import { filterdTasksState, tasksState } from '../state/tasks';
import { themeStyleState } from '../state/theme';
import { visibleState } from '../state/visible';
import TaskItem from './TaskItem';
Expand All @@ -30,7 +30,7 @@ const TaskSection: React.FC<ITaskSectionProps> = (props) => {
const { title, query } = props;
const [tasks, setTasks] = useState<TaskEntityObject[]>([]);
const visible = useRecoilValue(visibleState);
const tasksLoadable = useRecoilValueLoadable(tasksState(query));
const tasksLoadable = useRecoilValueLoadable(filterdTasksState(query));
const themeStyle = useRecoilValue(themeStyleState);
const { openInRightSidebar } = useRecoilValue(settingsState);
const input = useRecoilValue(inputState);
Expand Down
9 changes: 7 additions & 2 deletions src/state/filter.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { atom } from "recoil";

export const DEFAULT_OPTION = {
label: 'ALL',
value: '',
}

export const markerFilterState = atom({
key: 'filter/marker',
default: "",
default: DEFAULT_OPTION,
});

export const priorityFilterState = atom({
key: 'filter/priority',
default: "",
default: DEFAULT_OPTION,
});
24 changes: 23 additions & 1 deletion src/state/tasks.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { BlockEntity, PageEntity } from '@logseq/libs/dist/LSPlugin';
import { selectorFamily } from 'recoil';
import TaskEntity, { TASK_PRIORITY_WEIGHT } from '../models/TaskEntity';
import TaskEntity, { TaskEntityObject, TASK_PRIORITY_WEIGHT } from '../models/TaskEntity';
import { getBlockUUID } from '../utils';
import { markerFilterState, priorityFilterState } from './filter';

async function getTaskEntitiesByQuery(query: string) {
const collections = await window.logseq.DB.datascriptQuery<BlockEntity[][]>(
Expand Down Expand Up @@ -62,3 +63,24 @@ export const tasksState = selectorFamily({
eviction: 'most-recent',
},
});

export const filterdTasksState = selectorFamily({
key: 'filterd-tasks',
get: (query: string) => ({ get }) => {
const tasks = get(tasksState(query));
const marker = get(markerFilterState);
const priority = get(priorityFilterState);

return tasks.filter((task: TaskEntityObject) => {
if (marker.value && task.marker !== marker.value) {
return false;
}

if (priority.value && task.priority !== priority.value) {
return false;
}

return true;
});
},
})

0 comments on commit 412415f

Please sign in to comment.