Skip to content

Commit

Permalink
Merge pull request #1891 from undb-io/release/v1.0.0-17
Browse files Browse the repository at this point in the history
Release version v1.0.0-17
  • Loading branch information
nichenqin authored Aug 17, 2024
2 parents 4cbacaf + 5857dd9 commit d669219
Show file tree
Hide file tree
Showing 18 changed files with 364 additions and 3 deletions.
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-17


### 🩹 Fixes

- Fix route prerender ([7adc361](https://github.com/undb-io/undb/commit/7adc361))

### ❤️ Contributors

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

## v1.0.0-16


Expand Down
7 changes: 7 additions & 0 deletions apps/frontend/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ type Query {
tableByShare(shareId: ID!): Table
tableForeignTables(tableId: ID!): [Table!]!
tables: [Table]!
template(baseId: ID!, spaceId: ID!): Template
}

type RLS {
Expand Down Expand Up @@ -166,6 +167,12 @@ type Table {
views: [View!]!
}

type Template {
baseId: ID!
name: String!
spaceId: ID!
}

type User {
avatar: String
email: String!
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
query GetCreateFromTemplateData($spaceId: ID!, $baseId: ID!) {
space {
id
name
}

template(spaceId: $spaceId, baseId: $baseId) {
name
}

spaces {
id
name
isPersonal
member {
role
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<main class="flex h-screen w-screen items-center justify-center">
<slot />
</main>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { GetCreateFromTemplateDataStore } from "$houdini"
import type { LayoutLoad } from "./$types"

export const ssr = false
export const prerender = "auto"

export const load: LayoutLoad = async (event) => {
const { spaceId, baseId } = event.params

const store = new GetCreateFromTemplateDataStore()

await store.fetch({
event,
variables: { spaceId, baseId },
})

return {
store,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<script lang="ts">
import { goto } from "$app/navigation"
import * as Card from "$lib/components/ui/card/index.js"
import { Input } from "$lib/components/ui/input/index.js"
import Logo from "$lib/images/logo.svg"
import { createMutation } from "@tanstack/svelte-query"
import { defaults, superForm } from "sveltekit-superforms"
import { zodClient } from "sveltekit-superforms/adapters"
import * as Form from "$lib/components/ui/form"
import * as Alert from "$lib/components/ui/alert/index.js"
import { LoaderCircleIcon, SirenIcon, Store } from "lucide-svelte"
import { createFromTemplateCommand } from "@undb/commands"
import { Checkbox } from "$lib/components/ui/checkbox"
import { trpc } from "$lib/trpc/client"
import { page } from "$app/stores"
import type { PageData } from "./$types"
import * as Select from "$lib/components/ui/select/index.js"
export let data: PageData
let { spaceId, baseId } = $page.params
let store = data.store
let spaces = $store.data?.spaces ?? []
let space = $store.data?.space
let template = $store.data?.template
const createFromTemplateMutation = createMutation({
mutationFn: trpc.base.createFromTemplate.mutate,
async onSuccess(data, variables, context) {
await goto(`/bases/${data}`)
},
})
const form = superForm(
defaults(
{
spaceId,
baseId,
targetSpaceId: space?.id,
name: template?.name,
includeData: true,
},
zodClient(createFromTemplateCommand),
),
{
SPA: true,
dataType: "json",
validators: zodClient(createFromTemplateCommand),
resetForm: false,
invalidateAll: false,
async onUpdate(event) {
if (!event.form.valid) {
console.log(event.form.errors)
return
}
await $createFromTemplateMutation.mutateAsync(event.form.data)
},
},
)
const { enhance, form: formData } = form
$: selectedSpace = $formData.targetSpaceId
? {
label: spaces.find((space) => space?.id === $formData.targetSpaceId)?.name,
value: $formData.targetSpaceId,
}
: undefined
</script>

<section class="w-[450px] -translate-y-20 space-y-5">
<div class="flex justify-center">
<img src={Logo} alt="undb" class="h-12 w-12" />
</div>

<form method="POST" use:enhance>
<Card.Root class="mx-auto">
<Card.Header>
<Card.Title class="text-2xl">Create from template</Card.Title>
<Card.Description>Create a new base from a template.</Card.Description>
</Card.Header>
<Card.Content>
<div class="grid gap-2">
<div class="grid gap-2">
<Form.Field {form} name="name">
<Form.Control let:attrs>
<Form.Label for="name">Name</Form.Label>
<Input {...attrs} id="name" type="name" placeholder="Enter new base name" bind:value={$formData.name} />
</Form.Control>
<Form.Description />
<Form.FieldErrors />
</Form.Field>
</div>
<Form.Field {form} name="targetSpaceId">
<Form.Control let:attrs>
<Form.Label>Space</Form.Label>
<Select.Root
selected={selectedSpace}
onSelectedChange={(v) => {
v && ($formData.targetSpaceId = v.value)
}}
>
<Select.Trigger {...attrs}>
<Select.Value placeholder="Select a space" />
</Select.Trigger>
<Select.Content>
{#each spaces as space}
<Select.Item value={space?.id} label={space?.name} />
{/each}
</Select.Content>
</Select.Root>
<input hidden bind:value={$formData.targetSpaceId} name={attrs.name} />
</Form.Control>
<Form.Description>Select a space to create the new base in.</Form.Description>
<Form.FieldErrors />
</Form.Field>

<Form.Field
{form}
name="includeData"
class="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4"
>
<Form.Control let:attrs>
<Checkbox {...attrs} bind:checked={$formData.includeData} />
<div class="space-y-1 leading-none">
<Form.Label>Include data</Form.Label>
<Form.Description>Include data in the new base.</Form.Description>
</div>
<input name={attrs.name} value={$formData.includeData} hidden />
</Form.Control>
</Form.Field>

<Alert.Root>
<Alert.Description class="flex items-center text-xs">
<SirenIcon class="mr-2 h-4 w-4" />
System fields will be updated to the current user and timestamp.
</Alert.Description>
</Alert.Root>
<Form.Button type="submit" class="w-full" disabled={$createFromTemplateMutation.isPending}>
{#if $createFromTemplateMutation.isPending}
<LoaderCircleIcon class="mr-2 h-5 w-5 animate-spin" />
{/if}
Create
</Form.Button>
</div>
</Card.Content>
</Card.Root>
</form>
</section>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "undb",
"version": "1.0.0-16",
"version": "1.0.0-17",
"private": true,
"scripts": {
"build": "NODE_ENV=production bun --bun turbo build",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { BaseId, injectBaseRepository, WithBaseId, WithBaseSpaceId, type IBaseRepository } from "@undb/base"
import { CreateFromTemplateCommand } from "@undb/commands"
import { mustGetCurrentSpaceId } from "@undb/context/server"
import { commandHandler } from "@undb/cqrs"
import { singleton } from "@undb/di"
import { type ICommandHandler } from "@undb/domain"
import { createLogger } from "@undb/logger"
import { injectTableService, type ITableService } from "@undb/table"

@commandHandler(CreateFromTemplateCommand)
@singleton()
export class CreateFromTemplateCommandHandler implements ICommandHandler<CreateFromTemplateCommand, any> {
private readonly logger = createLogger(CreateFromTemplateCommandHandler.name)

constructor(
@injectBaseRepository()
private readonly baseRepository: IBaseRepository,
@injectTableService()
private readonly tableService: ITableService,
) {}

async execute(command: CreateFromTemplateCommand): Promise<any> {
const spec = new WithBaseId(new BaseId(command.baseId)).and(new WithBaseSpaceId(command.spaceId))
const base = (await this.baseRepository.findOne(spec)).expect("Base not found")

const targetSpaceId = command.targetSpaceId ?? mustGetCurrentSpaceId()
const duplicatedBase = await this.tableService.duplicateBase(base, targetSpaceId, {
id: command.baseId,
name: command.name,
includeData: command.includeData,
})

return duplicatedBase.id.value
}
}
2 changes: 2 additions & 0 deletions packages/command-handlers/src/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BulkDuplicateRecordsCommandHandler } from "./bulk-duplicate-records.com
import { BulkUpdateRecordsCommandHandler } from "./bulk-update-records.command-handler"
import { CreateApiTokenCommandHandler } from "./create-api-token.command-handler"
import { CreateBaseCommandHandler } from "./create-base.command-handler"
import { CreateFromTemplateCommandHandler } from "./create-from-template.command-handler"
import { CreateRecordCommandHandler } from "./create-record.command-handler"
import { CreateRecordsCommandHandler } from "./create-records.command-handler"
import { CreateSpaceCommandHandler } from "./create-space.command-handler"
Expand Down Expand Up @@ -72,6 +73,7 @@ export const commandHandlers = [
BulkUpdateRecordsCommandHandler,
CreateTableViewCommandHandler,
DuplicateViewCommandHandler,
CreateFromTemplateCommandHandler,
DeleteViewCommandHandler,
CreateBaseCommandHandler,
UpdateBaseCommandHandler,
Expand Down
31 changes: 31 additions & 0 deletions packages/commands/src/create-from-template.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { baseIdSchema } from "@undb/base"
import { Command, type CommandProps } from "@undb/domain"
import { spaceIdSchema } from "@undb/space"
import { z } from "@undb/zod"

export const createFromTemplateCommand = z.object({
spaceId: spaceIdSchema,
baseId: baseIdSchema,
targetSpaceId: spaceIdSchema.optional(),
name: z.string().optional(),
includeData: z.boolean().optional(),
})

export type ICreateFromTemplateCommand = z.infer<typeof createFromTemplateCommand>

export class CreateFromTemplateCommand extends Command implements ICreateFromTemplateCommand {
public readonly spaceId: string
public readonly baseId: string
public readonly targetSpaceId?: string
public readonly name?: string
public readonly includeData?: boolean

constructor(props: CommandProps<ICreateFromTemplateCommand>) {
super(props)
this.spaceId = props.spaceId
this.baseId = props.baseId
this.targetSpaceId = props.targetSpaceId
this.name = props.name
this.includeData = props.includeData
}
}
1 change: 1 addition & 0 deletions packages/commands/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from "./bulk-duplicate-records.command"
export * from "./bulk-update-records.command"
export * from "./create-api-token.command"
export * from "./create-base.command"
export * from "./create-from-template.command"
export * from "./create-record.command"
export * from "./create-records.command"
export * from "./create-space.command"
Expand Down
13 changes: 13 additions & 0 deletions packages/graphql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
GetTableQuery,
GetTablesByBaseIdQuery,
GetTablesQuery,
GetTemplateQuery,
} from "@undb/queries"
import { injectShareService, type IShareService } from "@undb/share"
import type { ISpaceDTO } from "@undb/space"
Expand Down Expand Up @@ -234,6 +235,12 @@ export class Graphql {
tables: [Table]!
}
type Template {
baseId: ID!
spaceId: ID!
name: String!
}
enum InvitationStatus {
pending
accepted
Expand Down Expand Up @@ -271,6 +278,8 @@ export class Graphql {
share(id: ID!): Share
tableByShare(shareId: ID!): Table
template(spaceId: ID!, baseId: ID!): Template
}
`,
Expand Down Expand Up @@ -370,6 +379,10 @@ export class Graphql {
invitations: async (_, args) => {
return await this.queryBus.execute(new GetInivitationsQuery({ status: args?.status }))
},
template: async (_, { spaceId, baseId }) => {
const template = await this.queryBus.execute(new GetTemplateQuery({ spaceId, baseId }))
return template
},
},
Base: {
// @ts-ignore
Expand Down
Loading

0 comments on commit d669219

Please sign in to comment.