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-68 #2017

Merged
merged 8 commits into from
Sep 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,6 +1,17 @@
# Changelog


## v1.0.0-68


### 🏡 Chore

- Add template url ([088313c](https://github.com/undb-io/undb/commit/088313c))

### ❤️ Contributors

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

## v1.0.0-67

## v1.0.0-66
Expand Down
6 changes: 6 additions & 0 deletions apps/frontend/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ type FormOption {
backgroundColor: String
}

type GalleryOption {
field: String
}

type Invitation {
email: String!
id: ID!
Expand Down Expand Up @@ -199,6 +203,7 @@ type View {
color: JSON
fields: JSON
filter: JSON
gallery: GalleryOption
id: ID!
isDefault: Boolean
kanban: KanbanOption
Expand All @@ -219,6 +224,7 @@ type ViewOption {
}

enum ViewType {
gallery
grid
kanban
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
})
toast.success("Record has been created!")
onSuccess?.(data)
recordsStore.invalidateRecord($table, data)
recordsStore?.invalidateRecord($table, data)
},
onError: (error: Error) => {
toast.error(error.message)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<script lang="ts">
import * as Carousel from "$lib/components/ui/carousel/index.js"
import * as Tooltip from "$lib/components/ui/tooltip"
import { ImagesIcon } from "lucide-svelte"

import { FieldIdVo, type RecordDO, type AttachmentField, AttachmentFieldValue, type Field } from "@undb/table"
import { queryParam } from "sveltekit-search-params"
import { getTable } from "$lib/store/table.store"
import FieldValue from "../field-value/field-value.svelte"

const table = getTable()
export let record: RecordDO
export let fields: Field[]
const r = queryParam("r")

let values = record.flatten()
let displayValues = record.displayValues?.toJSON() ?? {}

export let fieldId: string

let field = $table.schema.getFieldById(new FieldIdVo(fieldId)).into(undefined) as AttachmentField | undefined
$: fieldValues = record.getValue(new FieldIdVo(fieldId)).into(undefined) as AttachmentFieldValue | undefined
$: images = fieldValues?.getImages() ?? []
</script>

<div class="group col-span-1 flex flex-col rounded-md border shadow-sm transition-all hover:shadow-lg">
{#if images.length > 0}
<Carousel.Root class="h-[150px] w-full overflow-hidden border-b bg-gray-100">
<Carousel.Content>
{#each images as image}
<Carousel.Item>
<img src={image.signedUrl} alt="" class="h-full w-full object-cover" />
</Carousel.Item>
{/each}
</Carousel.Content>
<Carousel.Previous class="absolute left-2 top-1/2 hidden group-hover:flex" />
<Carousel.Next class="absolute right-2 top-1/2 hidden group-hover:flex" />
</Carousel.Root>
{:else}
<div class="flex h-[150px] w-full shrink-0 items-center justify-center border-b bg-gray-100">
<ImagesIcon class="text-muted-foreground/50 h-10 w-10" />
</div>
{/if}
<button on:click={() => ($r = record.id.value)} class="flex flex-1 flex-col space-y-2 px-2 py-3">
{#each fields.filter((f) => f.id.value !== fieldId) as field}
<div class="flex w-full">
<FieldValue
{field}
tableId={$table.id.value}
recordId={record.id.value}
value={values[field.id.value]}
type={field.type}
displayValue={displayValues[field.id.value]}
/>
</div>
{/each}
</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
import GalleryViewCard from "./gallery-view-card.svelte"
import { getRecordsStore } from "$lib/store/records.store"
import { getTable } from "$lib/store/table.store"
import type { Readable } from "svelte/store"

const table = getTable()
export let viewId: Readable<string>
export let fieldId: string
const recordsStore = getRecordsStore()

$: fields = $table.getOrderedVisibleFields($viewId) ?? []

let records = recordsStore.records
</script>

<div class="grid w-full gap-4 overflow-y-auto md:grid-cols-5">
{#each $records as record (record.id.value)}
<GalleryViewCard {record} {fieldId} {fields} />
{/each}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<script lang="ts">
import { Button } from "$lib/components/ui/button/index.js"
import { getTable } from "$lib/store/table.store"
import { updateGalleryViewDTO, type GalleryView } from "@undb/table"
import FieldPicker from "../field-picker/field-picker.svelte"
import { defaults, superForm } from "sveltekit-superforms"
import { zodClient } from "sveltekit-superforms/adapters"
import CreateFieldButton from "../create-field/create-field-button.svelte"
import { trpc } from "$lib/trpc/client"
import { createMutation } from "@tanstack/svelte-query"
import { toast } from "svelte-sonner"
import { invalidate } from "$app/navigation"

const table = getTable()

$: fields = $table.schema.getGalleryFields()

export let view: GalleryView

const form = superForm(
defaults(
{
tableId: $table.id.value,
viewId: view.id.value,
type: "gallery",
name: view.name.value,
gallery: view.gallery.unwrapOrElse(() => ({ field: undefined })),
},
zodClient(updateGalleryViewDTO),
),
{
SPA: true,
dataType: "json",
validators: zodClient(updateGalleryViewDTO),
resetForm: false,
invalidateAll: false,
onUpdate(event) {
if (!event.form.valid) return

$updateViewMutation.mutate(event.form.data)
},
},
)

const { enhance, form: formData } = form

const updateViewMutation = createMutation({
mutationFn: trpc.table.view.update.mutate,
mutationKey: ["updateView"],
async onSuccess(data, variables, context) {
toast.success("View updated")
await invalidate(`table:${$table.id.value}`)
},
})
</script>

<div class="space-y-2">
<form id="select-kanban-field-form" class="space-y-2" use:enhance>
<div class="grid w-full items-center gap-4">
<div class="flex flex-col space-y-1.5">
<FieldPicker
placeholder="Select a select type field to group kanban lanes"
value={$formData.gallery?.field}
onValueChange={(field) => {
if ($formData.gallery) {
$formData.gallery.field = field
} else {
$formData.gallery = { field }
}
}}
filter={(f) => fields.map((f) => f.id.value).includes(f.id)}
/>
</div>
</div>
</form>

<CreateFieldButton class="w-full" variant="secondary" />

<div class="flex w-full justify-end">
<Button type="submit" form="select-kanban-field-form">Confirm</Button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import * as Card from "$lib/components/ui/card/index.js"
import type { GalleryView } from "@undb/table"
import GalleryViewFieldForm from "./gallery-view-field-form.svelte"

export let view: GalleryView
</script>

<div class="flex h-full w-full items-center justify-center">
<Card.Root class="w-[450px]">
<Card.Header>
<Card.Title>Select gallery field</Card.Title>
<Card.Description>Select a attachment type field to display images.</Card.Description>
</Card.Header>
<Card.Content class="space-y-4">
<GalleryViewFieldForm {view} />
</Card.Content>
</Card.Root>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script lang="ts">
import { getTable } from "$lib/store/table.store"
import { derived, writable, type Readable } from "svelte/store"
import { type GalleryView, type IRecordsDTO, Records } from "@undb/table"
import { queryParam } from "sveltekit-search-params"
import TableTools from "../table-tools/table-tools.svelte"
import { trpc } from "$lib/trpc/client"
import { createQuery } from "@tanstack/svelte-query"
import GalleryViewCards from "./gallery-view-cards.svelte"
import { createRecordsStore, setRecordsStore } from "$lib/store/records.store"
import GalleryViewField from "./gallery-view-field.svelte"
import ViewPagination from "../view/view-pagination.svelte"

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

let view = $table.views.getViewById($viewId) as GalleryView

$: field = view.gallery.unwrapOrElse(() => ({ field: undefined })).field

const perPage = writable(50)
const currentPage = writable(1)
const q = queryParam("q")

const getRecords = createQuery(
derived([table, viewId, perPage, currentPage, q], ([$table, $viewId, $perPage, $currentPage, $q]) => {
const view = $table.views.getViewById($viewId)
return {
queryKey: ["records", $table?.id.value, $viewId, $q, $currentPage, $perPage],
enabled: view?.type === "gallery",
queryFn: () =>
trpc.record.list.query({
tableId: $table?.id.value,
viewId: $viewId,
q: $q ?? undefined,
pagination: { limit: $perPage, page: $currentPage },
}),
}
}),
)

const recordsStore = createRecordsStore()
setRecordsStore(recordsStore)

// $: records = (($getRecords.data as any)?.records as IRecordsDTO) ?? []
let records = derived([getRecords], ([$getRecords]) => {
return (($getRecords.data as any)?.records as IRecordsDTO) ?? []
})
$: recordsStore.setRecords(Records.fromJSON($table, $records), $getRecords.dataUpdatedAt)

$: total = ($getRecords.data as any)?.total
</script>

<TableTools />
<div class="flex-1 overflow-x-auto overflow-y-hidden p-4">
{#if !field}
<GalleryViewField {view} />
{:else}
<GalleryViewCards fieldId={field} {viewId} />
{/if}
</div>
<ViewPagination perPage={$perPage} bind:currentPage={$currentPage} count={total} />

{#await import("$lib/components/blocks/create-record/create-record-sheet.svelte") then { default: CreateRecordSheet }}
<CreateRecordSheet />
{/await}

{#await import("$lib/components/blocks/record-detail/table-record-detail-sheet.svelte") then { default: TableRecordDetailSheet }}
<TableRecordDetailSheet />
{/await}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import GridViewActionHeader from "./grid-view-action-header.svelte"
import GridViewCell from "./grid-view-cell.svelte"
import GridViewEmpty from "./grid-view-empty.svelte"
import GridViewPagination from "./grid-view-pagination.svelte"
import Checkbox from "$lib/components/ui/checkbox/checkbox.svelte"
import TableTools from "../table-tools/table-tools.svelte"
import GridViewHeader from "./grid-view-header.svelte"
Expand All @@ -31,6 +30,7 @@
import { gridViewStore, isRowSelected, isSelectedCell } from "./grid-view.store"
import SelectedRecordsButton from "./selected-records-button.svelte"
import { aggregatesStore } from "$lib/store/aggregates.store"
import ViewPagination from "../view/view-pagination.svelte"

export let readonly = false
export let viewId: Readable<string>
Expand Down Expand Up @@ -62,7 +62,6 @@
let store = getRecordsStore()
let hasRecord = store.hasRecord
let count = store.count
let records = store.records

const table = createTable(store.data, {
select: addSelectedRows(),
Expand Down Expand Up @@ -328,7 +327,7 @@

<div class="flex items-center justify-center px-4 py-2">
<div class="flex flex-1 flex-row items-center">
<GridViewPagination perPage={$perPage} bind:currentPage={$currentPage} count={total} />
<ViewPagination perPage={$perPage} bind:currentPage={$currentPage} count={total} />
<div class="flex items-center gap-2 text-sm">
<Select.Root
selected={{ value: $perPage, label: String($perPage) }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,12 @@
isLoading={$getRecords.isLoading}
total={$getRecords.data?.total ?? 0}
/>


{#await import("$lib/components/blocks/create-record/create-record-sheet.svelte") then { default: CreateRecordSheet }}
<CreateRecordSheet />
{/await}

{#await import("$lib/components/blocks/record-detail/table-record-detail-sheet.svelte") then { default: TableRecordDetailSheet }}
<TableRecordDetailSheet />
{/await}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<script lang="ts">
import { type Field, type RecordDO } from "@undb/table"
import { ViewColor, type Field, type RecordDO } from "@undb/table"
import FieldValue from "../field-value/field-value.svelte"
import { getTable } from "$lib/store/table.store"
import * as Tooltip from "$lib/components/ui/tooltip"
import { queryParam } from "sveltekit-search-params"
import { cn } from "$lib/utils"
import { getBgColor } from "../grid-view/grid-view.util"

const table = getTable()
export let color: ViewColor | undefined

export let fields: Field[]
export let record: RecordDO
export let readonly = false
Expand All @@ -14,14 +18,21 @@

let values = record.flatten()
let displayValues = record.displayValues?.toJSON() ?? {}

$: colorSpec = color?.getSpec($table.schema).into(undefined)
$: isMatch = colorSpec ? record.match(colorSpec) : false
$: condition = isMatch ? color?.getMatchedFieldConditions($table, record)[0] : undefined
</script>

<button
on:click={() => ($r = record.id.value)}
disabled={readonly}
data-record-id={record.id.value}
class="mb-2 flex w-full flex-col space-y-2 rounded bg-white p-2 shadow"
class={cn("relative mb-2 flex w-full flex-col space-y-2 rounded bg-white p-2 shadow", isMatch && "pl-3")}
>
{#if isMatch}
<div class={cn("absolute left-0 top-0 h-full w-1", condition && getBgColor(condition.option.color))}></div>
{/if}
{#each fields as field}
<div class="flex items-center gap-2">
<Tooltip.Root>
Expand Down
Loading
Loading