Spaces:
Paused
Paused
Commit
·
92864d8
1
Parent(s):
0268247
let's try again
Browse files
src/app/studio/[ownerId]/main.tsx
CHANGED
@@ -1,12 +1,14 @@
|
|
1 |
"use server"
|
2 |
|
3 |
// import { experimental_useFormStatus as useFormStatus } from "react-dom"
|
4 |
-
|
5 |
-
import { VideoTasksQueue } from "@/components/business/tasks/video-tasks-queue"
|
6 |
import { Textarea } from "@/components/ui/textarea"
|
7 |
import { Button } from "@/components/ui/button"
|
8 |
import { formSubmit } from "@/server/actions"
|
|
|
9 |
import { getTasks } from "@/server"
|
|
|
|
|
10 |
|
11 |
export default async function Main({ ownerId }: { ownerId: string }) {
|
12 |
const tasks = await getTasks(ownerId)
|
@@ -62,6 +64,7 @@ export default async function Main({ ownerId }: { ownerId: string }) {
|
|
62 |
</Button>
|
63 |
</div>
|
64 |
<VideoTasksQueue tasks={tasks} />
|
|
|
65 |
</form>
|
66 |
)
|
67 |
}
|
|
|
1 |
"use server"
|
2 |
|
3 |
// import { experimental_useFormStatus as useFormStatus } from "react-dom"
|
4 |
+
|
|
|
5 |
import { Textarea } from "@/components/ui/textarea"
|
6 |
import { Button } from "@/components/ui/button"
|
7 |
import { formSubmit } from "@/server/actions"
|
8 |
+
|
9 |
import { getTasks } from "@/server"
|
10 |
+
import { VideoTasksQueue } from "@/components/business/tasks/video-tasks-queue"
|
11 |
+
import { RefreshStudio } from "@/components/business/refresh"
|
12 |
|
13 |
export default async function Main({ ownerId }: { ownerId: string }) {
|
14 |
const tasks = await getTasks(ownerId)
|
|
|
64 |
</Button>
|
65 |
</div>
|
66 |
<VideoTasksQueue tasks={tasks} />
|
67 |
+
<RefreshStudio />
|
68 |
</form>
|
69 |
)
|
70 |
}
|
src/app/studio/[ownerId]/page.tsx
CHANGED
@@ -3,8 +3,6 @@ import Head from "next/head"
|
|
3 |
import Main from "./main"
|
4 |
|
5 |
export default async function StudioPage({ params: { ownerId } }: { params: { ownerId: string }}) {
|
6 |
-
console.log('ownerId:', ownerId)
|
7 |
-
|
8 |
return (
|
9 |
<div>
|
10 |
<Head>
|
|
|
3 |
import Main from "./main"
|
4 |
|
5 |
export default async function StudioPage({ params: { ownerId } }: { params: { ownerId: string }}) {
|
|
|
|
|
6 |
return (
|
7 |
<div>
|
8 |
<Head>
|
src/components/business/refresh.tsx
ADDED
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use client"
|
2 |
+
|
3 |
+
import { useEffect, useTransition } from "react"
|
4 |
+
import { usePathname } from "next/navigation"
|
5 |
+
|
6 |
+
import { refreshStudio } from "@/server/actions"
|
7 |
+
|
8 |
+
export function RefreshStudio() {
|
9 |
+
const pathname = usePathname()
|
10 |
+
const [isPending, startTransition] = useTransition()
|
11 |
+
|
12 |
+
useEffect(() => {
|
13 |
+
const slug = `${pathname.split("/").pop()}`
|
14 |
+
setInterval(() => {
|
15 |
+
console.log("refresh things!", slug)
|
16 |
+
startTransition(() => refreshStudio(slug))
|
17 |
+
}, 2000)
|
18 |
+
}, [])
|
19 |
+
|
20 |
+
// TODO we could display a spinner here
|
21 |
+
return <></>
|
22 |
+
}
|
src/components/business/tasks/columns.tsx
CHANGED
@@ -57,25 +57,16 @@ export const columns: ColumnDef<VideoTask>[] = [
|
|
57 |
},
|
58 |
},
|
59 |
{
|
60 |
-
accessorKey: "
|
61 |
header: ({ column }) => (
|
62 |
-
<DataTableColumnHeader column={column} title="
|
63 |
),
|
64 |
cell: ({ row }) => {
|
65 |
-
const
|
66 |
-
(status) => status.value === row.getValue("status")
|
67 |
-
)
|
68 |
-
|
69 |
-
if (!status) {
|
70 |
-
return null
|
71 |
-
}
|
72 |
|
73 |
return (
|
74 |
<div className="flex w-[100px] items-center">
|
75 |
-
{
|
76 |
-
<status.icon className="mr-2 h-4 w-4 text-muted-foreground" />
|
77 |
-
)}
|
78 |
-
<span>{status.label}</span>
|
79 |
</div>
|
80 |
)
|
81 |
},
|
@@ -93,7 +84,7 @@ export const columns: ColumnDef<VideoTask>[] = [
|
|
93 |
className="hover:underline cursor-pointer"
|
94 |
target="_blank"
|
95 |
href={`/api/download/${row.getValue("fileName")}`}>
|
96 |
-
<video src={`/api/download/${row.getValue("fileName")}`} muted autoPlay />
|
97 |
</a>
|
98 |
</div>,
|
99 |
enableSorting: false,
|
|
|
57 |
},
|
58 |
},
|
59 |
{
|
60 |
+
accessorKey: "progressPercent",
|
61 |
header: ({ column }) => (
|
62 |
+
<DataTableColumnHeader column={column} title="Progress" />
|
63 |
),
|
64 |
cell: ({ row }) => {
|
65 |
+
const progress = Number(row.getValue("progressPercent") || 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
|
67 |
return (
|
68 |
<div className="flex w-[100px] items-center">
|
69 |
+
<span>{progress}%</span>
|
|
|
|
|
|
|
70 |
</div>
|
71 |
)
|
72 |
},
|
|
|
84 |
className="hover:underline cursor-pointer"
|
85 |
target="_blank"
|
86 |
href={`/api/download/${row.getValue("fileName")}`}>
|
87 |
+
<video src={`/api/download/${row.getValue("fileName")}?progress=${row.getValue("progressPercent") || 0}`} muted autoPlay loop />
|
88 |
</a>
|
89 |
</div>,
|
90 |
enableSorting: false,
|
src/components/business/tasks/video-tasks-queue.tsx
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
"use client"
|
2 |
|
3 |
-
import * as React from "react"
|
4 |
import {
|
5 |
ColumnDef,
|
6 |
ColumnFiltersState,
|
@@ -27,19 +26,20 @@ import {
|
|
27 |
|
28 |
import { columns } from "@/components/business/tasks/columns"
|
29 |
import { VideoTask } from "@/app/types"
|
|
|
30 |
|
31 |
export function VideoTasksQueue({
|
32 |
tasks
|
33 |
}: {
|
34 |
tasks: VideoTask[]
|
35 |
}) {
|
36 |
-
const [rowSelection, setRowSelection] =
|
37 |
const [columnVisibility, setColumnVisibility] =
|
38 |
-
|
39 |
-
const [columnFilters, setColumnFilters] =
|
40 |
[]
|
41 |
)
|
42 |
-
const [sorting, setSorting] =
|
43 |
|
44 |
const table = useReactTable({
|
45 |
data: tasks,
|
@@ -62,7 +62,7 @@ export function VideoTasksQueue({
|
|
62 |
getFacetedRowModel: getFacetedRowModel(),
|
63 |
getFacetedUniqueValues: getFacetedUniqueValues(),
|
64 |
})
|
65 |
-
|
66 |
return (
|
67 |
<div className="rounded-lg border overflow-hidden">
|
68 |
<Table>
|
|
|
1 |
"use client"
|
2 |
|
|
|
3 |
import {
|
4 |
ColumnDef,
|
5 |
ColumnFiltersState,
|
|
|
26 |
|
27 |
import { columns } from "@/components/business/tasks/columns"
|
28 |
import { VideoTask } from "@/app/types"
|
29 |
+
import { useState } from "react"
|
30 |
|
31 |
export function VideoTasksQueue({
|
32 |
tasks
|
33 |
}: {
|
34 |
tasks: VideoTask[]
|
35 |
}) {
|
36 |
+
const [rowSelection, setRowSelection] = useState({})
|
37 |
const [columnVisibility, setColumnVisibility] =
|
38 |
+
useState<VisibilityState>({})
|
39 |
+
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
|
40 |
[]
|
41 |
)
|
42 |
+
const [sorting, setSorting] = useState<SortingState>([])
|
43 |
|
44 |
const table = useReactTable({
|
45 |
data: tasks,
|
|
|
62 |
getFacetedRowModel: getFacetedRowModel(),
|
63 |
getFacetedUniqueValues: getFacetedUniqueValues(),
|
64 |
})
|
65 |
+
|
66 |
return (
|
67 |
<div className="rounded-lg border overflow-hidden">
|
68 |
<Table>
|
src/server/actions.ts
CHANGED
@@ -4,11 +4,17 @@ import { revalidatePath } from "next/cache"
|
|
4 |
import { submitNewTask } from "."
|
5 |
|
6 |
export async function formSubmit(formData: FormData) {
|
|
|
|
|
7 |
await submitNewTask({
|
8 |
prompt: `${formData.get("prompt") || ""}`,
|
9 |
-
ownerId
|
10 |
})
|
11 |
|
12 |
// for doc see https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
|
13 |
-
revalidatePath(
|
|
|
|
|
|
|
|
|
14 |
}
|
|
|
4 |
import { submitNewTask } from "."
|
5 |
|
6 |
export async function formSubmit(formData: FormData) {
|
7 |
+
|
8 |
+
const ownerId = `${formData.get("ownerId") || ""}`
|
9 |
await submitNewTask({
|
10 |
prompt: `${formData.get("prompt") || ""}`,
|
11 |
+
ownerId,
|
12 |
})
|
13 |
|
14 |
// for doc see https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions
|
15 |
+
revalidatePath(`/studio/${ownerId}`)
|
16 |
+
}
|
17 |
+
|
18 |
+
export async function refreshStudio(ownerId: string) {
|
19 |
+
revalidatePath(`/studio/${ownerId}`)
|
20 |
}
|
src/server/base.ts
CHANGED
@@ -11,9 +11,9 @@ export const get = async <T>(path: string = '', defaultValue: T): Promise<T> =>
|
|
11 |
Accept: "application/json",
|
12 |
Authorization: `Bearer ${process.env.VC_SECRET_ACCESS_TOKEN}`,
|
13 |
},
|
14 |
-
cache: 'no-store',
|
15 |
// we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
|
16 |
-
|
17 |
})
|
18 |
|
19 |
// The return value is *not* serialized
|
|
|
11 |
Accept: "application/json",
|
12 |
Authorization: `Bearer ${process.env.VC_SECRET_ACCESS_TOKEN}`,
|
13 |
},
|
14 |
+
//cache: 'no-store',
|
15 |
// we can also use this (see https://vercel.com/blog/vercel-cache-api-nextjs-cache)
|
16 |
+
next: { revalidate: 2 }
|
17 |
})
|
18 |
|
19 |
// The return value is *not* serialized
|