Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release version v1.0.0-99 #2088

Merged
merged 8 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## v1.0.0-99


### 🏡 Chore

- Hide widget type ([d886315](https://github.com/undb-io/undb/commit/d886315))

### ❤️ Contributors

- Nichenqin ([@nichenqin](http://github.com/nichenqin))

## v1.0.0-98

## v1.0.0-97
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<script lang="ts">
import Check from "svelte-radix/Check.svelte"
import CaretSort from "svelte-radix/CaretSort.svelte"
import { tick } from "svelte"
import * as Command from "$lib/components/ui/command/index.js"
import * as Popover from "$lib/components/ui/popover/index.js"
import { Button } from "$lib/components/ui/button/index.js"
import { cn } from "$lib/utils.js"
import { LL } from "@undb/i18n/client"

let open = false
export let value: "sum" | "avg" | "max" | "min" | undefined = undefined
export let onValueChange: (value: "sum" | "avg" | "max" | "min") => void = () => {}

const aggregateTypes = ["sum", "avg", "max", "min"] as const

let search = ""

$: filtered = aggregateTypes.filter((type) => type.toLowerCase().includes(search.toLowerCase()))

$: selected = aggregateTypes.find((type) => type === value)
$: selectedValue = selected ?? "Select aggregate type..."

function closeAndFocusTrigger(triggerId: string) {
open = false
tick().then(() => {
document.getElementById(triggerId)?.focus()
})
}

export let sameWidth = true
</script>

<Popover.Root bind:open let:ids portal="body">
<Popover.Trigger asChild let:builder>
<Button
size="sm"
builders={[builder]}
variant="outline"
role="combobox"
aria-expanded={open}
{...$$restProps}
class={cn("w-full justify-between", $$restProps.class)}
>
<span class="flex items-center overflow-hidden text-ellipsis" title={selectedValue}>
{#if selected}
<slot>
{$LL.table.aggregateFns[selected]()}
</slot>
{/if}
</span>
<CaretSort class="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</Popover.Trigger>
<Popover.Content class="p-0" {sameWidth}>
<Command.Root shouldFilter={false}>
<Command.Input bind:value={search} placeholder="Search aggregate type..." class="h-9" />
<Command.Empty>No aggregate type found</Command.Empty>
<Command.Group class="max-h-[300px] overflow-y-auto">
{#each filtered as type}
<Command.Item
value={type}
onSelect={(currentValue) => {
value = currentValue
if (value) {
onValueChange(value)
}
closeAndFocusTrigger(ids.trigger)
}}
>
<Check class={cn("mr-2 h-4 w-4", value !== type && "text-transparent")} />
<span class="text-xs">
{$LL.table.aggregateFns[type]()}
</span>
</Command.Item>
{/each}
</Command.Group>
</Command.Root>
</Popover.Content>
</Popover.Root>
62 changes: 55 additions & 7 deletions apps/frontend/src/lib/components/blocks/aggregate/aggregate.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
<script lang="ts">
import type { ComponentType } from "svelte"
import type { IAggregate } from "@undb/table/src/modules/aggregate/aggregate.vo"
import CountAggregate from "./count-aggregate.svelte"
import { getTable } from "$lib/store/table.store"
import { trpc } from "$lib/trpc/client"
import { cn } from "$lib/utils"
import { createQuery } from "@tanstack/svelte-query"
import { ID_TYPE, type IAggregate } from "@undb/table"
import { derived } from "svelte/store"

const table = getTable()
export let viewId: string | undefined

export let aggregate: IAggregate

const map: Record<string, ComponentType> = {
count: CountAggregate,
}
const getAggregate = createQuery({
queryKey: ["aggregate", $table.id.value],
queryFn: () => {
if (aggregate.type === "count") {
return trpc.record.aggregate.query({
tableId: $table.id.value,
viewId,
aggregate: { [ID_TYPE]: "count" },
condition: aggregate.condition,
})
}

if (aggregate.config.field) {
return trpc.record.aggregate.query({
tableId: $table.id.value,
viewId,
aggregate: { [aggregate.config.field]: aggregate.type },
condition: aggregate.condition,
})
}
},
})

let count = derived(
getAggregate,
($data) => ($data.data as any)?.[aggregate.type === "count" ? ID_TYPE : aggregate.config.field!],
)
$: isPending = $getAggregate.isPending
</script>

<svelte:component this={map[aggregate.type]} />
<div class={cn("flex h-full w-full items-center justify-center rounded-lg bg-white p-6", $$restProps.class)}>
{#if isPending}
<div class="flex animate-pulse space-x-4">
<div class="h-16 w-16 rounded-full bg-slate-200"></div>
<div class="flex-1 space-y-6 py-1">
<div class="h-4 rounded bg-slate-200"></div>
<div class="space-y-3">
<div class="grid grid-cols-3 gap-4">
<div class="col-span-2 h-4 rounded bg-slate-200"></div>
<div class="col-span-1 h-4 rounded bg-slate-200"></div>
</div>
</div>
</div>
</div>
{:else}
<span class="text-8xl font-bold">{$count}</span>
{/if}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<script lang="ts">
import * as Tabs from "$lib/components/ui/tabs"
import { getTable } from "$lib/store/table.store"
import { invalidate } from "$app/navigation"
import {
filterAggregateField,
getIsFilterableFieldType,
parseValidAggregateCondition,
toMaybeConditionGroup,
type IAggregate,
type IAggregateCondition,
type IWidgetDTO,
type MaybeConditionGroup,
} from "@undb/table"
import { writable } from "svelte/store"
import FiltersEditor from "../../filters-editor/filters-editor.svelte"
import { createMutation, useQueryClient } from "@tanstack/svelte-query"
import { trpc } from "$lib/trpc/client"
import { Button } from "$lib/components/ui/button"
import { SaveIcon } from "lucide-svelte"
import FieldPicker from "../../field-picker/field-picker.svelte"
import AggregateTypePicker from "../aggregate-type-picker.svelte"
import { tick } from "svelte"

export let viewId: string
export let widget: IWidgetDTO
export let aggregate: IAggregate
export let onSuccess: () => void = () => {}

const table = getTable()
const value = writable<MaybeConditionGroup<IAggregateCondition> | undefined>(
toMaybeConditionGroup(aggregate.condition),
)
$: validValue = $value ? parseValidAggregateCondition($table.schema, $value) : undefined
$: visibleFields = $table.getOrderedVisibleFields()

const client = useQueryClient()

const updateViewWidgetMutation = createMutation({
mutationFn: trpc.table.view.widget.update.mutate,
async onSuccess(data, variables, context) {
await invalidate(`table:${$table.id.value}`)
await tick()
await client.invalidateQueries({ queryKey: ["aggregate", $table.id.value] })
onSuccess()
},
})

const updateViewWidget = (widget: IWidgetDTO) => {
if (widget.item.type !== "aggregate") {
return
}
$updateViewWidgetMutation.mutate({
tableId: $table.id.value,
viewId,
widget: {
...widget,
item: {
type: "aggregate",
aggregate: {
...widget.item.aggregate,
condition: validValue,
},
},
},
})
}
</script>

{#if widget.item.type === "aggregate"}
<div class="flex h-full flex-col py-2">
<div class="flex-1 space-y-3">
<div class="flex gap-2">
<div class="h-ful w-1 rounded-sm bg-gray-200"></div>
<div class="text-sm font-medium">Settings</div>
</div>
<Tabs.Root
class="w-full"
value={widget.item.aggregate.type === "count" ? "count" : "aggregate"}
onValueChange={(value) => {
if (widget.item.type === "aggregate") {
if (value === "aggregate") {
widget.item.aggregate.type = "sum"
// @ts-expect-error for type infer
if (widget.item.aggregate.type !== "count") {
widget.item.aggregate.config = { field: undefined }
}
}
if (value === "count") {
widget.item.aggregate = {
type: "count",
}
}
}
}}
>
<Tabs.List class="w-full">
<Tabs.Trigger class="flex-1" value="count">Count</Tabs.Trigger>
<Tabs.Trigger class="flex-1" value="aggregate">Aggregate</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="count"></Tabs.Content>
<Tabs.Content value="aggregate" class="space-y-2">
{#if widget.item.type === "aggregate" && widget.item.aggregate.type !== "count"}
<AggregateTypePicker bind:value={widget.item.aggregate.type} />
<FieldPicker
bind:value={widget.item.aggregate.config.field}
class="w-full flex-1"
placeholder="Select a field to aggregate..."
filter={(field) => filterAggregateField(field.type, widget.item.aggregate?.type)}
/>
{/if}
</Tabs.Content>
</Tabs.Root>

<div class="flex gap-2">
<div class="h-ful w-1 rounded-sm bg-gray-200"></div>
<div class="text-sm font-medium">Filters</div>
</div>

<FiltersEditor
bind:value={$value}
table={$table}
filter={(field) => visibleFields.some((f) => f.id.value === field.id) && getIsFilterableFieldType(field.type)}
class="rounded-md border pt-3"
></FiltersEditor>
</div>

<div class="flex justify-end">
<Button disabled={$updateViewWidgetMutation.isPending} on:click={() => updateViewWidget(widget)} class="w-full">
<SaveIcon class="mr-2 size-4" />
Save
</Button>
</div>
</div>
{/if}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { writable, type Readable, type Writable } from "svelte/store"
import { getRecordsStore } from "$lib/store/records.store"
import { getTable } from "$lib/store/table.store"
import { cn } from "$lib/utils"

const table = getTable()

Expand Down Expand Up @@ -39,9 +40,9 @@
}
</script>

<div class={$$restProps.class}>
<div class={cn("overflow-hidden", $$restProps.class)}>
<div class="flex w-full items-center justify-between gap-1">
<div class="flex flex-1 items-center gap-1">
<div class="flex flex-1 items-center gap-1 truncate">
<ForeignRecordsPickerDropdown
shouldUpdate
onOpenChange={(open) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
value={values[field.id.value]}
type={field.type}
displayValue={displayValues[field.id.value]}
class="text-xs"
class="truncate text-xs"
placeholder="-"
/>
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@
<ShareViewButton />
{/if}
<RecordsSearch />
<!-- <ViewWidgetButton /> -->
<ViewWidgetButton />
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
import CreateWidgetForm from "../widget/create-widget-form.svelte"
import Widget from "../widget/widget.svelte"

const table = getTable()
let table = getTable()
export let viewId: Readable<string | undefined>

const view = derived([viewId], ([$viewId]) => $table?.views.getViewById($viewId))
const widgets = derived([view], ([$view]) => $view?.widgets.unwrapOr([]) ?? [])
let view = derived([table, viewId], ([$table, $viewId]) => $table?.views.getViewById($viewId))
let widgets = derived([view], ([$view]) => ($view?.widgets.unwrapOr([]) ?? []).map((w) => w.toJSON()))

const createViewWidgetMutation = createMutation({
mutationFn: trpc.table.view.widget.create.mutate,
Expand All @@ -24,15 +24,15 @@
let open = false
</script>

<Sheet.Root open={$isModalOpen(VIEW_WIDGET_MODAL)} onOpenChange={() => toggleModal(VIEW_WIDGET_MODAL)}>
<Sheet.Root portal="body" open={$isModalOpen(VIEW_WIDGET_MODAL)} onOpenChange={() => toggleModal(VIEW_WIDGET_MODAL)}>
<Sheet.Content side="right" class="flex flex-col">
<Sheet.Header>
<Sheet.Title>Widgets</Sheet.Title>
<Sheet.Description>View Widgets</Sheet.Description>
</Sheet.Header>
<div class="flex-1 space-y-3 overflow-y-auto">
{#each $widgets as widget}
<Widget {widget} />
<Widget {widget} viewId={$view.id.value} />
{/each}
<Popover.Root bind:open>
<Popover.Trigger asChild let:builder>
Expand Down
Loading
Loading