Skip to content

Commit

Permalink
feat: empty kanban lane
Browse files Browse the repository at this point in the history
  • Loading branch information
nichenqin committed Sep 8, 2024
1 parent 3b9198a commit 6a2cb04
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
export let viewId: string
export let fieldId: string
export let field: SelectField
export let option: IOption
export let option: IOption | null
export let readonly = false
export let shareId: string
Expand All @@ -40,7 +40,7 @@
shareId,
filters: {
conjunction: "and",
children: [{ field: fieldId, op: "eq", value: option.id }],
children: [{ field: fieldId, op: "eq", value: option ? option.id : null }],
},
pagination: {
page: pageParam,
Expand All @@ -54,7 +54,7 @@
viewId,
filters: {
conjunction: "and",
children: [{ field: fieldId, op: "eq", value: option.id }],
children: [{ field: fieldId, op: "eq", value: option ? option.id : null }],
},
pagination: {
page: pageParam,
Expand All @@ -64,7 +64,7 @@
}
const query = createInfiniteQuery({
queryKey: [tableId, fieldId, "getRecords", option.id],
queryKey: [tableId, fieldId, "getRecords", option?.id],
queryFn: getRecords,
initialPageParam: 1,
getNextPageParam: (lastPage, pages) => {
Expand All @@ -81,7 +81,7 @@
const updateRecord = createMutation({
mutationFn: trpc.record.update.mutate,
onSuccess: (data, variables, context) => {
recordsStore.setRecordValue(variables.id, fieldId, option.id)
recordsStore.setRecordValue(variables.id, fieldId, option ? option.id : null)
recordsStore.invalidateRecord($table, variables.id)
},
})
Expand All @@ -108,7 +108,7 @@
option: {
options: field.option
.unwrapOrElse(() => ({ options: [] }))
.options.map((o) => (o.id === option.id ? { ...option } : o)),
.options.map((o) => (o.id === option?.id ? { ...option } : o)),
},
},
})
Expand All @@ -122,14 +122,14 @@
type: "select",
name: field.name.value,
option: {
options: field.option.unwrapOrElse(() => ({ options: [] })).options.filter((o) => o.id !== option.id),
options: field.option.unwrapOrElse(() => ({ options: [] })).options.filter((o) => o.id !== option?.id),
},
},
})
}
onMount(() => {
if (!shareId) {
if (!shareId && !readonly) {
new Sortable(laneElement, {
group: "shared",
animation: 150,
Expand All @@ -139,8 +139,7 @@
onEnd: (evt) => {
const recordId = evt.item.dataset.recordId
if (!recordId) return
const optionId = evt.to.dataset.optionId
if (!optionId) return
const optionId = evt.to.dataset.optionId ?? null
$updateRecord.mutate({
tableId,
Expand All @@ -160,7 +159,7 @@
recordsStore.upsertRecords(Records.fromJSON($table, records))
}
$: recordDos = recordsStore.getRecords(Some(new SelectEqual(option.id, new FieldIdVo(fieldId))))
$: recordDos = recordsStore.getRecords(Some(new SelectEqual(option?.id ?? null, new FieldIdVo(fieldId))))
$: fields = $table.getOrderedVisibleFields(viewId) ?? []
Expand All @@ -169,20 +168,25 @@
</script>

<div
data-option-id={option.id}
data-option-id={option?.id ?? null}
class="kanban-lane flex w-[350px] shrink-0 flex-col space-y-2 rounded-sm px-2 pt-2 transition-all"
>
<div class="flex w-full items-center justify-between gap-1">
<div class="flex items-center gap-1">
{#if !shareId}
{#if !shareId && option && !readonly}
<div class="lane-handle cursor-move">
<GripVerticalIcon class="text-muted-foreground h-4 w-4" />
</div>
{/if}
<Option {option} />

{#if option}
<Option {option} />
{:else}
<Option option={{ id: "", name: "No Option", color: "gray" }} />
{/if}
</div>

{#if !shareId && !readonly}
{#if !shareId && !readonly && option}
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild let:builder>
<Button size="xs" variant="ghost" builders={[builder]}>
Expand All @@ -208,17 +212,17 @@
</DropdownMenu.Root>
{/if}
</div>
<div class="max-w-[350px] flex-1 space-y-2 overflow-auto" data-option-id={option.id}>
<div class="max-w-[350px] flex-1 space-y-2 overflow-auto" data-option-id={option?.id ?? null}>
<div
bind:this={laneElement}
data-option-id={option.id}
data-option-id={option?.id ?? null}
class="min-h-[200px] space-y-2 rounded-lg border bg-gray-100 p-2"
>
{#if !readonly && $hasPermission("record:create")}
<Button
on:click={() => {
$defaultRecordValues = {
[fieldId]: option.id,
[fieldId]: option ? option.id : null,
}
toggleModal(CREATE_RECORD_MODAL)
}}
Expand Down Expand Up @@ -253,27 +257,31 @@
</div>
</div>

<Dialog.Root bind:open={updateOptionDialogOpen}>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Update option</Dialog.Title>
</Dialog.Header>
{#if option}
<Dialog.Root bind:open={updateOptionDialogOpen}>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Update option</Dialog.Title>
</Dialog.Header>

<form on:submit|preventDefault={() => updateOption()}>
<OptionEditor bind:name={option.name} bind:color={option.color} />
<Button type="submit" disabled={$updateFieldMutation.isPending} class="mt-2 w-full">Update</Button>
</form>
</Dialog.Content>
</Dialog.Root>
<form on:submit|preventDefault={() => updateOption()}>
<OptionEditor bind:name={option.name} bind:color={option.color} />
<Button type="submit" disabled={$updateFieldMutation.isPending} class="mt-2 w-full">Update</Button>
</form>
</Dialog.Content>
</Dialog.Root>
{/if}

<AlertDialog.Root bind:open={deleteOptionDialogOpen}>
<AlertDialog.Content>
<AlertDialog.Header>
<AlertDialog.Title>Delete Option <Option {option} /></AlertDialog.Title>
</AlertDialog.Header>
<AlertDialog.Footer>
<AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
<AlertDialog.Action on:click={() => deleteOption()}>Continue</AlertDialog.Action>
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog.Root>
{#if option}
<AlertDialog.Root bind:open={deleteOptionDialogOpen}>
<AlertDialog.Content>
<AlertDialog.Header>
<AlertDialog.Title>Delete Option <Option {option} /></AlertDialog.Title>
</AlertDialog.Header>
<AlertDialog.Footer>
<AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
<AlertDialog.Action on:click={() => deleteOption()}>Continue</AlertDialog.Action>
</AlertDialog.Footer>
</AlertDialog.Content>
</AlertDialog.Root>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@

<div class="flex-1 overflow-x-auto overflow-y-hidden p-4">
<div bind:this={lanesContainer} class="flex h-full overflow-y-hidden pr-4">
<SelectKanbanLane
{field}
{readonly}
tableId={$table.id.value}
viewId={view.id.value}
{fieldId}
option={null}
{shareId}
/>
{#each options as option (option.id)}
<SelectKanbanLane
{field}
Expand Down
35 changes: 26 additions & 9 deletions packages/persistence/src/record/record.filter-visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,14 @@ export class RecordFilterVisitor extends AbstractQBVisitor<RecordDO> implements
this.addCond(cond)
}
dateEqual(spec: DateEqual): void {
this.addCond(this.eb.eb(this.getFieldId(spec), "=", spec.date?.getTime() ?? null))
const time = spec.date?.getTime()
if (time === null) {
const cond = this.eb.eb(this.getFieldId(spec), "is", null)
this.addCond(cond)
} else {
const cond = this.eb.eb(this.getFieldId(spec), "=", time)
this.addCond(cond)
}
}
attachmentEqual(s: AttachmentEqual): void {
throw new Error("Method not implemented.")
Expand All @@ -123,7 +130,7 @@ export class RecordFilterVisitor extends AbstractQBVisitor<RecordDO> implements
}
userEqual(spec: UserEqual): void {
if (spec.value === null) {
const cond = this.eb.eb(this.getFieldId(spec), "=", null)
const cond = this.eb.eb(this.getFieldId(spec), "is", null)
this.addCond(cond)
} else {
function convertMacro(value: string) {
Expand All @@ -140,9 +147,14 @@ export class RecordFilterVisitor extends AbstractQBVisitor<RecordDO> implements
const cond = this.eb.eb(this.getFieldId(spec), "=", JSON.stringify(converted))
this.addCond(cond)
} else {
const converted = spec.value ? convertMacro(spec.value) : null
const cond = this.eb.eb(this.getFieldId(spec), "=", converted)
this.addCond(cond)
if (!spec.value) {
const cond = this.eb.eb(this.getFieldId(spec), "is", null)
this.addCond(cond)
} else {
const converted = convertMacro(spec.value)
const cond = this.eb.eb(this.getFieldId(spec), "=", converted)
this.addCond(cond)
}
}
}
}
Expand All @@ -151,8 +163,13 @@ export class RecordFilterVisitor extends AbstractQBVisitor<RecordDO> implements
this.addCond(cond)
}
currencyEqual(spec: CurrencyEqual): void {
const cond = this.eb.eb(this.getFieldId(spec), "=", spec.value === null ? null : spec.value * 100)
this.addCond(cond)
if (spec.value === null) {
const cond = this.eb.eb(this.getFieldId(spec), "is", null)
this.addCond(cond)
} else {
const cond = this.eb.eb(this.getFieldId(spec), "=", spec.value * 100)
this.addCond(cond)
}
}
percentageEqual(spec: PercentageEqual): void {
const cond = this.eb.eb(this.getFieldId(spec), "=", spec.value)
Expand Down Expand Up @@ -204,7 +221,7 @@ export class RecordFilterVisitor extends AbstractQBVisitor<RecordDO> implements
}
selectEqual(spec: SelectEqual): void {
if (spec.value === null) {
const cond = this.eb.eb(this.getFieldId(spec), "=", null)
const cond = this.eb.eb(this.getFieldId(spec), "is", null)
this.addCond(cond)
} else {
const cond = this.eb.eb(
Expand All @@ -216,7 +233,7 @@ export class RecordFilterVisitor extends AbstractQBVisitor<RecordDO> implements
}
}
selectEmpty(spec: SelectEmpty): void {
const cond = this.eb.eb(this.getFieldId(spec), "=", null)
const cond = this.eb.eb(this.getFieldId(spec), "is", null)
this.addCond(cond)
}
selectContainsAnyOf(spec: SelectContainsAnyOf): void {
Expand Down
6 changes: 5 additions & 1 deletion packages/persistence/src/record/record.mutate-visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,11 @@ export class RecordMutateVisitor extends AbstractQBMutationVisitor implements IR
const fieldValue = new SelectFieldValue(spec.value)
const value = fieldValue.getValue(field)

this.setData(spec.fieldId.value, Array.isArray(value) ? JSON.stringify(value) : value)
if (Array.isArray(value)) {
this.setData(spec.fieldId.value, value.length ? JSON.stringify(value) : null)
} else {
this.setData(spec.fieldId.value, value ?? null)
}
}
selectContainsAnyOf(spec: SelectContainsAnyOf): void {
throw new Error("Method not implemented.")
Expand Down

0 comments on commit 6a2cb04

Please sign in to comment.