Skip to content
This repository has been archived by the owner on Jul 20, 2024. It is now read-only.

Commit

Permalink
botway(core): big upgrades
Browse files Browse the repository at this point in the history
  • Loading branch information
abdfnx committed Jun 24, 2023
1 parent b6d88c8 commit a4a1eb6
Show file tree
Hide file tree
Showing 13 changed files with 716 additions and 417 deletions.
2 changes: 1 addition & 1 deletion .gitpod/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM botwayorg/gp-image:latest
USER gitpod

# Install tools
RUN brew install go-task/tap/go-task abdfnx/tap/gomo abdfnx/tap/botway deno go gh dart-lang/dart/dart
RUN brew install go-task/tap/go-task abdfnx/tap/gomo abdfnx/tap/botway deno go gh dart-lang/dart/dart poetry

# Install pnpm
RUN sudo npm i -g npm@latest pnpm@latest
Expand Down
Empty file added core/app/api/ai/route.ts
Empty file.
16 changes: 11 additions & 5 deletions core/app/api/ce/enable/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,17 @@ export async function POST(request: Request) {
name: "bwce-${body.slug}-${faker.number.int({ max: 100 })}"
serviceName: "CE"
template: "https://github.com/botwayorg/ce"
variables: {GIT_REPO: "https://github.com/${
body.repo
}" GITHUB_TOKEN: "${githubApiToken.data}" PASSWORD: "${
password.data
}"}
variables: {
GIT_REPO: "https://github.com/${body.repo}"
GITHUB_TOKEN: "${githubApiToken.data}"
PASSWORD: "${password.data}"
}
volumes: [
{
mountPath: "/home/coder"
projectId: "${projectId.data}"
}
]
}
]
Expand Down
88 changes: 88 additions & 0 deletions core/app/api/projects/services/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { NextResponse } from "next/server";
import { jwtDecrypt } from "jose";
import { BW_SECRET_KEY } from "@/tools/tokens";
import { fetcher } from "@/tools/fetch";
import createClient from "@/supabase/server";

export const revalidate = 0;

export async function POST(request: Request) {
const body = await request.json();

const supabase = createClient();

const {
data: { user: user },
error: userError,
} = await supabase.auth.getUser();

if (userError) {
return NextResponse.json({ error: userError });
}

const { data, error } = await supabase
.from("projects")
.select("railway_project_id")
.eq("id", body.projectId)
.single();

if (error) {
return NextResponse.json({ error });
}

const { payload: railwayProjectId } = await jwtDecrypt(
data.railway_project_id,
BW_SECRET_KEY
);

const { payload: railwayApiToken } = await jwtDecrypt(
user?.user_metadata["railwayApiToken"],
BW_SECRET_KEY
);

const projectData = await fetcher(
"https://backboard.railway.app/graphql/v2",
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${railwayApiToken.data}`,
},
body: JSON.stringify({
query: `
query {
project(id: "${railwayProjectId.data}") {
services {
edges {
node {
id
name
}
}
}
plugins {
edges {
node {
id
name
}
}
}
}
}
`,
}),
}
);

if (projectData.errors) {
return NextResponse.json({ error: projectData.errors[0].message });
}

return NextResponse.json({
message: "Success",
services: projectData.data.project.services.edges,
plugins: projectData.data.project.plugins.edges,
});
}
2 changes: 1 addition & 1 deletion core/app/project/[id]/code-editor/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const CE = ({ user, projectId }: any) => {
: "Your project needs to enable Botway CE"}
</h2>
<h2 className="text-sm text-gray-500 text-center">
Botway CE is a code editor that build on top of{" "}
Botway CE is a code editor that built on top of{" "}
<Link
href="https://coder.com"
target="_blank"
Expand Down
17 changes: 17 additions & 0 deletions core/app/project/[id]/nodes/node-loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { memo } from "react";

const NodeLoading = () => {
return (
<div className="px-4 py-2 rounded-xl bg-secondary border-2 border-dashed border-gray-800">
<div className="animate-pulse flex">
<div className="rounded-full w-12 h-12 flex justify-center items-center bg-bwdefualt" />
<div className="ml-2 pt-1">
<div className="h-4 w-20 mb-3 bg-bwdefualt rounded" />
<div className="h-3 w-10 bg-bwdefualt rounded" />
</div>
</div>
</div>
);
};

export default memo(NodeLoading);
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ const Node = ({ data }: any) => {
return (
<div className="px-4 py-2 rounded-xl bg-secondary border-2 border-dashed border-gray-800">
<div className="flex">
<div className="rounded-full w-12 h-12 flex justify-center items-center bg-gray-800"></div>
<div className="rounded-full w-12 h-12 flex justify-center items-center bg-gray-800" />
<div className="ml-2">
<div className="text-lg text-white font-bold">{data.name}</div>
{/* <div className="text-gray-400"></div> */}
<div className="text-base text-center text-white font-bold">
{data.name}
</div>
</div>
</div>
</div>
Expand Down
143 changes: 118 additions & 25 deletions core/app/project/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,134 @@ import {
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query";
import ReactFlow, { useNodesState } from "reactflow";
import Node from "./node";
import ReactFlow, { Node, useNodesState, ConnectionLineType } from "reactflow";
import NodeCustom from "./nodes/node";
import NodeLoading from "./nodes/node-loading";
import { fetcher } from "@/tools/fetch";
import dagre from "dagre";

const dagreGraph = new dagre.graphlib.Graph();
dagreGraph.setDefaultEdgeLabel(() => ({}));

export const revalidate = 0;

const queryClient = new QueryClient();

const nodeTypes = {
custom: Node,
custom: NodeCustom,
loading: NodeLoading,
};

const initNodes = [
{
id: "1",
type: "custom",
data: { name: "Test1" },
position: { x: 0, y: 50 },
},
];

const Flow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(initNodes);
const Project = ({ user, projectId }: any) => {
const fetchServices = async () => {
const services = await fetcher(`/api/projects/services`, {
method: "POST",
body: JSON.stringify({
projectId,
}),
});

return services;
};

return (
<ReactFlow
nodes={nodes}
onNodesChange={onNodesChange}
nodeTypes={nodeTypes}
fitView
nodesDraggable={false}
className=""
/>
const { data: services, isLoading: servicesIsLoading } = useQuery(
["services"],
fetchServices,
{
refetchInterval: 1,
refetchOnReconnect: true,
refetchOnWindowFocus: true,
refetchIntervalInBackground: true,
}
);
};

const Project = ({ user, projectId }: any) => {
let initNodes: Node<any, string | undefined>[] = [];

const nodeWidth = 172;
const nodeHeight = 36;

const getLayoutedElements = (nodes: any, direction = "TB") => {
const isHorizontal = direction === "LR";
dagreGraph.setGraph({ rankdir: direction });

nodes.forEach((node: any) => {
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight });
});

dagre.layout(dagreGraph);

nodes.forEach((node: any) => {
const nodeWithPosition = dagreGraph.node(node.id);

node.targetPosition = isHorizontal ? "left" : "top";
node.sourcePosition = isHorizontal ? "right" : "bottom";

// We are shifting the dagre node position (anchor=center center) to the top left
// so it matches the React Flow node anchor point (top left).
node.position = {
x: (nodeWithPosition.x * (services?.services.length - 2)) / 2,
y: 2 * (nodeWithPosition.y * services?.services.length),
};

return node;
});

return { nodes };
};

const position = { x: 0, y: 0 };

services?.services.map((node: any, index: any) => {
initNodes.push({
id: `"${index + 1}"`,
type: "custom",
data: {
name: node.node.name,
},
position,
});
});

services?.plugins.map((node: any, index: any) => {
initNodes.push({
id: `"${index + services?.services.length + 1}"`,
type: "custom",
data: {
name: node.node.name,
},
position,
});
});

const initNodesLoading = [
{
id: "1",
type: "loading",
data: {},
position: { x: 0, y: 50 },
},
];

const { nodes: layoutedNodes } = getLayoutedElements(initNodes);

const Flow = () => {
const [nodes, setNodes, onNodesChange] = useNodesState(
servicesIsLoading ? initNodesLoading : layoutedNodes
);

return (
<ReactFlow
nodes={nodes}
connectionLineType={ConnectionLineType.SmoothStep}
onNodesChange={onNodesChange}
nodeTypes={nodeTypes}
fitView
nodesDraggable={false}
className=""
/>
);
};

const fetchProject = async () => {
const { data: project } = await supabase
.from("projects")
Expand Down Expand Up @@ -77,6 +169,7 @@ const Project = ({ user, projectId }: any) => {
projectId={projectId}
projectName={project?.name}
projectRWID={project?.railway_project_id}
grid={true}
noMargin={true}
>
<div className="w-screen h-screen">
Expand Down
Loading

0 comments on commit a4a1eb6

Please sign in to comment.