mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: moving to pages dir and downgrading next to 12
This commit is contained in:
parent
96399c7112
commit
8cadced1aa
@ -1,64 +0,0 @@
|
||||
// next imports
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { Metadata, ResolvingMetadata } from "next";
|
||||
// components
|
||||
import IssueNavbar from "components/issues/navbar";
|
||||
import IssueFilter from "components/issues/filters-render";
|
||||
// service
|
||||
import ProjectService from "services/project.service";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
type LayoutProps = {
|
||||
params: { workspace_slug: string; project_slug: string };
|
||||
};
|
||||
|
||||
export async function generateMetadata({ params }: LayoutProps): Promise<Metadata> {
|
||||
// read route params
|
||||
const { workspace_slug, project_slug } = params;
|
||||
const projectServiceInstance = new ProjectService();
|
||||
|
||||
try {
|
||||
const project = await projectServiceInstance?.getProjectSettingsAsync(workspace_slug, project_slug);
|
||||
|
||||
return {
|
||||
title: `${project?.project_details?.name} | ${workspace_slug}`,
|
||||
description: `${
|
||||
project?.project_details?.description || `${project?.project_details?.name} | ${workspace_slug}`
|
||||
}`,
|
||||
icons: `data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>${
|
||||
typeof project?.project_details?.emoji != "object"
|
||||
? String.fromCodePoint(parseInt(project?.project_details?.emoji))
|
||||
: "✈️"
|
||||
}</text></svg>`,
|
||||
};
|
||||
} catch (error: any) {
|
||||
if (error?.data?.error) {
|
||||
redirect(`/project-not-published`);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
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-custom-border-300 relative flex items-center bga-white select-none">
|
||||
<IssueNavbar />
|
||||
</div>
|
||||
<IssueFilter />
|
||||
<div className="w-full h-full relative overflow-hidden">{children}</div>
|
||||
|
||||
<div className="absolute z-[99999] bottom-[10px] right-[10px] bg-custom-background-100 rounded-sm shadow-lg border border-custom-border-200">
|
||||
<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 text-custom-text-200">
|
||||
Powered by <b>Plane Deploy</b>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default RootLayout;
|
@ -1,31 +0,0 @@
|
||||
"use client";
|
||||
|
||||
// root styles
|
||||
import "styles/globals.css";
|
||||
|
||||
// next theme
|
||||
import { ThemeProvider } from "next-themes";
|
||||
|
||||
// toast alert
|
||||
import { ToastContextProvider } from "contexts/toast.context";
|
||||
|
||||
// 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" suppressHydrationWarning>
|
||||
<body className="antialiased bg-custom-background-90 w-100">
|
||||
<MobxStoreProvider>
|
||||
<MobxStoreInit />
|
||||
<ToastContextProvider>
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
<main>{children}</main>
|
||||
</ThemeProvider>
|
||||
</ToastContextProvider>
|
||||
</MobxStoreProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
export default RootLayout;
|
@ -1,171 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
// next
|
||||
import Image from "next/image";
|
||||
import Router from "next/router";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
|
||||
// assets
|
||||
import BluePlaneLogoWithoutText from "public/plane-logos/blue-without-text.png";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
// services
|
||||
import authenticationService from "services/authentication.service";
|
||||
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
// components
|
||||
import { EmailPasswordForm } from "./(auth)/components/email-password-form";
|
||||
import { GithubLoginButton } from "./(auth)/components/github-login-button";
|
||||
import { GoogleLoginButton } from "./(auth)/components/google-login";
|
||||
import { EmailCodeForm } from "./(auth)/components/email-code-form";
|
||||
|
||||
const HomePage = () => {
|
||||
const { user: userStore } = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const onSignInError = (error: any) => {
|
||||
setToastAlert({
|
||||
title: "Error signing in!",
|
||||
type: "error",
|
||||
message: error?.error || "Something went wrong. Please try again later or contact the support team.",
|
||||
});
|
||||
};
|
||||
|
||||
const onSignInSuccess = (response: any) => {
|
||||
const isOnboarded = response?.user?.onboarding_step?.profile_complete || false;
|
||||
const nextPath = searchParams?.get("next_path") || "/";
|
||||
|
||||
userStore.setCurrentUser(response?.user);
|
||||
|
||||
if (!isOnboarded) {
|
||||
router.push(`/onboarding?next_path=${nextPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
router.push(nextPath);
|
||||
};
|
||||
|
||||
const handleGoogleSignIn = async ({ clientId, credential }: any) => {
|
||||
try {
|
||||
if (clientId && credential) {
|
||||
const socialAuthPayload = {
|
||||
medium: "google",
|
||||
credential,
|
||||
clientId,
|
||||
};
|
||||
const response = await authenticationService.socialAuth(socialAuthPayload);
|
||||
|
||||
onSignInSuccess(response);
|
||||
} else {
|
||||
throw Error("Cant find credentials");
|
||||
}
|
||||
} catch (err: any) {
|
||||
onSignInError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleGitHubSignIn = async (credential: string) => {
|
||||
try {
|
||||
if (process.env.NEXT_PUBLIC_GITHUB_ID && credential) {
|
||||
const socialAuthPayload = {
|
||||
medium: "github",
|
||||
credential,
|
||||
clientId: process.env.NEXT_PUBLIC_GITHUB_ID,
|
||||
};
|
||||
const response = await authenticationService.socialAuth(socialAuthPayload);
|
||||
onSignInSuccess(response);
|
||||
} else {
|
||||
throw Error("Cant find credentials");
|
||||
}
|
||||
} catch (err: any) {
|
||||
onSignInError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handlePasswordSignIn = async (formData: any) => {
|
||||
await authenticationService
|
||||
.emailLogin(formData)
|
||||
.then((response) => {
|
||||
try {
|
||||
if (response) {
|
||||
onSignInSuccess(response);
|
||||
}
|
||||
} catch (err: any) {
|
||||
onSignInError(err);
|
||||
}
|
||||
})
|
||||
.catch((err) => onSignInError(err));
|
||||
};
|
||||
|
||||
const handleEmailCodeSignIn = async (response: any) => {
|
||||
try {
|
||||
if (response) {
|
||||
onSignInSuccess(response);
|
||||
}
|
||||
} catch (err: any) {
|
||||
onSignInError(err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-screen w-full overflow-hidden">
|
||||
<div className="hidden sm:block sm:fixed border-r-[0.5px] border-custom-border-200 h-screen w-[0.5px] top-0 left-20 lg:left-32" />
|
||||
<div className="fixed grid place-items-center bg-custom-background-100 sm:py-5 top-11 sm:top-12 left-7 sm:left-16 lg:left-28">
|
||||
<div className="grid place-items-center bg-custom-background-100">
|
||||
<div className="h-[30px] w-[30px]">
|
||||
<Image src={BluePlaneLogoWithoutText} alt="Plane Logo" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid place-items-center h-full overflow-y-auto py-5 px-7">
|
||||
<div>
|
||||
{parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0") ? (
|
||||
<>
|
||||
<h1 className="text-center text-2xl sm:text-2.5xl font-semibold text-custom-text-100">
|
||||
Sign in to Plane
|
||||
</h1>
|
||||
<div className="flex flex-col divide-y divide-custom-border-200">
|
||||
<div className="pb-7">
|
||||
<EmailCodeForm handleSignIn={handleEmailCodeSignIn} />
|
||||
</div>
|
||||
<div className="flex flex-col items-center justify-center gap-4 pt-7 sm:w-[360px] mx-auto overflow-hidden">
|
||||
<GoogleLoginButton handleSignIn={handleGoogleSignIn} />
|
||||
<GithubLoginButton handleSignIn={handleGitHubSignIn} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<EmailPasswordForm onSubmit={handlePasswordSignIn} />
|
||||
)}
|
||||
|
||||
{parseInt(process.env.NEXT_PUBLIC_ENABLE_OAUTH || "0") ? (
|
||||
<p className="pt-16 text-custom-text-200 text-sm text-center">
|
||||
By signing up, you agree to the{" "}
|
||||
<a
|
||||
href="https://plane.so/terms-and-conditions"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-medium underline"
|
||||
>
|
||||
Terms & Conditions
|
||||
</a>
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(HomePage);
|
@ -1,9 +1,7 @@
|
||||
import { useEffect, useState, FC } from "react";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// next-themes
|
||||
import { useTheme } from "next-themes";
|
||||
// images
|
||||
@ -18,9 +16,9 @@ export const GithubLoginButton: FC<GithubLoginButtonProps> = ({ handleSignIn })
|
||||
const [loginCallBackURL, setLoginCallBackURL] = useState(undefined);
|
||||
const [gitCode, setGitCode] = useState<null | string>(null);
|
||||
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
|
||||
const code = searchParams?.get("code");
|
||||
const { code } = router.query;
|
||||
|
||||
const { theme } = useTheme();
|
||||
|
@ -1,30 +1,20 @@
|
||||
import { useEffect, Fragment } from "react";
|
||||
|
||||
// next
|
||||
import { useSearchParams, useRouter } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// react-hook-form
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
// headless ui
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
|
||||
// icons
|
||||
import { ChevronDownIcon, CheckIcon } from "@heroicons/react/20/solid";
|
||||
|
||||
// constants
|
||||
import { USER_ROLES } from "constants/workspace";
|
||||
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
// services
|
||||
import UserService from "services/user.service";
|
||||
|
||||
// ui
|
||||
import { Input, PrimaryButton } from "components/ui";
|
||||
|
||||
@ -38,11 +28,11 @@ type Props = {
|
||||
user?: any;
|
||||
};
|
||||
|
||||
export const UserDetails: React.FC<Props> = observer(({ user }) => {
|
||||
export const OnBoardingForm: React.FC<Props> = observer(({ user }) => {
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const { next_path } = router.query;
|
||||
|
||||
const { user: userStore } = useMobxStore();
|
||||
|
||||
@ -71,10 +61,7 @@ export const UserDetails: React.FC<Props> = observer(({ user }) => {
|
||||
.updateMe(payload)
|
||||
.then((response) => {
|
||||
userStore.setCurrentUser(response);
|
||||
|
||||
const nextPath = searchParams?.get("next_path") || "/";
|
||||
router.push(nextPath);
|
||||
|
||||
router.push(next_path?.toString() || "/");
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
@ -16,9 +13,7 @@ const IssueFilter = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const clearAllFilters = () => {
|
||||
router.replace(
|
||||
|
@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
@ -13,9 +10,7 @@ export const RenderIssueLabel = observer(({ label }: { label: IIssueLabel }) =>
|
||||
const store = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const removeLabelFromFilter = () => {
|
||||
router.replace(
|
||||
|
@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
@ -16,9 +13,7 @@ const IssueLabelFilter = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const clearLabelFilters = () => {
|
||||
router.replace(
|
||||
|
@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
@ -13,10 +10,7 @@ export const RenderIssuePriority = observer(({ priority }: { priority: IIssuePri
|
||||
const store = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const removePriorityFromFilter = () => {
|
||||
router.replace(
|
||||
|
@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
@ -17,9 +14,7 @@ const IssuePriorityFilter = observer(() => {
|
||||
const store = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const clearPriorityFilters = () => {
|
||||
router.replace(
|
||||
|
@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
@ -15,9 +12,7 @@ export const RenderIssueState = observer(({ state }: { state: IIssueState }) =>
|
||||
const store = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const stateGroup = issueGroupFilter(state.group);
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
@ -16,9 +13,7 @@ const IssueStateFilter = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const clearStateFilters = () => {
|
||||
router.replace(
|
||||
|
@ -1,8 +1,4 @@
|
||||
"use client";
|
||||
|
||||
// next imports
|
||||
import { useRouter, useParams, useSearchParams } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// constants
|
||||
import { issueViews } from "constants/data";
|
||||
@ -16,9 +12,7 @@ export const NavbarIssueBoardView = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const handleCurrentBoardView = (boardView: TIssueBoardKeys) => {
|
||||
store?.issue?.setCurrentIssueBoardView(boardView);
|
||||
|
@ -1,18 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
|
||||
import { ChevronDownIcon } from "@heroicons/react/20/solid";
|
||||
|
||||
// mobx react lite
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// icons
|
||||
import { ChevronDownIcon } from "@heroicons/react/20/solid";
|
||||
// mobx
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
// components
|
||||
import { Dropdown } from "components/ui/dropdown";
|
||||
|
||||
// constants
|
||||
import { issueGroupFilter } from "constants/data";
|
||||
|
||||
@ -22,7 +16,7 @@ export const NavbarIssueFilter = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const pathName = usePathname();
|
||||
const pathName = router.asPath;
|
||||
|
||||
const handleOnSelect = (key: "states" | "labels" | "priorities", value: string) => {
|
||||
if (key === "states") {
|
||||
|
@ -1,22 +1,15 @@
|
||||
import React, { useRef } from "react";
|
||||
|
||||
import { useParams } from "next/navigation";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
// react-hook-form
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
|
||||
// lib
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
// ui
|
||||
import { SecondaryButton } from "components/ui";
|
||||
|
||||
// types
|
||||
import { Comment } from "store/types";
|
||||
|
||||
// components
|
||||
import Tiptap, { ITiptapRichTextEditor } from "components/tiptap";
|
||||
|
||||
@ -48,8 +41,8 @@ export const AddComment: React.FC<Props> = observer((props) => {
|
||||
reset,
|
||||
} = useForm<Comment>({ defaultValues });
|
||||
|
||||
const routerParams = useParams();
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const router = useRouter();
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const { issue: issueStore, user: userStore } = useMobxStore();
|
||||
|
||||
|
@ -1,25 +1,17 @@
|
||||
"use client";
|
||||
|
||||
// react
|
||||
import { useEffect } from "react";
|
||||
|
||||
// next
|
||||
import { useParams } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// lib
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
// helpers
|
||||
import { groupReactions, renderEmoji } from "helpers/emoji.helper";
|
||||
|
||||
// ui
|
||||
// components
|
||||
import { ReactionSelector } from "components/ui";
|
||||
|
||||
export const IssueEmojiReactions: React.FC = observer(() => {
|
||||
const routerParams = useParams();
|
||||
const router = useRouter();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const { user: userStore, issue: issueStore } = useMobxStore();
|
||||
|
||||
|
@ -1,21 +1,15 @@
|
||||
"use client";
|
||||
|
||||
// react
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
|
||||
// next
|
||||
import { useParams } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useRouter } from "next/router";
|
||||
// lib
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
export const IssueVotes: React.FC = observer(() => {
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
const routerParams = useParams();
|
||||
const router = useRouter();
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const { workspace_slug, project_slug } = router.query as { workspace_slug: string; project_slug: string };
|
||||
|
||||
const { user: userStore, issue: issueStore } = useMobxStore();
|
||||
|
||||
|
31
apps/space/layouts/project-layout.tsx
Normal file
31
apps/space/layouts/project-layout.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
// components
|
||||
import IssueNavbar from "components/issues/navbar";
|
||||
|
||||
type LayoutProps = {
|
||||
params: { workspace_slug: string; project_slug: string };
|
||||
};
|
||||
|
||||
const ProjectLayout = ({ 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="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">
|
||||
<a 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>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default ProjectLayout;
|
@ -2,7 +2,7 @@
|
||||
|
||||
import { useEffect } from "react";
|
||||
// next imports
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useRouter } from "next/router";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
@ -10,8 +10,8 @@ import { RootStore } from "store/root";
|
||||
const MobxStoreInit = () => {
|
||||
const store: RootStore = useMobxStore();
|
||||
|
||||
// search params
|
||||
const routerSearchparams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const { states, labels, priorities } = router.query as { states: string[]; labels: string[]; priorities: string[] };
|
||||
|
||||
useEffect(() => {
|
||||
// theme
|
||||
@ -21,16 +21,10 @@ const MobxStoreInit = () => {
|
||||
}, [store?.theme]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!routerSearchparams) return;
|
||||
|
||||
const states = routerSearchparams.get("states");
|
||||
const labels = routerSearchparams.get("labels");
|
||||
const priorities = routerSearchparams.get("priorities");
|
||||
|
||||
store.issue.userSelectedLabels = labels?.split(",") || [];
|
||||
store.issue.userSelectedPriorities = priorities?.split(",") || [];
|
||||
store.issue.userSelectedStates = states?.split(",") || [];
|
||||
}, [routerSearchparams, store.issue]);
|
||||
store.issue.userSelectedLabels = labels || [];
|
||||
store.issue.userSelectedPriorities = priorities || [];
|
||||
store.issue.userSelectedStates = states || [];
|
||||
}, [store.issue]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
@ -6,7 +6,6 @@ const nextConfig = {
|
||||
swcMinify: true,
|
||||
experimental: {
|
||||
outputFileTracingRoot: path.join(__dirname, "../../"),
|
||||
appDir: true,
|
||||
},
|
||||
output: "standalone",
|
||||
};
|
||||
|
@ -10,17 +10,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.7.13",
|
||||
"@types/node": "18.14.1",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/react": "18.0.28",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"axios": "^1.3.4",
|
||||
"eslint": "8.34.0",
|
||||
"eslint-config-next": "13.2.1",
|
||||
"js-cookie": "^3.0.1",
|
||||
"mobx": "^6.10.0",
|
||||
"mobx-react-lite": "^4.0.3",
|
||||
"next": "^13.4.16",
|
||||
"next": "12.3.2",
|
||||
"next-theme": "^0.1.5",
|
||||
"nprogress": "^0.2.0",
|
||||
"react": "^18.2.0",
|
||||
@ -31,8 +25,14 @@
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@types/js-cookie": "^3.0.3",
|
||||
"@types/node": "18.14.1",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/react": "18.0.28",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "8.34.0",
|
||||
"eslint-config-next": "13.2.1",
|
||||
"postcss": "^8.4.21",
|
||||
"tailwindcss": "^3.2.7"
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
// next imports
|
||||
import { useRouter, useParams, useSearchParams } from "next/navigation";
|
||||
import { useRouter } from "next/router";
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
@ -17,26 +14,23 @@ import { RootStore } from "store/root";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// types
|
||||
import { TIssueBoardKeys } from "store/types";
|
||||
import ProjectLayout from "layouts/project-layout";
|
||||
|
||||
const WorkspaceProjectPage = () => {
|
||||
const store: RootStore = useMobxStore();
|
||||
|
||||
const router = useRouter();
|
||||
const routerParams = useParams();
|
||||
const routerSearchparams = useSearchParams();
|
||||
|
||||
const activeIssueId = store.issue.activePeekOverviewIssueId;
|
||||
|
||||
const { workspace_slug, project_slug } = routerParams as { workspace_slug: string; project_slug: string };
|
||||
const board =
|
||||
routerSearchparams &&
|
||||
routerSearchparams.get("board") != null &&
|
||||
(routerSearchparams.get("board") as TIssueBoardKeys | "");
|
||||
|
||||
const states = routerSearchparams && routerSearchparams.get("states") != null && routerSearchparams.get("states");
|
||||
const labels = routerSearchparams && routerSearchparams.get("labels") != null && routerSearchparams.get("labels");
|
||||
const priorities =
|
||||
routerSearchparams && routerSearchparams.get("priorities") != null && routerSearchparams.get("priorities");
|
||||
const { workspace_slug, project_slug, board, states, labels, priorities } = router.query as {
|
||||
workspace_slug: string;
|
||||
project_slug: string;
|
||||
board: TIssueBoardKeys;
|
||||
states: string[];
|
||||
labels: string[];
|
||||
priorities: string[];
|
||||
};
|
||||
|
||||
// updating default board view when we are in the issues page
|
||||
useEffect(() => {
|
||||
@ -114,46 +108,48 @@ const WorkspaceProjectPage = () => {
|
||||
}, [workspace_slug, project_slug, store?.project, store?.issue, states, labels, priorities]);
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-full overflow-hidden">
|
||||
<IssuePeekOverview
|
||||
isOpen={Boolean(activeIssueId)}
|
||||
onClose={() => store.issue.setActivePeekOverviewIssueId(null)}
|
||||
issue={store?.issue?.issues?.find((_issue) => _issue.id === activeIssueId) || null}
|
||||
workspaceSlug={workspace_slug}
|
||||
/>
|
||||
<ProjectLayout>
|
||||
<div className="relative w-full h-full overflow-hidden">
|
||||
<IssuePeekOverview
|
||||
isOpen={Boolean(activeIssueId)}
|
||||
onClose={() => store.issue.setActivePeekOverviewIssueId(null)}
|
||||
issue={store?.issue?.issues?.find((_issue) => _issue.id === activeIssueId) || null}
|
||||
workspaceSlug={workspace_slug}
|
||||
/>
|
||||
|
||||
{store?.issue?.loader && !store.issue.issues ? (
|
||||
<div className="text-sm text-center py-10 text-custom-text-100">Loading...</div>
|
||||
) : (
|
||||
<>
|
||||
{store?.issue?.error ? (
|
||||
<div className="text-sm text-center py-10 bg-custom-background-200 text-custom-text-100">
|
||||
Something went wrong.
|
||||
</div>
|
||||
) : (
|
||||
store?.issue?.currentIssueBoardView && (
|
||||
<>
|
||||
{store?.issue?.currentIssueBoardView === "list" && (
|
||||
<div className="relative w-full h-full overflow-y-auto">
|
||||
<div className="mx-auto px-4">
|
||||
<IssueListView />
|
||||
{store?.issue?.loader && !store.issue.issues ? (
|
||||
<div className="text-sm text-center py-10 text-custom-text-100">Loading...</div>
|
||||
) : (
|
||||
<>
|
||||
{store?.issue?.error ? (
|
||||
<div className="text-sm text-center py-10 bg-custom-background-200 text-custom-text-100">
|
||||
Something went wrong.
|
||||
</div>
|
||||
) : (
|
||||
store?.issue?.currentIssueBoardView && (
|
||||
<>
|
||||
{store?.issue?.currentIssueBoardView === "list" && (
|
||||
<div className="relative w-full h-full overflow-y-auto">
|
||||
<div className="mx-auto px-4">
|
||||
<IssueListView />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{store?.issue?.currentIssueBoardView === "kanban" && (
|
||||
<div className="relative w-full h-full mx-auto px-9 py-5">
|
||||
<IssueKanbanView />
|
||||
</div>
|
||||
)}
|
||||
{store?.issue?.currentIssueBoardView === "calendar" && <IssueCalendarView />}
|
||||
{store?.issue?.currentIssueBoardView === "spreadsheet" && <IssueSpreadsheetView />}
|
||||
{store?.issue?.currentIssueBoardView === "gantt" && <IssueGanttView />}
|
||||
</>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{store?.issue?.currentIssueBoardView === "kanban" && (
|
||||
<div className="relative w-full h-full mx-auto px-9 py-5">
|
||||
<IssueKanbanView />
|
||||
</div>
|
||||
)}
|
||||
{store?.issue?.currentIssueBoardView === "calendar" && <IssueCalendarView />}
|
||||
{store?.issue?.currentIssueBoardView === "spreadsheet" && <IssueSpreadsheetView />}
|
||||
{store?.issue?.currentIssueBoardView === "gantt" && <IssueGanttView />}
|
||||
</>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</ProjectLayout>
|
||||
);
|
||||
};
|
||||
|
@ -1,10 +1,24 @@
|
||||
import type { AppProps } from "next/app";
|
||||
import { ThemeProvider } from "next-themes";
|
||||
// styles
|
||||
import "styles/globals.css";
|
||||
// types
|
||||
import type { AppProps } from "next/app";
|
||||
// contexts
|
||||
import { ToastContextProvider } from "contexts/toast.context";
|
||||
// mobx store provider
|
||||
import { MobxStoreProvider } from "lib/mobx/store-provider";
|
||||
import MobxStoreInit from "lib/mobx/store-init";
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
return <Component {...pageProps} />;
|
||||
return (
|
||||
<MobxStoreProvider>
|
||||
<MobxStoreInit />
|
||||
<ToastContextProvider>
|
||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||
<Component {...pageProps} />
|
||||
</ThemeProvider>
|
||||
</ToastContextProvider>
|
||||
</MobxStoreProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default MyApp;
|
||||
|
@ -5,7 +5,7 @@ class MyDocument extends Document {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<body>
|
||||
<body className="antialiased bg-custom-background-90 w-100">
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
|
7
apps/space/pages/index.tsx
Normal file
7
apps/space/pages/index.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
const HomePage = () => (
|
||||
<div className="relative w-screen h-screen flex justify-center items-center text-5xl">Plane Deploy</div>
|
||||
);
|
||||
|
||||
export default HomePage;
|
@ -1,28 +1,19 @@
|
||||
"use client";
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
// next
|
||||
import Image from "next/image";
|
||||
|
||||
// assets
|
||||
import BluePlaneLogoWithoutText from "public/plane-logos/blue-without-text.png";
|
||||
import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
// services
|
||||
import authenticationService from "services/authentication.service";
|
||||
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
// components
|
||||
import { UserDetails } from "./components/user-details";
|
||||
import { OnBoardingForm } from "components/accounts/onboarding-form";
|
||||
|
||||
const HomePage = () => {
|
||||
const OnBoardingPage = () => {
|
||||
const { user: userStore } = useMobxStore();
|
||||
|
||||
const user = userStore?.currentUser;
|
||||
@ -52,11 +43,11 @@ const HomePage = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative flex justify-center sm:items-center h-full px-8 pb-0 sm:px-0 sm:py-12 sm:pr-[8.33%] sm:w-10/12 md:w-9/12 lg:w-4/5 overflow-hidden">
|
||||
<UserDetails user={user} />
|
||||
<OnBoardingForm user={user} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(HomePage);
|
||||
export default observer(OnBoardingPage);
|
@ -1,5 +1,3 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// service
|
||||
|
Loading…
Reference in New Issue
Block a user