-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
330 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { CreateRecordCommandHandler } from './create-record.command.handler' | ||
import { CreateTableCommandHandler } from './create-table.command.handler' | ||
import { SetFiltersCommandHandler } from './set-filters.command.handler' | ||
|
||
export const commandHandlers = [CreateTableCommandHandler, CreateRecordCommandHandler] | ||
export const commandHandlers = [CreateTableCommandHandler, CreateRecordCommandHandler, SetFiltersCommandHandler] |
14 changes: 14 additions & 0 deletions
14
apps/backend/src/modules/table/commands/set-filters.command.handler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { SetFiltersCommandHandler as DomainHandler, SetFitlersCommand, type ITableRepository } from '@egodb/core' | ||
import type { ICommandHandler } from '@nestjs/cqrs' | ||
import { CommandHandler } from '@nestjs/cqrs' | ||
import { InjectTableReposiory } from '../adapters' | ||
|
||
@CommandHandler(SetFitlersCommand) | ||
export class SetFiltersCommandHandler extends DomainHandler implements ICommandHandler<SetFitlersCommand> { | ||
constructor( | ||
@InjectTableReposiory() | ||
protected readonly repo: ITableRepository, | ||
) { | ||
super(repo) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import type { Field, IFieldValue, IOperator, IRecordOperator, Table } from '@egodb/core' | ||
import { Group } from '@egodb/ui' | ||
import { useEffect, useState } from 'react' | ||
import { FieldSelector } from './field-selector' | ||
import { FilterValueInput } from './filter-value-input' | ||
import { OperatorSelector } from './operator-selector' | ||
|
||
interface IProps { | ||
schema: Table['schema'] | ||
index: number | ||
onChange: (field: IRecordOperator | null, index: number) => void | ||
} | ||
|
||
export const FieldFilter: React.FC<IProps> = ({ schema, onChange, index }) => { | ||
const [selectedField, setField] = useState<Field | null>(null) | ||
const [operator, setOperator] = useState<IOperator.LeafOperator | null>(null) | ||
const [value, setValue] = useState<IFieldValue | null>(null) | ||
|
||
useEffect(() => { | ||
if (selectedField && operator) { | ||
onChange(selectedField.createFilter(operator, value), index) | ||
} else { | ||
onChange(null, index) | ||
} | ||
}, [selectedField, operator, value]) | ||
|
||
useEffect(() => { | ||
if (!selectedField) { | ||
setOperator(null) | ||
} | ||
}, [selectedField]) | ||
|
||
return ( | ||
<Group> | ||
<FieldSelector schema={schema} onChange={setField} /> | ||
<OperatorSelector field={selectedField} value={operator} onChange={setOperator} /> | ||
<FilterValueInput field={selectedField} onChange={setValue} /> | ||
</Group> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { Field, Table } from '@egodb/core' | ||
import { Select } from '@egodb/ui' | ||
import { FieldInputLabel } from '../fields/field-input-label' | ||
|
||
interface IProps { | ||
schema: Table['schema'] | ||
onChange: (field: Field | null) => void | ||
} | ||
export const FieldSelector: React.FC<IProps> = ({ schema, onChange }) => { | ||
return ( | ||
<Select | ||
label={<FieldInputLabel>Field</FieldInputLabel>} | ||
searchable | ||
clearable | ||
onChange={(value) => { | ||
onChange(value ? schema.getField(value).into(null) : null) | ||
}} | ||
placeholder="search field" | ||
data={schema.fields.map((f) => ({ | ||
value: f.name.value, | ||
label: f.name.value, | ||
}))} | ||
/> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import type { Field, IFieldValue } from '@egodb/core' | ||
import { NumberField } from '@egodb/core' | ||
import { TextField } from '@egodb/core' | ||
import { NumberInput, TextInput } from '@egodb/ui' | ||
import { FieldInputLabel } from '../fields/field-input-label' | ||
|
||
interface IProps { | ||
field: Field | null | ||
onChange: (v: IFieldValue) => void | ||
} | ||
|
||
export const FilterValueInput: React.FC<IProps> = ({ field, onChange }) => { | ||
if (!field) { | ||
return null | ||
} | ||
|
||
const label = <FieldInputLabel>value</FieldInputLabel> | ||
|
||
if (field instanceof TextField) { | ||
return <TextInput label={label} onChange={(event) => onChange(event.target.value)} /> | ||
} | ||
|
||
if (field instanceof NumberField) { | ||
return <NumberInput label={label} onChange={(number) => onChange(number || null)} /> | ||
} | ||
|
||
return null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import type { IRecordOperator, TableSchema } from '@egodb/core' | ||
import { Box, Button, Divider, Group, IconPlus, Stack, useListState } from '@egodb/ui' | ||
import { FieldFilter } from './field-filter' | ||
import useDeepCompareEffect from 'use-deep-compare-effect' | ||
|
||
interface IProps { | ||
schema: TableSchema | ||
onChange?: (filters: IRecordOperator[]) => void | ||
onApply?: (filters: IRecordOperator[]) => void | ||
onCancel?: () => void | ||
} | ||
|
||
export const FiltersEditor: React.FC<IProps> = ({ schema, onChange, onApply, onCancel }) => { | ||
const [filters, handlers] = useListState<IRecordOperator | null>([null]) | ||
const validFilters = filters.filter((f) => f !== null) as IRecordOperator[] | ||
|
||
useDeepCompareEffect(() => { | ||
onChange?.(validFilters) | ||
}, [validFilters]) | ||
|
||
return ( | ||
<Box miw={640}> | ||
<Stack> | ||
{filters.map((_, index) => ( | ||
<FieldFilter | ||
key={index} | ||
schema={schema} | ||
index={index} | ||
onChange={(operator, index) => handlers.setItem(index, operator)} | ||
/> | ||
))} | ||
<Divider h="md" /> | ||
<Group position="apart"> | ||
<Button variant="outline" size="xs" leftIcon={<IconPlus size={14} />} onClick={() => handlers.append(null)}> | ||
Add new filter | ||
</Button> | ||
<Group> | ||
<Button onClick={onCancel} variant="subtle" size="xs"> | ||
Cancel | ||
</Button> | ||
<Button size="xs" onClick={() => onApply?.(validFilters)}> | ||
Apply | ||
</Button> | ||
</Group> | ||
</Group> | ||
</Stack> | ||
</Box> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import type { Field, IOperator } from '@egodb/core' | ||
import { NumberField, TextField } from '@egodb/core' | ||
import type { SelectItem } from '@egodb/ui' | ||
import { Select } from '@egodb/ui' | ||
import { FieldInputLabel } from '../fields/field-input-label' | ||
|
||
interface IProps { | ||
field: Field | null | ||
value: IOperator.LeafOperator | null | ||
onChange: (operator: IOperator.LeafOperator | null) => void | ||
} | ||
|
||
export const OperatorSelector: React.FC<IProps> = ({ value, field, onChange }) => { | ||
const label = <FieldInputLabel>Operator</FieldInputLabel> | ||
let data: SelectItem[] = [] | ||
|
||
// TODO: optimize if else | ||
if (field instanceof TextField) { | ||
data = [ | ||
{ value: '$eq', label: 'equal' }, | ||
{ value: '$neq', label: 'not equal' }, | ||
] | ||
} else if (field instanceof NumberField) { | ||
data = [ | ||
{ value: '$eq', label: 'equal' }, | ||
{ value: '$neq', label: 'not equal' }, | ||
] | ||
} | ||
|
||
return ( | ||
<Select | ||
value={value} | ||
disabled={!field} | ||
label={label} | ||
data={data} | ||
onChange={(value) => onChange(value as IOperator.LeafOperator | null)} | ||
/> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,37 @@ | ||
import { Button, IconFilter } from '@egodb/ui' | ||
import { Button, IconFilter, Popover, useDisclosure } from '@egodb/ui' | ||
import { trpc } from '../../trpc' | ||
import { FiltersEditor } from '../filters-editor/filters-editor' | ||
import type { ITableBaseProps } from './table-base-props' | ||
|
||
export const TableFilterEditor: React.FC<ITableBaseProps> = () => { | ||
export const TableFilterEditor: React.FC<ITableBaseProps> = ({ table }) => { | ||
const [opened, handler] = useDisclosure(false) | ||
|
||
const utils = trpc.useContext() | ||
|
||
const setFilters = trpc.table.setFilters.useMutation({ | ||
onSuccess: () => { | ||
handler.close() | ||
utils.record.list.refetch({ tableId: table.id.value }) | ||
}, | ||
}) | ||
|
||
return ( | ||
<Button variant="white" leftIcon={<IconFilter />}> | ||
Filter | ||
</Button> | ||
<Popover position="bottom-start" opened={opened} onChange={handler.toggle} closeOnClickOutside> | ||
<Popover.Target> | ||
<Button variant="white" leftIcon={<IconFilter size={18} />} onClick={handler.open}> | ||
Filter | ||
</Button> | ||
</Popover.Target> | ||
|
||
<Popover.Dropdown> | ||
<FiltersEditor | ||
schema={table.schema} | ||
onApply={(filters) => { | ||
setFilters.mutate({ tableId: table.id.value, filters }) | ||
}} | ||
onCancel={handler.close} | ||
/> | ||
</Popover.Dropdown> | ||
</Popover> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
packages/core/commands/set-filters/set-filters.command.input.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
import { z } from 'zod' | ||
import { $filter } from '../../filter' | ||
import { $filters } from '../../filter' | ||
import { tableIdSchema } from '../../value-objects' | ||
import { viewNameSchema } from '../../view' | ||
|
||
export const setFiltersCommandInput = z.object({ | ||
tableId: tableIdSchema, | ||
viewName: viewNameSchema.optional(), | ||
filters: $filter, | ||
filters: $filters, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.