Skip to content

Commit b26ca76

Browse files
committed
feat: duplicate base
1 parent d56b298 commit b26ca76

33 files changed

+475
-18
lines changed

apps/frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@undb/queries": "workspace:*",
3737
"@undb/share": "workspace:*",
3838
"@undb/table": "workspace:*",
39+
"@undb/utils": "workspace:*",
3940
"@undb/trpc": "workspace:*",
4041
"autoprefixer": "^10.4.20",
4142
"date-fns": "^3.6.0",

apps/frontend/src/lib/components/blocks/base/base-header.svelte

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<script lang="ts">
22
import type { GetBaseQuery$result } from "$houdini"
33
import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js"
4-
import { UPDATE_BASE_MODAL, toggleModal } from "$lib/store/modal.store"
5-
import { HardDriveIcon, PencilIcon, ChevronDownIcon } from "lucide-svelte"
4+
import { DUPLICATE_BASE_MODAL, UPDATE_BASE_MODAL, toggleModal } from "$lib/store/modal.store"
5+
import { HardDriveIcon, PencilIcon, ChevronDownIcon, CopyIcon } from "lucide-svelte"
6+
import DuplicateBase from "./duplicate-base.svelte"
67
78
export let base: GetBaseQuery$result["base"]
89
</script>
@@ -18,12 +19,18 @@
1819
<ChevronDownIcon class="h-4 w-4" />
1920
</div>
2021
</DropdownMenu.Trigger>
21-
<DropdownMenu.Content>
22+
<DropdownMenu.Content class="w-[200px]">
2223
<DropdownMenu.Item class="text-xs" on:click={() => toggleModal(UPDATE_BASE_MODAL)}>
2324
<PencilIcon class="mr-2 h-3 w-3" />
2425
Update Base Name
2526
</DropdownMenu.Item>
27+
<DropdownMenu.Item class="text-xs" on:click={() => toggleModal(DUPLICATE_BASE_MODAL)}>
28+
<CopyIcon class="mr-2 h-3 w-3" />
29+
Duplicate Base
30+
</DropdownMenu.Item>
2631
</DropdownMenu.Content>
2732
</DropdownMenu.Root>
2833
{/if}
2934
</header>
35+
36+
<DuplicateBase {base} />
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<script lang="ts">
2+
import { goto, invalidateAll } from "$app/navigation"
3+
import Button from "$lib/components/ui/button/button.svelte"
4+
import * as Dialog from "$lib/components/ui/dialog"
5+
import { closeModal, DUPLICATE_BASE_MODAL, isModalOpen } from "$lib/store/modal.store"
6+
import { trpc } from "$lib/trpc/client"
7+
import { createMutation } from "@tanstack/svelte-query"
8+
import type { Base, IBaseDTO } from "@undb/base"
9+
import { LoaderCircleIcon } from "lucide-svelte"
10+
import { toast } from "svelte-sonner"
11+
12+
export let base: Omit<IBaseDTO, "spaceId">
13+
14+
const duplicateBaseMutation = createMutation({
15+
mutationFn: trpc.base.duplicate.mutate,
16+
onSuccess: async (data) => {
17+
await invalidateAll()
18+
closeModal(DUPLICATE_BASE_MODAL)
19+
await goto(`/bases/${data}`)
20+
},
21+
onError: (error) => {
22+
toast.error(error.message)
23+
},
24+
})
25+
</script>
26+
27+
<Dialog.Root
28+
open={$isModalOpen(DUPLICATE_BASE_MODAL)}
29+
onOpenChange={(open) => {
30+
if (!open) {
31+
closeModal(DUPLICATE_BASE_MODAL)
32+
}
33+
}}
34+
>
35+
<Dialog.Content>
36+
<Dialog.Header>
37+
<Dialog.Title>Duplicate Base {base.name}</Dialog.Title>
38+
<Dialog.Description>Create a new base include all tables in base.</Dialog.Description>
39+
</Dialog.Header>
40+
41+
<div class="item-center flex justify-end gap-2">
42+
<Button
43+
on:click={() => {
44+
closeModal(DUPLICATE_BASE_MODAL)
45+
}}
46+
variant="outline"
47+
>
48+
Cancel
49+
</Button>
50+
<Button
51+
disabled={$duplicateBaseMutation.isPending}
52+
on:click={() => {
53+
$duplicateBaseMutation.mutate({ id: base.id })
54+
}}
55+
>
56+
{#if $duplicateBaseMutation.isPending}
57+
<LoaderCircleIcon class="mr-2 h-5 w-5 animate-spin" />
58+
{/if}
59+
Duplicate
60+
</Button>
61+
</div>
62+
</Dialog.Content>
63+
</Dialog.Root>

apps/frontend/src/lib/components/blocks/create-table/create-schema.svelte

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
FieldIdVo,
55
fieldTypes,
66
getIsDisplayFieldType,
7-
getNextName,
8-
OptionIdVo,
97
systemFieldTypes,
108
type ICreateSchemaDTO,
119
type NoneSystemFieldType,
1210
} from "@undb/table"
11+
import { getNextName } from "@undb/utils"
1312
import * as Popover from "$lib/components/ui/popover"
1413
import * as Card from "$lib/components/ui/card"
1514
import * as Form from "$lib/components/ui/form"

apps/frontend/src/lib/components/blocks/view/create-view-button.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
import * as Popover from "$lib/components/ui/popover"
66
import { trpc } from "$lib/trpc/client"
77
import { createMutation } from "@tanstack/svelte-query"
8-
import { createViewDTO, getNextName } from "@undb/table"
8+
import { createViewDTO } from "@undb/table"
9+
import { getNextName } from "@undb/utils"
910
import { PlusCircleIcon } from "lucide-svelte"
1011
import { toast } from "svelte-sonner"
1112
import { defaults, superForm } from "sveltekit-superforms"

apps/frontend/src/lib/components/blocks/view/duplicate-view.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import * as Form from "$lib/components/ui/form"
99
import { Input } from "$lib/components/ui/input"
1010
import { toggleModal, DUPLICATE_VIEW } from "$lib/store/modal.store"
11-
import { getNextName } from "@undb/table"
11+
import { getNextName } from "@undb/utils"
1212
1313
const table = getTable()
1414

apps/frontend/src/lib/store/modal.store.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const UPDATE_VIEW = "updateView" as const
1717
export const DUPLICATE_VIEW = "duplicateView" as const
1818
export const DELETE_VIEW = "deleteView" as const
1919
export const CREATE_BASE_MODAL = "createBase" as const
20+
export const DUPLICATE_BASE_MODAL = "duplicateBase" as const
2021
export const UPDATE_BASE_MODAL = "updateBase" as const
2122
export const DELETE_TABLE_MODAL = "deleteTable" as const
2223

@@ -36,6 +37,7 @@ type ModalType =
3637
| typeof CREATE_BASE_MODAL
3738
| typeof UPDATE_BASE_MODAL
3839
| typeof DELETE_TABLE_MODAL
40+
| typeof DUPLICATE_BASE_MODAL
3941

4042
export const toggleModal = (type: ModalType) => {
4143
modal.update(($modal) => {

bun.lockb

464 Bytes
Binary file not shown.

packages/base/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"@undb/di": "workspace:*",
1414
"@undb/domain": "workspace:*",
1515
"@undb/space": "workspace:*",
16+
"@undb/utils": "workspace:*",
1617
"@undb/zod": "workspace:*"
1718
}
1819
}

packages/base/src/base.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { AggregateRoot, and } from "@undb/domain"
22
import type { ISpaceId } from "@undb/space"
3+
import { getNextName } from "@undb/utils"
34
import type { Option } from "oxide.ts"
5+
import { BaseFactory } from "./base.factory.js"
46
import type { IBaseDTO } from "./dto/base.dto.js"
57
import type { IUpdateBaseDTO } from "./dto/update-base.dto.js"
68
import { BaseUpdatedEvent } from "./events/base-updated.event.js"
79
import type { IBaseSpecification } from "./interface.js"
810
import { WithBaseName } from "./specifications/base-name.specification.js"
9-
import type { BaseId, BaseName } from "./value-objects/index.js"
11+
import { DuplicatedBaseSpecification } from "./specifications/base.specification.js"
12+
import { BaseId, type BaseName } from "./value-objects/index.js"
1013

1114
export class Base extends AggregateRoot<any> {
1215
id!: BaseId
@@ -36,6 +39,16 @@ export class Base extends AggregateRoot<any> {
3639
return spec
3740
}
3841

42+
public $duplicate(baseNames: string[]): DuplicatedBaseSpecification {
43+
const duplicatedBase = BaseFactory.fromJSON({
44+
...this.toJSON(),
45+
id: BaseId.create().value,
46+
name: getNextName(baseNames, this.name.value),
47+
})
48+
49+
return new DuplicatedBaseSpecification(this, duplicatedBase)
50+
}
51+
3952
public toJSON(): IBaseDTO {
4053
return {
4154
id: this.id.value,

0 commit comments

Comments
 (0)