Skip to content

Commit

Permalink
Merge pull request #196 from openchatai/minor/dashboard-polishing
Browse files Browse the repository at this point in the history
Minor/dashboard polishing
  • Loading branch information
faltawy authored Nov 7, 2023
2 parents 2d7cce3 + c64aff1 commit 34f987c
Show file tree
Hide file tree
Showing 36 changed files with 1,917 additions and 130 deletions.
12 changes: 12 additions & 0 deletions dashboard/app/(copilot)/_parts/CopilotNotFound.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { EmptyBlock } from "@/components/domain/EmptyBlock";
import React from "react";

export function CopilotNotFound() {
return (
<div className="flex-center h-full w-full">
<EmptyBlock Imagesize={100}>
<h2 className="text-center text-xl font-semibold">Copilot not found</h2>
</EmptyBlock>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function WorkflowsList({ copilot_id }: { copilot_id: string }) {
<li key={i} className="h-fit w-full">
<NavLink
href={flowsBase + "/?workflow_id=" + workflow._id}
matchSearchParams
className="flex items-center rounded border px-4 py-2 text-sm font-medium text-accent-foreground transition duration-150 ease-in-out "
activeClassName="border-gray-300 bg-accent"
>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useSearchParams } from "next/navigation";

export function useIsEditing() {
const searchParams = useSearchParams();
const workflow_id = searchParams.get("workflow_id");
const isEditing = !!workflow_id;
return [isEditing, workflow_id] as const;
}
168 changes: 78 additions & 90 deletions dashboard/app/(copilot)/copilot/[copilot_id]/flows/page.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,49 @@
"use client";
import React, { useState } from "react";
import {
CodePreview,
Controller,
FlowArena,
useController,
transformPaths,
trasnformEndpointNodesData,
} from "@openchatai/copilot-flows-editor";
import { HeaderShell } from "@/components/domain/HeaderShell";
import { useCopilot } from "../../_context/CopilotProvider";
import useSwr from "swr";
import useSwr, { mutate } from "swr";
import { getSwaggerByBotId } from "@/data/swagger";
import { Button } from "@/components/ui/button";
import {
createWorkflowByBotId,
deleteWorkflowById,
getWorkflowsByBotId,
getWorkflowById,
} from "@/data/flow";
import { useRouter, useSearchParams } from "next/navigation";
import { useRouter } from "next/navigation";
import { toast } from "@/components/ui/use-toast";
import _ from "lodash";
import { useIsEditing } from "./_parts/useIsEditing";
import {
Controller,
FlowArena,
transformPaths,
useController,
} from "@/components/domain/flows-editor";

function Header() {
const { id: copilotId, name: copilotName } = useCopilot();
const { loadPaths, state } = useController();
const saerchParams = useSearchParams();
const workflow_id = saerchParams.get("workflow_id");
const isEditing = !!workflow_id;
const { replace } = useRouter();
const [loading, setLoading] = useState(false);
// editing => workflow_id // creating => undefined
const { isLoading: isSwaggerLoading } = useSwr(
const [isEditing, workflow_id] = useIsEditing();
const { replace } = useRouter();
const { id: copilotId, name: copilotName } = useCopilot();
const {
loadPaths,
reset: resetFlowEditor,
getData,
loadFlows,
state,
} = useController();
useSwr(workflow_id, getWorkflowById, {
onSuccess: (data) => {
const first = _.first(data.data.flows);
if (first) {
console.log(first);
// @ts-ignore
loadFlows([first]);
}
},
});
const { isLoading: isSwaggerLoading, mutate: mutateSwagger } = useSwr(
copilotId + "swagger_file",
async () => getSwaggerByBotId(copilotId),
{
Expand All @@ -41,14 +53,16 @@ function Header() {
},
},
);
console.log(state);
const [loading, setLoading] = useState(false);
const isLoading = isSwaggerLoading || loading;

async function handleSave() {}
async function handleDelete() {
if (!isEditing || !workflow_id) return;
setLoading(true);
const { data } = await deleteWorkflowById(workflow_id);
if (data) {
console.log(data);
toast({
title: "Workflow deleted",
description: "Your workflow has been deleted.",
Expand All @@ -57,46 +71,46 @@ function Header() {
replace(`/copilot/${copilotId}/flows`, {
scroll: false,
});
mutate(copilotId + "/workflows");
setLoading(false);
}
}
async function handleCreate() {
if (isEditing) return;
setLoading(true);
const firstFlow = _.first(state.flows);
const steps = trasnformEndpointNodesData(firstFlow?.steps || []);

const { data } = await createWorkflowByBotId(copilotId, {
opencopilot: "0.1",
info: {
title: "My OpenCopilot definition",
version: "1.0.0",
},
flows: [
{
name: firstFlow?.name,
description: firstFlow?.description,
steps: steps.map((step) => ({
operation: "call",
stepId: step.id,
open_api_operation_id: step.operationId,
})),
requires_confirmation: true,
on_success: [{}],
on_failure: [{}],
},
],
});
if (data.workflow_id) {
const firstFlow = _.first(getData().flows);
if (firstFlow) {
setLoading(true);
try {
const { data } = await createWorkflowByBotId(copilotId, getData());
if (data.workflow_id) {
toast({
title: "Workflow created",
description: "Your workflow has been created.",
variant: "success",
});
replace(
`/copilot/${copilotId}/flows/?workflow_id=${data.workflow_id}`,
{
scroll: false,
},
);
mutate(copilotId + "/workflows");
}
} catch (error) {
toast({
title: "Workflow not created",
description: "Something went wrong.",
variant: "destructive",
});
} finally {
setLoading(false);
}
} else {
toast({
title: "Workflow created",
description: "Your workflow has been created.",
variant: "success",
});
replace(`/copilot/${copilotId}/flows/?workflow_id=${data.workflow_id}`, {
scroll: false,
title: "Workflow not created",
description: "You need at least one flow to create a workflow.",
variant: "destructive",
});
setLoading(false);
}
}
return (
Expand All @@ -122,53 +136,27 @@ function Header() {
<Button onClick={handleCreate} disabled={isLoading}>
Create
</Button>
<Button
variant="destructive"
onClick={() => {
confirm("Are you sure??") && resetFlowEditor();
mutateSwagger();
}}
>
Reset
</Button>
</div>
)}
</HeaderShell>
);
}

export default function FlowsPage({
params: { copilot_id },
}: {
params: { copilot_id: string };
}) {
const saerchParams = useSearchParams();
const workflow_id = saerchParams.get("workflow_id");
const isEditing = !!workflow_id;

const { data: workflowData } = useSwr(copilot_id + "/swagger", () =>
getWorkflowsByBotId(copilot_id),
);
console.log(workflowData);
export default function FlowsPage() {
return (
// @ts-ignore
<Controller
maxFlows={1}
initialState={{
flows: [
{
id: "flow-1",
name: "",
createdAt: 123564654,
description: "",
updatedAt: 123564654,
steps: [
{
id: "fick",
data: {},
},
],
},
],
paths: [],
}}
>
<Controller maxFlows={1}>
<div className="flex h-full w-full flex-col">
<Header />
<div className="relative flex h-full w-full flex-1 items-start justify-between">
<FlowArena />
<CodePreview />
</div>
</div>
</Controller>
Expand Down
3 changes: 1 addition & 2 deletions dashboard/app/(copilot)/copilot/[copilot_id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ function InstallationSection() {
<CodeBlock
code={`<script>
// be aware to call this function when the document/window is ready.
const options = {
apiUrl: "http://localhost:8888/backend/api" // your base url where your are hosting OpenCopilot at (the API), usually it's http://localhost:5000/api
apiUrl: "http://localhost:8888/backend/api", // your base url where your are hosting OpenCopilot at (the API), usually it's http://localhost:5000/api
initialMessages: ["How are the things"], // optional: you can pass an array of messages that will be sent to the copilot when it's initialized
token: "${CopilotToken}", // you can get your token from the dashboard
triggerSelector: "#triggerSelector", // the selector of the element that will trigger the copilot when clicked
Expand Down
3 changes: 2 additions & 1 deletion dashboard/app/(copilot)/copilot/_context/CopilotProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { createSafeContext } from "@/lib/createSafeContext";
import { useParams } from "next/navigation";
import React from "react";
import useSwr from "swr";
import { CopilotNotFound } from "../../_parts/CopilotNotFound";
const [SafeCopilotProvider, useCopilot] = createSafeContext<CopilotType>(
"[useCopilot] should be used within a CopilotProvider",
);
Expand All @@ -26,7 +27,7 @@ function CopilotProvider({ children }: { children: React.ReactNode }) {
</SafeCopilotProvider>
);
} else {
return <div>copilot not found</div>;
return <CopilotNotFound />;
}
}

Expand Down
25 changes: 24 additions & 1 deletion dashboard/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
@import url("@openchatai/copilot-flows-editor/dist/style.css");
@tailwind base;
@tailwind components;
@tailwind utilities;
Expand Down Expand Up @@ -102,3 +101,27 @@
display: none; /* Safari and Chrome */
}
}
.loading-el {
position: relative;
overflow: hidden;
pointer-events: none;
color: transparent;
}
.loading-el::after {
content: "";
position: absolute;
inset: 0;
z-index: 10;
@apply bg-white opacity-50;
}

.loading-el::before {
content: "";
position: absolute;
z-index: 11;
translate: -50% -50%;
top: 50%;
left: 50%;
border-width: 3px;
@apply h-5 w-5 animate-spin rounded-full border-primary border-t-transparent;
}
10 changes: 9 additions & 1 deletion dashboard/app/swr-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,13 @@
import React from "react";
import { SWRConfig } from "swr";
export function SWRProvider({ children }: { children: React.ReactNode }) {
return <SWRConfig>{children}</SWRConfig>;
return (
<SWRConfig
value={{
revalidateOnFocus: false,
}}
>
{children}
</SWRConfig>
);
}
4 changes: 3 additions & 1 deletion dashboard/components/domain/CodeBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ function CodeBlock({
padding: "20px 24px",
color: "#ddd",
fontFamily: '"Fira Code"',
fontSize: "13px",
fontSize: "14px",
margin: "0px",
borderRadius: "0.5rem",
fontWeight: 500,
},
}}
wrapLongLines
>
{code}
</SyntaxHighlighter>
Expand Down
Loading

0 comments on commit 34f987c

Please sign in to comment.