Skip to content

Commit

Permalink
refactor: publish boards
Browse files Browse the repository at this point in the history
  • Loading branch information
sriramveeraghanta committed May 14, 2024
1 parent 2b196ba commit a2fbd61
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 177 deletions.
5 changes: 0 additions & 5 deletions space/app/[workspace_slug]/[project_id]/error.tsx

This file was deleted.

7 changes: 6 additions & 1 deletion space/app/[workspace_slug]/[project_id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Image from "next/image";
import { notFound } from "next/navigation";
// components
import IssueNavbar from "@/components/issues/navbar";
// services
Expand All @@ -10,7 +11,11 @@ const projectService = new ProjectService();

export default async function ProjectLayout({ children, params }: { children: React.ReactNode; params: any }) {
const { workspace_slug, project_id } = params;
const projectSettings = await projectService.getProjectSettings(workspace_slug, project_id);
const projectSettings = await projectService.getProjectSettings(workspace_slug, project_id).catch(() => null);

if (!projectSettings) {
notFound();
}

return (
<div className="relative flex h-screen min-h-[500px] w-screen flex-col overflow-hidden">
Expand Down
3 changes: 0 additions & 3 deletions space/app/[workspace_slug]/[project_id]/not-found.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion space/app/[workspace_slug]/[project_id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"use client";
// components
import { ProjectDetailsView } from "@/components/views";

export default async function WorkspaceProjectPage({ params }: { params: any }) {
export default function WorkspaceProjectPage({ params }: { params: any }) {
const { workspace_slug, project_id, peekId } = params;

return <ProjectDetailsView workspaceSlug={workspace_slug} projectId={project_id} peekId={peekId} />;
Expand Down
22 changes: 21 additions & 1 deletion space/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { Metadata } from "next";
// styles
import "@/styles/globals.css";
// components
import { InstanceNotReady, InstanceFailureView } from "@/components/instance";
// helpers
import { ASSET_PREFIX } from "@/helpers/common.helper";
// lib
import { AppProvider } from "@/lib/app-providers";
// services
import { InstanceService } from "@/services/instance.service";

const instanceService = new InstanceService();

export const metadata: Metadata = {
title: "Plane Deploy | Make your Plane boards public with one-click",
Expand All @@ -20,6 +28,8 @@ export const metadata: Metadata = {
};

export default async function RootLayout({ children }: { children: React.ReactNode }) {
const instanceDetails = await instanceService.getInstanceInfo().catch(() => undefined);

return (
<html lang="en">
<head>
Expand All @@ -29,7 +39,17 @@ export default async function RootLayout({ children }: { children: React.ReactNo
<link rel="manifest" href={`${ASSET_PREFIX}/site.webmanifest.json`} />
<link rel="shortcut icon" href={`${ASSET_PREFIX}/favicon/favicon.ico`} />
</head>
<body>{children}</body>
<body>
<AppProvider initialState={{ instance: instanceDetails?.instance }}>
{!instanceDetails ? (
<InstanceFailureView />
) : (
<>{instanceDetails.instance.is_setup_done ? <>{children}</> : <InstanceNotReady />}</>
)}

{children}
</AppProvider>
</body>
</html>
);
}
37 changes: 11 additions & 26 deletions space/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
"use client";
import Image from "next/image";
import { useTheme } from "next-themes";
import { Button } from "@plane/ui";
// assets
import InstanceFailureDarkImage from "@/public/instance/instance-failure-dark.svg";
import InstanceFailureImage from "@/public/instance/instance-failure.svg";
import UserLoggedInImage from "public/user-logged-in.svg";

export default function InstanceNotFound() {
const { resolvedTheme } = useTheme();

const instanceImage = resolvedTheme === "dark" ? InstanceFailureDarkImage : InstanceFailureImage;

const handleRetry = () => {
window.location.reload();
};

return (
<div>
<div className="h-full w-full relative container px-5 mx-auto flex justify-center items-center mt-10">
<div className="w-auto max-w-2xl relative space-y-8 py-10">
<div className="relative flex flex-col justify-center items-center space-y-4">
<Image src={instanceImage} alt="Plane Logo" />
<h3 className="font-medium text-2xl text-white ">Unable to fetch instance details.</h3>
<p className="font-medium text-base text-center">
We were unable to fetch the details of the instance. <br />
Fret not, it might just be a connectivity issue.
</p>
</div>
<div className="flex justify-center">
<Button size="md" onClick={handleRetry}>
Retry
</Button>
<div className="flex h-screen w-screen flex-col">
<div className="grid h-full w-full place-items-center p-6">
<div className="text-center">
<div className="mx-auto grid h-52 w-52 place-items-center rounded-full bg-custom-background-80">
<div className="h-32 w-32">
<Image src={UserLoggedInImage} alt="User already logged in" />
</div>
</div>
<h1 className="mt-12 text-3xl font-semibold">Not Found</h1>
<p className="mt-4">Please enter the appropriate project URL to view the issue board.</p>
</div>
</div>
</div>
Expand Down
25 changes: 1 addition & 24 deletions space/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,20 @@
// components
import { UserLoggedIn } from "@/components/accounts";
import { InstanceNotReady, InstanceFailureView } from "@/components/instance";
import { AuthView } from "@/components/views";
// helpers
// import { EPageTypes } from "@/helpers/authentication.helper";
// import { useInstance, useUser } from "@/hooks/store";
// wrapper
// import { AuthWrapper } from "@/lib/wrappers";
// lib
import { AppProvider } from "@/lib/app-providers";
// services
import { InstanceService } from "@/services/instance.service";
import { UserService } from "@/services/user.service";

const userServices = new UserService();
const instanceService = new InstanceService();

export default async function HomePage() {
const instanceDetails = await instanceService.getInstanceInfo().catch(() => undefined);
const user = await userServices
.currentUser()
.then((user) => ({ ...user, isAuthenticated: true }))
.catch(() => ({ isAuthenticated: false }));

if (!instanceDetails) {
return <InstanceFailureView />;
}

if (!instanceDetails?.instance?.is_setup_done) {
<InstanceNotReady />;
}

if (user.isAuthenticated) {
return <UserLoggedIn />;
}

return (
<AppProvider initialState={{ instance: instanceDetails.instance }}>
<AuthView />
</AppProvider>
);
return <AuthView />;
}
7 changes: 4 additions & 3 deletions space/components/issues/board-views/kanban/header.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
"use client";
// mobx react lite
import { observer } from "mobx-react-lite";
// ui
import { StateGroupIcon } from "@plane/ui";
// constants
import { issueGroupFilter } from "@/constants/data";
// mobx hook
import { useIssue } from "@/hooks/store";
// import { useIssue } from "@/hooks/store";
// interfaces
import { IIssueState } from "@/types/issue";

export const IssueKanBanHeader = observer(({ state }: { state: IIssueState }) => {
const { getCountOfIssuesByState } = useIssue();
// const { getCountOfIssuesByState } = useIssue();
const stateGroup = issueGroupFilter(state.group);

if (stateGroup === null) return <></>;
Expand All @@ -21,7 +22,7 @@ export const IssueKanBanHeader = observer(({ state }: { state: IIssueState }) =>
<StateGroupIcon stateGroup={state.group} color={state.color} height="14" width="14" />
</div>
<div className="mr-1 truncate font-semibold capitalize text-custom-text-200">{state?.name}</div>
<span className="flex-shrink-0 rounded-full text-custom-text-300">{getCountOfIssuesByState(state.id)}</span>
{/* <span className="flex-shrink-0 rounded-full text-custom-text-300">{getCountOfIssuesByState(state.id)}</span> */}
</div>
);
});
1 change: 1 addition & 0 deletions space/components/issues/board-views/list/block.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import { FC } from "react";
import { observer } from "mobx-react-lite";
import { useParams, useRouter, useSearchParams } from "next/navigation";
Expand Down
8 changes: 5 additions & 3 deletions space/components/issues/board-views/list/header.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
"use client";
import { observer } from "mobx-react-lite";
// ui
import { StateGroupIcon } from "@plane/ui";
// constants
import { issueGroupFilter } from "@/constants/data";
// mobx hook
import { useIssue } from "@/hooks/store";
// import { useIssue } from "@/hooks/store";
// types
import { IIssueState } from "@/types/issue";

export const IssueListHeader = observer(({ state }: { state: IIssueState }) => {
const { getCountOfIssuesByState } = useIssue();
// const { getCountOfIssuesByState } = useIssue();
const stateGroup = issueGroupFilter(state.group);
// const count = getCountOfIssuesByState(state.id);

if (stateGroup === null) return <></>;

Expand All @@ -20,7 +22,7 @@ export const IssueListHeader = observer(({ state }: { state: IIssueState }) => {
<StateGroupIcon stateGroup={state.group} color={state.color} height="14" width="14" />
</div>
<div className="mr-1 font-medium capitalize">{state?.name}</div>
<div className="text-sm font-medium text-custom-text-200">{getCountOfIssuesByState(state.id)}</div>
{/* <div className="text-sm font-medium text-custom-text-200">{count}</div> */}
</div>
);
});
1 change: 1 addition & 0 deletions space/components/issues/board-views/list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"use client";
import { FC } from "react";
import { observer } from "mobx-react-lite";
// components
Expand Down
129 changes: 129 additions & 0 deletions space/components/issues/navbar/controls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
"use client";

import { useEffect, FC } from "react";
import Link from "next/link";
import { useRouter, useParams, useSearchParams, usePathname } from "next/navigation";
// ui
import { Avatar, Button } from "@plane/ui";
// components
import { IssueFiltersDropdown } from "@/components/issues/filters";
// hooks
import { useProject, useUser, useIssueFilter } from "@/hooks/store";
// types
import { TIssueBoardKeys } from "@/types/issue";
// components
import { NavbarIssueBoardView } from "./issue-board-view";
import { NavbarTheme } from "./theme";

export type NavbarControlsProps = {
workspaceSlug: string;
projectId: string;
projectSettings: any;
};

export const NavbarControls: FC<NavbarControlsProps> = (props) => {
const { workspaceSlug, projectId, projectSettings } = props;
const { views } = projectSettings;
// router
const router = useRouter();
const { board, labels, states, priorities, peekId } = useParams<any>();
const searchParams = useSearchParams();
const pathName = usePathname();
// store
const { updateFilters } = useIssueFilter();
const { settings, activeLayout, hydrate, setActiveLayout } = useProject();
hydrate(projectSettings);

const { data: user } = useUser();

useEffect(() => {
if (workspaceSlug && projectId && settings) {
const viewsAcceptable: string[] = [];
const currentBoard: TIssueBoardKeys | null = null;

if (settings?.views?.list) viewsAcceptable.push("list");
if (settings?.views?.kanban) viewsAcceptable.push("kanban");
if (settings?.views?.calendar) viewsAcceptable.push("calendar");
if (settings?.views?.gantt) viewsAcceptable.push("gantt");
if (settings?.views?.spreadsheet) viewsAcceptable.push("spreadsheet");

// if (board) {
// if (viewsAcceptable.includes(board.toString())) {
// currentBoard = board.toString() as TIssueBoardKeys;
// } else {
// if (viewsAcceptable && viewsAcceptable.length > 0) {
// currentBoard = viewsAcceptable[0] as TIssueBoardKeys;
// }
// }
// } else {
// if (viewsAcceptable && viewsAcceptable.length > 0) {
// currentBoard = viewsAcceptable[0] as TIssueBoardKeys;
// }
// }

if (currentBoard) {
if (activeLayout === null || activeLayout !== currentBoard) {
let params: any = { board: currentBoard };
if (peekId && peekId.length > 0) params = { ...params, peekId: peekId };
if (priorities && priorities.length > 0) params = { ...params, priorities: priorities };
if (states && states.length > 0) params = { ...params, states: states };
if (labels && labels.length > 0) params = { ...params, labels: labels };
console.log("params", params);
let storeParams: any = {};
if (priorities && priorities.length > 0) storeParams = { ...storeParams, priority: priorities.split(",") };
if (states && states.length > 0) storeParams = { ...storeParams, state: states.split(",") };
if (labels && labels.length > 0) storeParams = { ...storeParams, labels: labels.split(",") };

if (storeParams) updateFilters(projectId, storeParams);
setActiveLayout(currentBoard);
router.push(`/${workspaceSlug}/${projectId}?${searchParams}`);
}
}
}
}, [
board,
workspaceSlug,
projectId,
router,
updateFilters,
labels,
states,
priorities,
peekId,
settings,
activeLayout,
setActiveLayout,
searchParams,
]);
return (
<>
{/* issue views */}
<div className="relative flex flex-shrink-0 items-center gap-1 transition-all delay-150 ease-in-out">
<NavbarIssueBoardView layouts={views} />
</div>

{/* issue filters */}
<div className="relative flex flex-shrink-0 items-center gap-1 transition-all delay-150 ease-in-out">
<IssueFiltersDropdown workspaceSlug={workspaceSlug} projectId={projectId} />
</div>

{/* theming */}
<div className="relative flex-shrink-0">
<NavbarTheme />
</div>

{user?.id ? (
<div className="flex items-center gap-2 rounded border border-custom-border-200 p-2">
<Avatar name={user?.display_name} src={user?.avatar ?? undefined} shape="square" size="sm" />
<h6 className="text-xs font-medium">{user.display_name}</h6>
</div>
) : (
<div className="flex-shrink-0">
<Link href={`/?next_path=${pathName}`}>
<Button variant="outline-primary">Sign in</Button>
</Link>
</div>
)}
</>
);
};
Loading

0 comments on commit a2fbd61

Please sign in to comment.