Skip to content

Commit

Permalink
feat: Mobx integration, List and Kanban boards implementation in plan…
Browse files Browse the repository at this point in the history
…e space (#1844)

* feat: init mobx and issue filter

* feat: Implemented list and kanban views in plane space and integrated mobx.

* feat: updated store type check
  • Loading branch information
gurusainath committed Aug 11, 2023
1 parent ad4cdcc commit cd5e5b9
Show file tree
Hide file tree
Showing 63 changed files with 2,123 additions and 7 deletions.
2 changes: 1 addition & 1 deletion apps/space/.env.example
Original file line number Diff line number Diff line change
@@ -1 +1 @@
NEXT_PUBLIC_VERCEL_ENV=local
NEXT_PUBLIC_API_BASE_URL=''
33 changes: 33 additions & 0 deletions apps/space/app/[workspace_slug]/[project_slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

// next imports
import Link from "next/link";
import Image from "next/image";
// components
import IssueNavbar from "components/issues/navbar";
import IssueFilter from "components/issues/filters-render";

const RootLayout = ({ children }: { children: React.ReactNode }) => (
<div className="relative w-screen min-h-[500px] h-screen overflow-hidden flex flex-col">
<div className="flex-shrink-0 h-[60px] border-b border-gray-300 relative flex items-center bg-white select-none">
<IssueNavbar />
</div>
{/* <div className="flex-shrink-0 min-h-[50px] h-auto py-1.5 border-b border-gray-300 relative flex items-center shadow-md bg-white select-none">
<IssueFilter />
</div> */}
<div className="w-full h-full relative bg-gray-100/50 overflow-hidden">{children}</div>

<div className="absolute z-[99999] bottom-[10px] right-[10px] bg-white rounded-sm shadow-lg border border-gray-100">
<Link href="https://plane.so" className="p-1 px-2 flex items-center gap-1" target="_blank">
<div className="w-[24px] h-[24px] relative flex justify-center items-center">
<Image src="/plane-logo.webp" alt="plane logo" className="w-[24px] h-[24px]" height="24" width="24" />
</div>
<div className="text-xs">
Powered by <b>Plane Deploy</b>
</div>
</Link>
</div>
</div>
);

export default RootLayout;
84 changes: 84 additions & 0 deletions apps/space/app/[workspace_slug]/[project_slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"use client";

import { useEffect } from "react";
// next imports
import { useRouter, useParams, useSearchParams } from "next/navigation";
// mobx
import { observer } from "mobx-react-lite";
// components
import { IssueListView } from "components/issues/board-views/list";
import { IssueKanbanView } from "components/issues/board-views/kanban";
import { IssueCalendarView } from "components/issues/board-views/calendar";
import { IssueSpreadsheetView } from "components/issues/board-views/spreadsheet";
import { IssueGanttView } from "components/issues/board-views/gantt";
// mobx store
import { RootStore } from "store/root";
import { useMobxStore } from "lib/mobx/store-provider";
// types
import { TIssueBoardKeys } from "store/types";

const WorkspaceProjectPage = observer(() => {
const store: RootStore = useMobxStore();

const router = useRouter();
const routerParams = useParams();
const routerSearchparams = useSearchParams();

const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
const board = routerSearchparams.get("board") as TIssueBoardKeys | "";

// updating default board view when we are in the issues page
useEffect(() => {
if (workspace_slug && project_slug) {
if (!board) {
store.issue.setCurrentIssueBoardView("list");
router.replace(`/${workspace_slug}/${project_slug}?board=${store?.issue?.currentIssueBoardView}`);
} else {
if (board != store?.issue?.currentIssueBoardView) store.issue.setCurrentIssueBoardView(board);
}
}
}, [workspace_slug, project_slug, board, router, store?.issue]);

useEffect(() => {
if (workspace_slug && project_slug) {
store?.project?.getProjectSettingsAsync(workspace_slug, project_slug);
store?.issue?.getIssuesAsync(workspace_slug, project_slug);
}
}, [workspace_slug, project_slug, store?.project, store?.issue]);

return (
<div className="relative w-full h-full overflow-hidden">
{store?.issue?.loader && !store.issue.issues ? (
<div className="text-sm text-center py-10 text-gray-500">Loading...</div>
) : (
<>
{store?.issue?.error ? (
<div className="text-sm text-center py-10 text-gray-500">Something went wrong.</div>
) : (
store?.issue?.currentIssueBoardView && (
<>
{store?.issue?.currentIssueBoardView === "list" && (
<div className="relative w-full h-full overflow-y-auto">
<div className="container mx-auto px-5 py-3">
<IssueListView />
</div>
</div>
)}
{store?.issue?.currentIssueBoardView === "kanban" && (
<div className="relative w-full h-full mx-auto px-5">
<IssueKanbanView />
</div>
)}
{store?.issue?.currentIssueBoardView === "calendar" && <IssueCalendarView />}
{store?.issue?.currentIssueBoardView === "spreadsheet" && <IssueSpreadsheetView />}
{store?.issue?.currentIssueBoardView === "gantt" && <IssueGanttView />}
</>
)
)}
</>
)}
</div>
);
});

export default WorkspaceProjectPage;
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React from "react";
"use client";

const WorkspaceProjectPage = () => (
<div className="relative w-screen h-screen flex justify-center items-center text-5xl">
Plane Workspace project Space
</div>
<div className="relative w-screen h-screen flex justify-center items-center text-5xl">Plane Workspace Space</div>
);

export default WorkspaceProjectPage;
10 changes: 9 additions & 1 deletion apps/space/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
"use client";

// root styles
import "styles/globals.css";
// mobx store provider
import { MobxStoreProvider } from "lib/mobx/store-provider";
import MobxStoreInit from "lib/mobx/store-init";

const RootLayout = ({ children }: { children: React.ReactNode }) => (
<html lang="en">
<body className="antialiased w-100">
<main>{children}</main>
<MobxStoreProvider>
<MobxStoreInit />
<main>{children}</main>
</MobxStoreProvider>
</body>
</html>
);
Expand Down
2 changes: 2 additions & 0 deletions apps/space/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import React from "react";

const HomePage = () => (
Expand Down
5 changes: 5 additions & 0 deletions apps/space/components/icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from "./issue-group/backlog-state-icon";
export * from "./issue-group/unstarted-state-icon";
export * from "./issue-group/started-state-icon";
export * from "./issue-group/completed-state-icon";
export * from "./issue-group/cancelled-state-icon";
23 changes: 23 additions & 0 deletions apps/space/components/icons/issue-group/backlog-state-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
// types
import type { Props } from "../types";
// constants
import { issueGroupColors } from "constants/data";

export const BacklogStateIcon: React.FC<Props> = ({
width = "14",
height = "14",
className,
color = issueGroupColors["backlog"],
}) => (
<svg
width={width}
height={height}
className={className}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="10" cy="10" r="9" stroke={color} strokeLinecap="round" strokeDasharray="4 4" />
</svg>
);
74 changes: 74 additions & 0 deletions apps/space/components/icons/issue-group/cancelled-state-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from "react";
// types
import type { Props } from "../types";
// constants
import { issueGroupColors } from "constants/data";

export const CancelledStateIcon: React.FC<Props> = ({
width = "14",
height = "14",
className,
color = issueGroupColors["cancelled"],
}) => (
<svg width={width} height={height} className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 84.36 84.36">
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M20.45,7.69a39.74,39.74,0,0,1,43.43.54"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M76.67,20.45a39.76,39.76,0,0,1-.53,43.43"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M63.92,76.67a39.78,39.78,0,0,1-43.44-.53"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M7.69,63.92a39.75,39.75,0,0,1,.54-43.44"
/>
<circle className="cls-2" fill={color} cx="42.18" cy="42.18" r="31.04" />
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M32.64,32.44q9.54,9.75,19.09,19.48"
/>
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M32.64,51.92,51.73,32.44"
/>
</g>
</g>
</svg>
);
65 changes: 65 additions & 0 deletions apps/space/components/icons/issue-group/completed-state-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from "react";
// types
import type { Props } from "../types";
// constants
import { issueGroupColors } from "constants/data";

export const CompletedStateIcon: React.FC<Props> = ({
width = "14",
height = "14",
className,
color = issueGroupColors["completed"],
}) => (
<svg width={width} height={height} className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 84.36 84.36">
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M20.45,7.69a39.74,39.74,0,0,1,43.43.54"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M76.67,20.45a39.76,39.76,0,0,1-.53,43.43"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M63.92,76.67a39.78,39.78,0,0,1-43.44-.53"
/>
<path
className="cls-1"
fill="none"
strokeWidth={3}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
d="M7.69,63.92a39.75,39.75,0,0,1,.54-43.44"
/>
<circle className="cls-2" fill={color} cx="42.18" cy="42.18" r="31.04" />
<path
className="cls-3"
fill="none"
strokeWidth={3}
stroke="#ffffff"
strokeLinecap="square"
strokeMiterlimit={10}
d="M30.45,43.75l6.61,6.61L53.92,34"
/>
</g>
</g>
</svg>
);
Loading

0 comments on commit cd5e5b9

Please sign in to comment.