Skip to content

Commit

Permalink
useMigrations
Browse files Browse the repository at this point in the history
  • Loading branch information
mmkal committed Apr 26, 2024
1 parent b8f4a5a commit ce06cd0
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 50 deletions.
7 changes: 7 additions & 0 deletions packages/admin/eslint.config.cjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
module.exports = [
...require('eslint-plugin-mmkal').recommendedFlatConfigs,
{plugins: {tailwindcss: require('eslint-plugin-tailwindcss')}},
{languageOptions: {globals: {React: false, JSX: false}}},
{
rules: {
'no-console': 'off',
'unicorn/prefer-ternary': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'tailwindcss/no-custom-classname': [
'warn',
{
whitelist: [/DISABLED.*/.source],
},
],
},
},
]
1 change: 1 addition & 0 deletions packages/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"@types/react-dom": "^18.2.15",
"autoprefixer": "^10.4.19",
"eslint": "^8.57.0",
"eslint-plugin-tailwindcss": "3.15.1",
"postcss": "^8.4.38",
"shadcn-ui": "0.8.0",
"strip-indent": "^4.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/admin/src/client/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {QueryClientProvider} from '@tanstack/react-query'
import Component from './page'
import {withSettings} from './settings'
import {AlertProvider} from './utils/alert'
import {AlertProvider} from './utils/alerter'
import {trpc, useTrpcClient} from './utils/trpc'
import {Toaster} from '@/components/ui/sonner'

Expand Down
2 changes: 1 addition & 1 deletion packages/admin/src/client/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@tailwind utilities;

body {
color: white
color: white;
}

:root {
Expand Down
File renamed without changes.
15 changes: 15 additions & 0 deletions packages/admin/src/client/utils/destructive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {useMutation} from '@tanstack/react-query'
import {AlertOptions, useAlerter} from './alerter'

export function useDestructive<T extends {mutateAsync: Function}>(
input: T,
...alerterArgs: [title?: string, options?: AlertOptions]
) {
const alerter = useAlerter()
return useMutation(async (...args: never[]) => {
const [title = 'Are you sure?', options = {}] = alerterArgs
const confirmed = await alerter.confirm(title, options)
if (!confirmed) return
return input.mutateAsync(...args) as unknown
}) as T
}
84 changes: 45 additions & 39 deletions packages/admin/src/client/views/Migrations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import clsx from 'clsx'
import React from 'react'
import {useLocalStorage} from 'react-use'
import {MeasuredCodeMirror} from '../sql-codemirror'
import {useAlerter} from '../utils/alert'
import {createCascadingState} from '../utils/cascading-state'
import {useDestructive} from '../utils/destructive'
import {trpc} from '../utils/trpc'
import {parseFileTree, basename, File, Folder, commonPrefix} from './file-tree'
import {Button} from '@/components/ui/button'
Expand Down Expand Up @@ -54,22 +54,35 @@ const workingFSContext = createCascadingState({} as Record<string, string>, v =>
// eslint-disable-next-line prefer-arrow-callback
export const Migrations = file.wrap(workingFSContext.wrap(_Migrations))

function _Migrations() {
const {confirm} = useAlerter()
const [fileState] = file.useState()
const [workingFS, setWorkingFS] = workingFSContext.useState()
const list = trpc.migrations.list.useQuery()
const useMigrations = () => {
const util = trpc.useUtils()
const mutationConfig = {
onSuccess: () => util.migrations.invalidate(),
}
useDestructive(trpc.migrations.down.useMutation(mutationConfig), 'Are you sure?', {
description: `This may delete data, which will not be restored even if you reapply the migration.`,
})

const list = trpc.migrations.list.useQuery()

const create = trpc.migrations.create.useMutation(mutationConfig)
const up = trpc.migrations.up.useMutation(mutationConfig)
const down = trpc.migrations.down.useMutation(mutationConfig)
const down = useDestructive(trpc.migrations.down.useMutation(mutationConfig), 'Are you sure?', {
description: `This may delete data, which will not be restored even if you reapply the migration.`,
})
const update = trpc.migrations.update.useMutation(mutationConfig)
const downify = trpc.migrations.downify.useMutation(mutationConfig)
const definitions = trpc.migrations.definitions.useMutation(mutationConfig)

return {list, create, up, down, update, downify, definitions}
}

function _Migrations() {
const [fileState] = file.useState()
const [workingFS, setWorkingFS] = workingFSContext.useState()

const {create, list, up, down, update, downify, definitions} = useMigrations()

const filesData = React.useMemo(() => {
const fsEntries = (list.data?.migrations || [])
.flatMap(m => {
Expand Down Expand Up @@ -110,40 +123,47 @@ function _Migrations() {
<Button title="Create migration" onClick={() => create.mutate({name: prompt('name?')!})}>
<icons.SquarePlus />
</Button>
<Button
title="Revert migrations"
onClick={async () => {
const yes = await confirm('Are you sure?', {
description: `This may delete data, which will not be restored even if you reapply the migration.`,
})
if (yes) down.mutate()
}}
>
<icons.CircleArrowDown />
</Button>

<ContextMenu>
<ContextMenuTrigger>
<Button title="Revert migrations" onClick={async () => down.mutate()}>
<icons.CircleArrowDown />
</Button>
</ContextMenuTrigger>
<ContextMenuContent className="mt-5 bg-gray-800 text-gray-100">
<ContextMenuItem onClick={() => down.mutate({to: 0})}>
<icons.CircleArrowDown />
<icons.Bomb />
Revert all migrations
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
<ContextMenu>
<ContextMenuTrigger>
<Button title="Apply migrations" onClick={() => up.mutate()}>
<icons.CircleArrowUp />
</Button>
</ContextMenuTrigger>
<ContextMenuContent className="mt-3 bg-sky-950">
<ContextMenuContent className="mt-3 bg-muted-foreground">
<ContextMenuItem>
<Button variant="outline" title="Apply 1 migration" onClick={() => up.mutate({step: 1})}>
<Button onClick={() => up.mutate({step: 1})}>
<icons.CircleArrowUp />
<icons.Tally1 />
Apply 1 migration
</Button>
</ContextMenuItem>
<ContextMenuItem>
<Button variant="outline" title="Apply 1 migration" onClick={() => up.mutate({step: 2})}>
<Button onClick={() => up.mutate({step: 2})}>
<icons.CircleArrowUp />
<icons.Tally2 />
Apply 2 migrations
</Button>
</ContextMenuItem>
<ContextMenuItem>
<Button variant="outline" title="Apply 1 migration" onClick={() => up.mutate({step: 3})}>
<Button onClick={() => up.mutate({step: 3})}>
<icons.CircleArrowUp />
<icons.Tally3 />
Apply 3 migrations
</Button>
</ContextMenuItem>
</ContextMenuContent>
Expand Down Expand Up @@ -268,16 +288,10 @@ const _sampleFilesJson: Record<string, string> = {
'create table orders (id serial primary key, user_id integer not null, product_id integer not null)',
}

const _sampleFiles = Object.keys(_sampleFilesJson)

export const FileTree = (tree: File | Folder) => {
const [_, setFileState] = file.useState()
const list = trpc.migrations.list.useQuery()
const util = trpc.useUtils()
const mutationConfig = {onSuccess: () => util.migrations.invalidate()}
const up = trpc.migrations.up.useMutation(mutationConfig)
const down = trpc.migrations.down.useMutation(mutationConfig)
const {confirm} = useAlerter()

const {up, down, list} = useMigrations()

if (tree.type === 'file') {
const fileInfo = list.data?.migrations.find(f => f.path === tree.path)
Expand Down Expand Up @@ -307,15 +321,7 @@ export const FileTree = (tree: File | Folder) => {
{fileInfo?.status === 'executed' && (
<ContextMenuContent className="mt-3 bg-sky-950">
<ContextMenuItem className="p-0">
<Button
className="gap-2"
onClick={async () => {
const yes = await confirm('Are you sure?', {
description: `This may delete data, which will not be restored even if you reapply the migration.`,
})
if (yes) down.mutate({to: fileInfo.name})
}}
>
<Button className="gap-2" onClick={() => down.mutate({to: fileInfo.name})}>
<icons.CircleArrowDown />
Revert migrations down to this one
</Button>
Expand Down
11 changes: 5 additions & 6 deletions packages/admin/src/client/views/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,16 @@ export const Table = ({identifier}: {identifier: string}) => {
</Pagination>
</div>
<div className="flex items-center gap-2">
<Button title="Filter" className="" size="sm" variant="outline">
<Button title="Filter" className="" size="sm">
<FilterIcon className="w-4 h-4 " />
</Button>
<Button title="Columns" className="" size="sm" variant="outline">
<Button title="Columns" className="" size="sm">
<ColumnsIcon className="w-4 h-4 " />
</Button>
<Button title="Add Row" className="" size="sm" variant="outline">
<Button title="Add Row" className="" size="sm">
<PlusIcon className="w-4 h-4 " />
</Button>
{/* <Button title="Pagination" className="" size="sm" variant="outline">
{/* <Button title="Pagination" className="" size="sm">
<NavigationIcon className="w-4 h-4 " />
</Button> */}
<Button
Expand All @@ -90,11 +90,10 @@ export const Table = ({identifier}: {identifier: string}) => {
title="Refresh"
className=""
size="sm"
variant="outline"
>
<RefreshCwIcon className="w-4 h-4 " />
</Button>
<Button title="Download" className="" size="sm" variant="outline">
<Button title="Download" className="" size="sm">
<DownloadIcon className="w-4 h-4 " />
</Button>
</div>
Expand Down
8 changes: 5 additions & 3 deletions packages/admin/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Slot} from '@radix-ui/react-slot'
import {cva, type VariantProps} from 'class-variance-authority'
import clsx from 'clsx'
import * as React from 'react'

import {cn} from '@/lib/utils'
Expand All @@ -9,10 +10,11 @@ const buttonVariants = cva(
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90 Xhover:bg-red-500',
default: 'bg-primary text-primary-foreground shadow hover:bg-primary/50',
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
outline:
'border border-input bg-background text-gray-900 shadow-sm hover:bg-accent hover:text-accent-foreground',
outline: clsx(
'border border-input bg-background text-foreground shadow-sm hover:bg-accent hover:text-accent-foreground',
),
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
Expand Down
14 changes: 14 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ce06cd0

Please sign in to comment.