Skip to content

Commit

Permalink
feat(filter): ✨ supports set color
Browse files Browse the repository at this point in the history
  • Loading branch information
haydenull committed Nov 25, 2023
1 parent de92e38 commit d8322d9
Show file tree
Hide file tree
Showing 16 changed files with 186 additions and 57 deletions.
10 changes: 6 additions & 4 deletions src/newHelper/fullCalendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import { padZero } from '@/util/util'
*/
export const transformAgendaTaskToCalendarEvent = (
task: AgendaTaskWithStart,
options: { showFirstEventInCycleOnly?: boolean; showTimeLog?: boolean } = {},
options: { showFirstEventInCycleOnly?: boolean; showTimeLog?: boolean; groupType: 'filter' | 'page' } = {
groupType: 'page',
},
): CalendarEvent[] => {
const { showFirstEventInCycleOnly = false, showTimeLog = false } = options
const { showFirstEventInCycleOnly = false, showTimeLog = false, groupType } = options
const { estimatedTime = DEFAULT_ESTIMATED_TIME, timeLogs = [], status, actualTime } = task
const spanTime = status === 'done' && actualTime && showTimeLog ? actualTime : estimatedTime
const rrule: CalendarEvent['rrule'] =
Expand All @@ -29,7 +31,7 @@ export const transformAgendaTaskToCalendarEvent = (
end: log.end.toDate(),
extendedProps: task,
editable: false,
color: task.project.bgColor,
color: groupType === 'page' ? task.project.bgColor : task.filters?.[0]?.color,
}))
}
return [
Expand All @@ -47,7 +49,7 @@ export const transformAgendaTaskToCalendarEvent = (
// 只有时间点事件才能传 duration
duration: task.allDay ? undefined : { minute: spanTime },
editable: !(task.recurringPast || task.rrule),
color: task.project.bgColor,
color: groupType === 'page' ? task.project.bgColor : task.filters?.[0]?.color,
},
]
}
Expand Down
45 changes: 37 additions & 8 deletions src/newHelper/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export type BlockFromQuery = BlockEntity & {
page: AgendaTaskPage
repeated?: boolean
}
export type BlockFromQueryWithFilters = BlockFromQuery & {
filters?: Filter[]
}
export const getAgendaTasks = async (settings: Settings) => {
const favoritePages = (await logseq.App.getCurrentGraphFavorites()) || []
let blocks = (await logseq.DB.datascriptQuery(`
Expand Down Expand Up @@ -70,16 +73,25 @@ export const getAgendaTasks = async (settings: Settings) => {
:where
[?block :block/marker ?marker]
[(contains? #{"TODO" "DOING" "NOW" "LATER" "WAITING" "DONE"} ?marker)]]
`)) as BlockFromQuery[]
`)) as BlockFromQueryWithFilters[]
if (!blocks || blocks?.length === 0) return []
blocks = blocks.flat()

const filters = settings.filters?.filter((_filter) => settings.selectedFilters?.includes(_filter.id)) ?? []
const filterBlocks = await retrieveFilteredBlocks(filters)

if (settings.selectedFilters?.length) {
const filterBlocks = await retrieveFilteredBlocks(filters)
const filterBlockIds = filterBlocks.map((block) => block.uuid)
blocks = blocks.filter((block) => filterBlockIds.includes(block.uuid))
blocks = blocks
.filter((block) => filterBlockIds.includes(block.uuid))
.map((block) => {
return {
...block,
filters: filterBlocks
.filter((filterBlock) => filterBlock.uuid === block.uuid)
.map((filterBlock) => filterBlock.filter),
}
})
}
const promiseList: Promise<AgendaTask[]>[] = blocks.map(async (block) => {
const _block = {
Expand Down Expand Up @@ -136,7 +148,16 @@ export const transformBlockToAgendaTask = async (
settings: Settings,
): Promise<AgendaTask> => {
const { general = {} } = settings
const { uuid, marker, content, scheduled: scheduledNumber, deadline: deadlineNumber, properties, page } = block
const {
uuid,
marker,
content,
scheduled: scheduledNumber,
deadline: deadlineNumber,
properties,
page,
filters,
} = block

const title = content.split('\n')[0]?.replace(marker, '')?.trim()

Expand Down Expand Up @@ -240,6 +261,7 @@ export const transformBlockToAgendaTask = async (
estimatedTime,
actualTime,
project: transformPageToProject(page, favoritePages),
filters,
timeLogs,
// TODO: read from logseq
// label: page,
Expand Down Expand Up @@ -439,10 +461,17 @@ export const execQuery = async (query: string): Promise<BlockEntity[] | null> =>
return logseq.DB.datascriptQuery(query)
}

export const retrieveFilteredBlocks = async (filters: Filter[]): Promise<BlockEntity[]> => {
const list = filters.map((filter) => {
return execQuery(filter.query)
type BlockEntityWithFilter = BlockEntity & {
filter: Filter
}
export const retrieveFilteredBlocks = async (filters: Filter[]): Promise<BlockEntityWithFilter[]> => {
const list = filters.map(async (filter) => {
const blocks = await execQuery(filter.query)
return blocks?.flat(Infinity)?.map((block) => ({
...block,
filter,
}))
})
const result = await Promise.all(list)
return result.flat(Infinity).filter(Boolean) as BlockEntity[]
return result.flat(Infinity).filter(Boolean) as BlockEntityWithFilter[]
}
1 change: 1 addition & 0 deletions src/newModel/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ export type Filter = {
id: string
name: string
query: string
color: string
}
5 changes: 4 additions & 1 deletion src/pages/NewDashboard/components/Backlog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ReactSortable } from 'react-sortablejs'
import { navToLogseqBlock } from '@/newHelper/logseq'
import { categorizeTasksByPage, formatTaskTitle } from '@/newHelper/task'
import { logseqAtom } from '@/newModel/logseq'
import { settingsAtom } from '@/newModel/settings'
import { backlogTasksAtom } from '@/newModel/tasks'

import LogseqLogo from './LogseqLogo'
Expand All @@ -21,6 +22,8 @@ const Backlog = ({ bindCalendar = true }: { bindCalendar?: boolean }) => {
const { currentGraph } = useAtomValue(logseqAtom)
const categorizedTasks = categorizeTasksByPage(backlogTasks)
const projects = categorizedTasks.map(({ project }) => project)
const settings = useAtomValue(settingsAtom)
const groupType = settings.selectedFilters?.length ? 'filter' : 'page'

const [filterProjectIds, setFilterProjectIds] = useState<string[]>([])

Expand Down Expand Up @@ -101,7 +104,7 @@ const Backlog = ({ bindCalendar = true }: { bindCalendar?: boolean }) => {
data-event={JSON.stringify({
id: task.id,
title: showTitle,
color: task.project.bgColor,
color: groupType === 'page' ? task.project.bgColor : task.filters?.[0]?.color,
backlog: true,
})}
>
Expand Down
2 changes: 2 additions & 0 deletions src/pages/NewDashboard/components/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const Calendar = ({ onCalendarTitleChange }: CalendarProps, ref) => {
const { updateTaskData, deleteTask, addNewTask } = useAgendaTasks()
const tasksWithStart = useAtomValue(tasksWithStartAtom)
const settings = useAtomValue(settingsAtom)
const groupType = settings.selectedFilters?.length ? 'filter' : 'page'
const showTasks = tasksWithStart?.filter((task) =>
settings.viewOptions?.hideCompleted ? task.status === 'todo' : true,
)
Expand All @@ -60,6 +61,7 @@ const Calendar = ({ onCalendarTitleChange }: CalendarProps, ref) => {
transformAgendaTaskToCalendarEvent(task, {
showFirstEventInCycleOnly: settings.viewOptions?.showFirstEventInCycleOnly,
showTimeLog: settings.viewOptions?.showTimeLog,
groupType,
}),
)
.flat()
Expand Down
31 changes: 31 additions & 0 deletions src/pages/NewDashboard/components/ColorPickerCom.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Button, ColorPicker } from 'antd'
import type { Color } from 'antd/es/color-picker'

import { BACKGROUND_COLOR } from '@/constants/agenda'

const ColorPickerCom = ({ value, onChange }: { value?: string; onChange?: (value: string) => void }) => {
// const [color, setColor] = useState<Color | string>(BACKGROUND_COLOR[DEFAULT_BG_COLOR_NAME])

// const bgColor = useMemo<string>(() => (typeof color === 'string' ? color : color.toHexString()), [color])

const btnStyle: React.CSSProperties = {
backgroundColor: value,
}

return (
<ColorPicker
disabledAlpha
presets={[{ label: 'Recommend', colors: Object.values(BACKGROUND_COLOR) }]}
value={value}
onChange={(color, hex) => {
onChange?.(hex)
}}
>
<Button block type="primary" style={btnStyle}>
Agenda
</Button>
</ColorPicker>
)
}

export default ColorPickerCom
16 changes: 14 additions & 2 deletions src/pages/NewDashboard/components/EditFilterModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Form, Input, Modal } from 'antd'
import { Button, ColorPicker, Form, Input, Modal } from 'antd'
import { useState } from 'react'

import { BACKGROUND_COLOR, DEFAULT_BG_COLOR_NAME } from '@/constants/agenda'
import type { Filter } from '@/newModel/settings'
import { genRandomString } from '@/util/util'

import ColorPickerCom from './ColorPickerCom'

const EditFilterModal = ({
children,
type,
Expand Down Expand Up @@ -35,7 +38,16 @@ const EditFilterModal = ({
onCancel={() => setOpen(false)}
onOk={handleClickOk}
>
<Form<Filter> form={formRef} layout="vertical" initialValues={initialValues} preserve={false} className="mt-8">
<Form<Filter>
form={formRef}
layout="vertical"
initialValues={initialValues ?? { color: BACKGROUND_COLOR[DEFAULT_BG_COLOR_NAME] }}
preserve={false}
className="mt-8"
>
<Form.Item label="Filter Color" name="color" rules={[{ required: true }]}>
<ColorPickerCom />
</Form.Item>
<Form.Item label="Filter Name" name="name" rules={[{ required: true }]}>
<Input />
</Form.Item>
Expand Down
5 changes: 4 additions & 1 deletion src/pages/NewDashboard/components/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ const Filter = () => {
)}
onClick={() => onClickItem(filter)}
>
{filter.name}
<div className="flex gap-1 items-center">
<span className="w-2 h-2 rounded-full" style={{ backgroundColor: filter.color }}></span>
{filter.name}
</div>
<IoMdCheckmark className={cn('invisible', { visible: isSelected })} />
</div>
)
Expand Down
33 changes: 33 additions & 0 deletions src/pages/NewDashboard/components/Group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { type AgendaTask } from '@/types/task'

const Group = ({ task, type }: { task: AgendaTask; type: 'page' | 'filter' }) => {
return type === 'page' ? <RenderPage task={task} /> : <RenderFilter task={task} />
}

function RenderPage({ task }: { task: AgendaTask }) {
return (
<>
{task.project.isJournal ? null : (
<div className="text-gray-400 text-xs flex gap-1 items-center">
<span className="w-2 h-2 rounded-full" style={{ backgroundColor: task.project.bgColor }} />
<span>{task.project?.originalName}</span>
</div>
)}
</>
)
}

function RenderFilter({ task }: { task: AgendaTask }) {
return (
<div className="flex gap-2 items-center">
{task.filters?.map((filter) => (
<div key={filter.id} className="text-gray-400 text-xs flex gap-1 items-center border px-1 rounded-full">
<span className="w-2 h-2 rounded-full" style={{ backgroundColor: filter.color }} />
<span>{filter.name}</span>
</div>
))}
</div>
)
}

export default Group
15 changes: 7 additions & 8 deletions src/pages/NewDashboard/components/KanBan.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { recentTasksAtom } from '@/newModel/tasks'
import type { AgendaTaskWithStart, AgendaTask } from '@/types/task'
import { cn, genDays, replaceDateInfo } from '@/util/util'

import Group from './Group'
import LogseqLogo from './LogseqLogo'
import PlannerModal from './PlannerModal'
import TaskModal from './TaskModal'
Expand Down Expand Up @@ -57,6 +58,8 @@ const KanBan = (props, ref) => {
const days = getRecentDays()
const today = dayjs()

const groupType = settings.selectedFilters?.length ? 'filter' : 'page'

const app = useAtomValue(appAtom)

const [editTaskModal, setEditTaskModal] = useState<{
Expand Down Expand Up @@ -261,7 +264,7 @@ const KanBan = (props, ref) => {
id: task.id,
title: showTitle,
duration: minutesToHHmm(estimatedTime),
color: task.project.bgColor,
color: groupType === 'page' ? task.project.bgColor : task?.filters?.[0]?.color,
})}
>
<Dropdown
Expand Down Expand Up @@ -306,7 +309,8 @@ const KanBan = (props, ref) => {
<span
className="text-[10px] rounded px-1 py-0.5 text-white opacity-70"
style={{
backgroundColor: task.project.bgColor,
backgroundColor:
groupType === 'page' ? task.project.bgColor : task?.filters?.[0]?.color,
}}
>
{task.start.format('HH:mm')}
Expand All @@ -333,12 +337,7 @@ const KanBan = (props, ref) => {
<div className={cn('text-gray-600 my-0.5', { 'line-through': task.status === 'done' })}>
{showTitle}
</div>
{task.project.isJournal ? null : (
<div className="text-gray-400 text-xs flex gap-1 items-center">
<span className="w-2 h-2 rounded-full" style={{ backgroundColor: task.project.bgColor }} />
<span>{task.project?.originalName}</span>
</div>
)}
<Group task={task} type={groupType} />
</div>
</Dropdown>
</div>
Expand Down
15 changes: 13 additions & 2 deletions src/pages/NewDashboard/components/PageSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@ import { Select } from 'antd'

import usePages from '@/hooks/usePages'

const PageSelect = ({ value, onChange }: { value?: string; onChange?: (value: string) => void }) => {
const PageSelect = ({
value,
onChange,
showPageColor = true,
}: {
value?: string
onChange?: (value: string) => void
showPageColor?: boolean
}) => {
const { allPages: pages } = usePages()

return (
<Select
showSearch
Expand All @@ -20,7 +29,9 @@ const PageSelect = ({ value, onChange }: { value?: string; onChange?: (value: st
{pages.map((project) => (
<Select.Option key={project.id} value={project.id} label={project.originalName}>
<div className="flex flex-row items-center gap-1">
<span className="w-2 h-2 rounded-full" style={{ backgroundColor: project.bgColor }}></span>
{showPageColor ? (
<span className="w-2 h-2 rounded-full" style={{ backgroundColor: project.bgColor }}></span>
) : null}
{project.originalName}
</div>
</Select.Option>
Expand Down

0 comments on commit d8322d9

Please sign in to comment.