-
Notifications
You must be signed in to change notification settings - Fork 399
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #522 from openchatai/ui/better-actions-ui
Better UI for users to manage their actions without creating flows
- Loading branch information
Showing
22 changed files
with
462 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
dashboard/app/(copilot)/copilot/[copilot_id]/actions/Action.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"; | ||
import { Settings2, Trash2 } from "lucide-react"; | ||
import { Button } from "@/components/ui/button"; | ||
import { methodVariants } from "@/components/domain/MethodRenderer"; | ||
import { useRef } from "react"; | ||
import { Row } from "@tanstack/react-table"; | ||
import { Stack } from "@/components/ui/Stack"; | ||
import { ActionForm } from "@/components/domain/action-form/ActionForm"; | ||
import { ActionWithModifiedParametersResponse } from "@/data/actions"; | ||
import { useUpdateAction } from "@/hooks/useActions"; | ||
import { useCopilot } from "../../_context/CopilotProvider"; | ||
|
||
export function Action({ getValue, original }: Row<ActionWithModifiedParametersResponse>) { | ||
const { | ||
id: copilotId | ||
} = useCopilot(); | ||
const containerRef = useRef<HTMLDivElement>(null); | ||
|
||
const [ | ||
state, | ||
updateAction | ||
] = useUpdateAction(copilotId, original.id) | ||
|
||
return <Stack | ||
ref={containerRef} | ||
ic="start" | ||
gap={5} | ||
direction="column" | ||
className='bg-secondary p-3.5 rounded-lg transition-all col-span-full lg:col-span-6 xl:col-span-4 border border-primary/20 shadow-sm'> | ||
<Stack ic="start" gap={10} id="some" direction="row"> | ||
<div className='text-sm font-semibold flex-1'>{getValue("name")}</div> | ||
{/* @ts-ignore */} | ||
<div className={methodVariants({ size: "tiny", method: String(getValue("request_type")).toUpperCase() })}>{getValue("request_type")}</div> | ||
</Stack> | ||
<div className='text-xs text-gray-500'>{getValue("description")}</div> | ||
<Stack | ||
direction="row" | ||
js="between"> | ||
<div> | ||
<span className="text-secondary-foreground font-medium text-xs text-start whitespace-nowrap"> | ||
Created {" "}{getValue("created_at")} | ||
</span> | ||
</div> | ||
<Stack className="mt-auto gap-1" js="end"> | ||
<AlertDialog> | ||
<AlertDialogContent className="overflow-hidden"> | ||
</AlertDialogContent> | ||
<AlertDialogTrigger asChild> | ||
<Button size='fit'> | ||
<Settings2 size={15} /> | ||
</Button> | ||
</AlertDialogTrigger> | ||
<AlertDialogContent> | ||
<AlertDialogHeader> | ||
<AlertDialogTitle>Edit Action</AlertDialogTitle> | ||
</AlertDialogHeader> | ||
{/* */} | ||
<ActionForm defaultValues={original} | ||
className="overflow-auto no-scrollbar" | ||
onSubmit={async (data) => { | ||
await updateAction(data) | ||
}} | ||
footer={() => <AlertDialogFooter className="my-4"> | ||
<AlertDialogCancel asChild> | ||
<Button variant='secondary'> | ||
Cancel | ||
</Button> | ||
</AlertDialogCancel> | ||
<Button variant='default' type="submit" loading={state.loading}> | ||
Save | ||
</Button> | ||
</AlertDialogFooter> | ||
} | ||
/> | ||
{/* */} | ||
|
||
</AlertDialogContent> | ||
</AlertDialog> | ||
<AlertDialog> | ||
<AlertDialogContent> | ||
<AlertDialogHeader> | ||
<AlertDialogTitle>Delete Action</AlertDialogTitle> | ||
<AlertDialogDescription> | ||
Are you sure you want to delete this action? This action cannot be undone. | ||
</AlertDialogDescription> | ||
</AlertDialogHeader> | ||
<AlertDialogFooter> | ||
<AlertDialogCancel asChild> | ||
<Button variant='secondary' size='fit'> | ||
Cancel | ||
</Button> | ||
</AlertDialogCancel> | ||
<AlertDialogAction asChild> | ||
<Button variant='destructive' size='fit'> | ||
Delete | ||
</Button> | ||
</AlertDialogAction> | ||
</AlertDialogFooter> | ||
</AlertDialogContent> | ||
<AlertDialogTrigger asChild> | ||
<Button variant='destructiveOutline' size='fit'> | ||
<Trash2 size={15} /> | ||
</Button> | ||
</AlertDialogTrigger> | ||
</AlertDialog> | ||
</Stack> | ||
</Stack> | ||
</Stack> | ||
} |
99 changes: 99 additions & 0 deletions
99
dashboard/app/(copilot)/copilot/[copilot_id]/actions/ActionsDataGrid.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
'use client'; | ||
import { Input } from "@/components/ui/input"; | ||
import { useListActions } from "@/hooks/useActions"; | ||
import { ColumnDef, ColumnFiltersState, RowSelectionState, SortingState, getCoreRowModel, getFilteredRowModel, getGroupedRowModel, getPaginationRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table"; | ||
import { useCallback, useState } from "react"; | ||
import { Stack } from "@/components/ui/Stack"; | ||
import { format } from "timeago.js"; | ||
import _ from "lodash"; | ||
import { EmptyBlock } from "@/components/domain/EmptyBlock"; | ||
import { DataTablePagination } from "@/components/ui/TablePagination"; | ||
import { Action } from "./Action"; | ||
import { ActionWithModifiedParametersResponse } from "@/data/actions"; | ||
|
||
const columns: ColumnDef<ActionWithModifiedParametersResponse>[] = [ | ||
{ | ||
accessorKey: "id", | ||
id: "id" | ||
}, | ||
{ | ||
accessorKey: "name", | ||
id: "name" | ||
}, { | ||
accessorKey: "description", | ||
id: "description" | ||
}, { | ||
accessorKey: "request_type", | ||
id: "request_type" | ||
}, | ||
{ | ||
id: "created_at", | ||
accessorFn: (value) => format(value.created_at) | ||
}, | ||
{ | ||
id: "updated_at", | ||
accessorFn: (value) => format(value.updated_at) | ||
} | ||
]; | ||
|
||
export function ActionsDataGrid({ copilot_id }: { copilot_id: string }) { | ||
const { data: actions } = useListActions(copilot_id); | ||
const [sorting, setSorting] = useState<SortingState>([]); | ||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]); | ||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({}); | ||
|
||
const grid = useReactTable({ | ||
data: actions || [], | ||
columns, | ||
pageCount: 1, | ||
onRowSelectionChange: setRowSelection, | ||
onSortingChange: setSorting, | ||
onColumnFiltersChange: setColumnFilters, | ||
getCoreRowModel: getCoreRowModel(), | ||
getSortedRowModel: getSortedRowModel(), | ||
getFilteredRowModel: getFilteredRowModel(), | ||
getGroupedRowModel: getGroupedRowModel(), | ||
getPaginationRowModel: getPaginationRowModel(), | ||
enableFilters: true, | ||
enableColumnFilters: true, | ||
enableSorting: true, | ||
enableMultiRowSelection: false, | ||
state: { | ||
sorting, | ||
columnFilters, | ||
rowSelection, | ||
} | ||
}) | ||
|
||
const filterByName = useCallback((name: string) => { | ||
grid.getColumn("name")?.setFilterValue(name) | ||
}, [ | ||
grid | ||
]) | ||
console.log( | ||
grid.getSelectedRowModel().rows | ||
) | ||
return ( | ||
<div className="container"> | ||
<Stack fluid direction="row" js="between" className="!gap-5"> | ||
<Input placeholder="Search" | ||
className="flex-1" | ||
onChange={(e) => filterByName(e.target.value)} | ||
/> | ||
</Stack> | ||
<div className="grid gap-4 grid-cols-12 mt-5"> | ||
{_.isEmpty(grid.getRowModel().rows) ? | ||
<EmptyBlock> | ||
<h1 className="text-lg font-semibold">No actions found</h1> | ||
<p className="text-sm text-gray-500">Create a new action to get started</p> | ||
</EmptyBlock> | ||
: grid.getRowModel().rows.map((item, index) => ( | ||
<Action key={index} {...item} /> | ||
))} | ||
</div> | ||
<div hidden={grid.getPageCount() === 1} className="mt-4"> | ||
<DataTablePagination table={grid} /> | ||
</div> | ||
</div> | ||
) | ||
} |
44 changes: 44 additions & 0 deletions
44
dashboard/app/(copilot)/copilot/[copilot_id]/actions/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use client'; | ||
import { HeaderShell } from '@/components/domain/HeaderShell' | ||
import { RouteIcon } from 'lucide-react'; | ||
import { ActionsDataGrid } from './ActionsDataGrid'; | ||
import { Suspense } from 'react'; | ||
import { Stack } from '@/components/ui/Stack'; | ||
import { Button } from '@/components/ui/button'; | ||
import { AddActionDrawer, useActionFormState } from '@/components/domain/new-flows-editor/addActionDrawer'; | ||
|
||
type Props = { | ||
params: { | ||
copilot_id: string; | ||
} | ||
} | ||
|
||
export default function ActionsPage({ params }: Props) { | ||
const [ | ||
, | ||
setActionFormState | ||
] = useActionFormState(); | ||
return ( | ||
<Stack | ||
ic='center' | ||
direction='column' | ||
fluid | ||
className='size-full'> | ||
<HeaderShell className='justify-between'> | ||
<div className='flex items-center gap-2'> | ||
<RouteIcon size={24} /> | ||
<h1 className='text-lg font-semibold'>Actions</h1> | ||
</div> | ||
<div> | ||
<Button onClick={() => setActionFormState(true)} variant='default'>Create</Button> | ||
</div> | ||
</HeaderShell> | ||
<AddActionDrawer /> | ||
<div className='flex-1 w-full p-4 overflow-auto'> | ||
<Suspense fallback={<div>Loading...</div>}> | ||
<ActionsDataGrid copilot_id={params.copilot_id} /> | ||
</Suspense> | ||
</div> | ||
</Stack> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.