Skip to content

Commit

Permalink
feat(web): update kanban field id
Browse files Browse the repository at this point in the history
  • Loading branch information
nichenqin committed Jan 1, 2023
1 parent c1259eb commit c105175
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 52 deletions.
5 changes: 5 additions & 0 deletions apps/web/components/kanban-ui/kanban-edit-field.atom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { atom } from 'jotai'

export const openKanbanEditFieldAtom = atom(false)

export const openKanbanEditField = atom(null, (_, set) => set(openKanbanEditFieldAtom, true))
9 changes: 8 additions & 1 deletion apps/web/components/kanban-ui/kanban.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { QueryRecords } from '@egodb/core'
import type { IKanbanField } from '@egodb/core/view/kanban.schema'
import { Container, Center } from '@egodb/ui'
import type { ITableBaseProps } from '../table/table-base-props'
import { KanbanBoard } from './board'
import { SelectKanbanField } from './select-kanban-field'
Expand All @@ -12,7 +13,13 @@ export const Kanban: React.FC<IProps> = ({ table, records }) => {
const view = table.mustGetView()
const fieldId = view.kanbanSelectFieldId
if (fieldId.isNone()) {
return <SelectKanbanField table={table} />
return (
<Container h="100%">
<Center h="100%">
<SelectKanbanField table={table} />
</Center>
</Container>
)
}

const field = table.schema.getFieldById(fieldId.unwrap().value).unwrap()
Expand Down
33 changes: 29 additions & 4 deletions apps/web/components/kanban-ui/select-board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import {
} from '@dnd-kit/core'
import { restrictToHorizontalAxis } from '@dnd-kit/modifiers'
import { horizontalListSortingStrategy, SortableContext, sortableKeyboardCoordinates } from '@dnd-kit/sortable'
import type { SelectField } from '@egodb/core'
import type { QueryRecords } from '@egodb/core'
import { Container, Group, useListState } from '@egodb/ui'
import { useState } from 'react'
import type { QueryRecords, SelectField } from '@egodb/core'
import { Container, Group, Modal, useEgoUITheme, useListState } from '@egodb/ui'
import { useAtom } from 'jotai'
import { useEffect, useState } from 'react'
import { trpc } from '../../trpc'
import type { ITableBaseProps } from '../table/table-base-props'
import { openKanbanEditFieldAtom } from './kanban-edit-field.atom'
import { KanbanLane, SortableKanbanLane } from './kanban-lane'
import { SelectKanbanField } from './select-kanban-field'

interface IProps extends ITableBaseProps {
field: SelectField
Expand All @@ -25,6 +27,11 @@ interface IProps extends ITableBaseProps {

export const SelectBoard: React.FC<IProps> = ({ table, field, records }) => {
const [options, handlers] = useListState(field.options.options)

useEffect(() => {
handlers.setState(field.options.options)
}, [field])

const items = options.map((o) => o.id.value)
const sensors = useSensors(
useSensor(MouseSensor),
Expand All @@ -39,8 +46,26 @@ export const SelectBoard: React.FC<IProps> = ({ table, field, records }) => {

const reorderOptions = trpc.table.reorderOptions.useMutation()

const [opened, setOpened] = useAtom(openKanbanEditFieldAtom)

const theme = useEgoUITheme()

return (
<Container fluid ml={0}>
{opened && (
<Modal
target="body"
withCloseButton={false}
opened={opened}
onClose={() => setOpened(false)}
overlayColor={theme.colorScheme === 'dark' ? theme.colors.dark[9] : theme.colors.gray[2]}
overlayOpacity={0.55}
overlayBlur={3}
>
<SelectKanbanField table={table} onSuccess={() => setOpened(false)} />
</Modal>
)}

<Group>
<KanbanLane table={table} field={field} records={records} title="uncategorized" id={null} />

Expand Down
21 changes: 16 additions & 5 deletions apps/web/components/kanban-ui/select-existing-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@ import { trpc } from '../../trpc'
import type { ITableBaseProps } from '../table/table-base-props'
import { stepOneAtom } from './kanban-step.atom'

export const SelectExistingField: React.FC<ITableBaseProps> = ({ table }) => {
interface IProps extends ITableBaseProps {
onSuccess?: () => void
}

export const SelectExistingField: React.FC<IProps> = ({ table, onSuccess }) => {
const selectFields = table.schema.selectFields
const view = table.mustGetView()
const initialSelectFieldId = view.kanban.into()?.fieldId?.value
const hasSelectFields = selectFields.length > 0

const utils = trpc.useContext()
const setKanbanField = trpc.table.setKanbanField.useMutation({
onSuccess() {
utils.table.get.refetch()
onSuccess?.()
},
})

const form = useForm({
initialValues: {
field: '',
field: initialSelectFieldId ?? '',
},
validate: zodResolver(setKanbanFieldSchema),
})
Expand All @@ -34,7 +41,7 @@ export const SelectExistingField: React.FC<ITableBaseProps> = ({ table }) => {

return (
<form onSubmit={onSubmit}>
<Card shadow={'sm'} w={450}>
<Card shadow={'sm'}>
<Card.Section withBorder inheritPadding py="sm">
<Text>select one field</Text>
</Card.Section>
Expand All @@ -43,7 +50,11 @@ export const SelectExistingField: React.FC<ITableBaseProps> = ({ table }) => {
<Stack spacing="xs">
{hasSelectFields ? (
<>
<Radio.Group {...form.getInputProps('field')}>
<Radio.Group
orientation="vertical"
defaultValue={initialSelectFieldId}
{...form.getInputProps('field')}
>
{selectFields.map((f) => (
<Radio key={f.id.value} value={f.id.value} label={f.name.value} />
))}
Expand All @@ -60,7 +71,7 @@ export const SelectExistingField: React.FC<ITableBaseProps> = ({ table }) => {

<Card.Section withBorder inheritPadding py="sm">
<Group position="right">
<Button size="xs" type="submit" disabled={!form.isValid()}>
<Button size="xs" type="submit" disabled={!form.isValid() || !form.isDirty()}>
Done
</Button>
</Group>
Expand Down
17 changes: 9 additions & 8 deletions apps/web/components/kanban-ui/select-kanban-field.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { Center, Container } from '@egodb/ui'
import { useAtomValue } from 'jotai'
import type { ITableBaseProps } from '../table/table-base-props'
import { CreateSelectField } from './create-select-field'
import { stepAtom } from './kanban-step.atom'
import { SelectExistingField } from './select-existing-field'

export const SelectKanbanField: React.FC<ITableBaseProps> = ({ table }) => {
interface IProps extends ITableBaseProps {
onSuccess?: () => void
}

export const SelectKanbanField: React.FC<IProps> = ({ table, onSuccess }) => {
const step = useAtomValue(stepAtom)

return (
<Container h="100%">
<Center h="100%">
{step === 0 ? <SelectExistingField table={table} /> : null}
{step === 1 ? <CreateSelectField table={table} /> : null}
</Center>
</Container>
<>
{step === 0 ? <SelectExistingField onSuccess={onSuccess} table={table} /> : null}
{step === 1 ? <CreateSelectField table={table} /> : null}
</>
)
}
106 changes: 72 additions & 34 deletions apps/web/components/table/toolbar-view.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
import type { IViewDisplayType } from '@egodb/core'
import { Button, Menu, SegmentedControl, Tooltip, useDisclosure } from '@egodb/ui'
import type { IViewDisplayType, Kanban } from '@egodb/core'
import type { FieldId } from '@egodb/core'
import type { Table } from '@egodb/core'
import { Button, IconSelect, Menu, SegmentedControl, Tooltip, useDisclosure } from '@egodb/ui'
import { useSetAtom } from 'jotai'
import { trpc } from '../../trpc'
import { openKanbanEditField } from '../kanban-ui/kanban-edit-field.atom'
import { DisplayTypeIcon } from '../view/display-type-icon'
import type { ITableBaseProps } from './table-base-props'

const StackedBy: React.FC<{ fieldId?: FieldId; table: Table }> = ({ table, fieldId }) => {
const setOpened = useSetAtom(openKanbanEditField)
if (!fieldId) return null

const field = table.schema.getFieldById(fieldId.value).into()
if (!field) return null

return (
<Tooltip label="stacked by">
<Button
onClick={setOpened}
compact
variant="subtle"
leftIcon={<IconSelect size={18} />}
>{`stacked by ${field.name.value}`}</Button>
</Tooltip>
)
}

const KanbanControl: React.FC<{ table: Table; kanban?: Kanban }> = ({ table, kanban }) => {
return (
<>
<StackedBy fieldId={kanban?.fieldId} table={table} />
</>
)
}

export const ToolbarView: React.FC<ITableBaseProps> = ({ table }) => {
const [opened, toggle] = useDisclosure(false)
const view = table.mustGetView()

const displayType = view.displayType

const utils = trpc.useContext()
const switchDisplayType = trpc.table.switchDisplayType.useMutation({
onSuccess() {
Expand All @@ -16,37 +50,41 @@ export const ToolbarView: React.FC<ITableBaseProps> = ({ table }) => {
})

return (
<Menu opened={opened} closeOnItemClick closeOnClickOutside onClose={toggle.close}>
<Menu.Target>
<Tooltip label={view.displayType}>
<Button
compact
variant="subtle"
onClick={toggle.toggle}
leftIcon={<DisplayTypeIcon displayType={view.displayType} />}
>
{view.name.unpack()}
</Button>
</Tooltip>
</Menu.Target>

<Menu.Dropdown>
<SegmentedControl
data={[
{ label: 'Grid', value: 'grid' },
{ label: 'Kanban', value: 'kanban' },
]}
onChange={(type) => {
switchDisplayType.mutate({
tableId: table.id.value,
viewName: view.name.unpack(),
displayType: type as IViewDisplayType,
})
}}
value={view.displayType}
defaultValue={view.displayType}
/>
</Menu.Dropdown>
</Menu>
<Button.Group>
<Menu opened={opened} closeOnItemClick closeOnClickOutside onClose={toggle.close}>
<Menu.Target>
<Tooltip label={view.displayType}>
<Button
compact
variant="subtle"
onClick={toggle.toggle}
leftIcon={<DisplayTypeIcon displayType={view.displayType} />}
>
{view.name.unpack()}
</Button>
</Tooltip>
</Menu.Target>

<Menu.Dropdown>
<SegmentedControl
data={[
{ label: 'Grid', value: 'grid' },
{ label: 'Kanban', value: 'kanban' },
]}
onChange={(type) => {
switchDisplayType.mutate({
tableId: table.id.value,
viewName: view.name.unpack(),
displayType: type as IViewDisplayType,
})
}}
value={view.displayType}
defaultValue={view.displayType}
/>
</Menu.Dropdown>
</Menu>

{displayType === 'kanban' ? <KanbanControl table={table} kanban={view.kanban.into()} /> : null}
</Button.Group>
)
}
1 change: 1 addition & 0 deletions packages/core/view/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './kanban'
export * from './specifications'
export * from './view'
export * from './view-field-options'
Expand Down
1 change: 1 addition & 0 deletions packages/ui/Overlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Overlay } from '@mantine/core'
1 change: 1 addition & 0 deletions packages/ui/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './emotion'
export * from './Alert'
export * from './Accordion'
export * from './Icon'
export * from './Overlay'
export * from './Table'
export * from './Date'
export * from './Layout'
Expand Down

0 comments on commit c105175

Please sign in to comment.