feat: app dir migration (#4743)

* feat: creating new app dir structure for web app

* fix: moving few pages to app dir

* fix: adding profile settings layout

* fix: errors on app dir.

* chore: remove pages routes.

* chore: add sign-in/ sign-up, invitations, onboarding pages.

* [WEB-1374] fix: clear changes made on modal close (#4555)

* [WEB-1480] fix: preserve page access when making a copy (#4568)

* [WEB-1465] fix: theme fluctuation on initial load. (#4638)

* [WEB-1445] fix: issue creation on sub groups when cycle/ module grouping is applied. (#4636)

* [WEB-1244] fix: add better image insertion and replacement logic in the editor (#4508)

* fix: add better image insertion and replacement logic

* refactor: image handling in editor

* chore: remove passing uploadKey around

* refactor: remove unused code

* fix: redundant files removed

* fix: add is editor ready to discard api to control behvaiours from our app

* fix: focus issues and image insertion position when not using slash command

* fix: import order fixed

* fix: notification mark all as read (#4643)

* chore: remove enter key extension (#4648)

* [WEB-1467] chore: run the API's required to bootstrap the application in parallel. (#4642)

* [WEB - 1482] fix: uploads when using block storages other than s3 and minio (#4647)

* fix: minio storage and redirection

* dev: disconnect web url and app base url configuration.

* fix: negate check while trying to discard (#4653)

* fix: email notification preferences (#4656)

* [WEB-1493] chore: product tour asset and app sidebar quick action hover (#4655)

* chore: product tour asset updated

* fix: app sidebar quick action hover

* fix: project state setting state name remove camel case logic (#4652)

* [WEB-1419] chore: enable module creation with dates older than today. (#4659)

* [WEB-1216] chore: increase module empty state for consistency. (#4658)

* fix: build errors

* [WEB-1235] chore: module and cycle sidebar graph improvement (#4650)

* chore: module and cycle sidebar graph improvement

* chore: code refactor

* [WEB-1424] chore: page and view logo implementation, and emoji/icon (#4662)

* [WEB-1424] chore: page and view logo implementation, and emoji/icon picker improvement (#4583)

* chore: added logo_props

* chore: logo props in cycles, views and modules

* chore: emoji icon picker types updated

* chore: info icon added to plane ui package

* chore: icon color adjust helper function added

* style: icon picker ui improvement and default color options updated

* chore: update page logo action added in store

* chore: emoji code to unicode helper function added

* chore: common logo renderer component added

* chore: app header project logo updated

* chore: project logo updated across platform

* chore: page logo picker added

* chore: control link component improvement

* chore: list item improvement

* chore: emoji picker component updated

* chore: space app and package logo prop type updated

* chore: migration

* chore: logo added to project view

* chore: page logo picker added in create modal and breadcrumbs

* chore: view logo picker added in create modal and updated breadcrumbs

* fix: build error

* chore: AIO docker images for preview deployments (#4605)

* fix: adding single docker base file

* action added

* fix action

* dockerfile.base modified

* action fix

* dockerfile

* fix: base aio dockerfile

* fix: dockerfile.base

* fix: dockerfile base

* fix: modified folder structure

* fix: action

* fix: dockerfile

* fix: dockerfile.base

* fix: supervisor file name changed

* fix: base dockerfile updated

* fix dockerfile base

* fix: base dockerfile

* fix: docker files

* fix: base dockerfile

* update base image

* modified docker aio base

* aio base modified to debian-12-slim

* fixes

* finalize the dockerfiles with volume exposure

* modified the aio build and dockerfile

* fix: codacy suggestions implemented

* fix: codacy fix

* update aio build action

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>

* fix: merge conflict

* chore: lucide react added to planu ui package

* chore: new emoji picker component added with lucid icon and code refactor

* chore: logo component updated

* chore: emoji picker updated for pages and views

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: Manish Gupta <59428681+mguptahub@users.noreply.github.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>

* fix: build error

---------

Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: Manish Gupta <59428681+mguptahub@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>

* refactor: drag handle component (#4663)

* refactor: checkbox ui component (#4665)

* [WEB-1325] chore: refactor inbox issue store to avoid data loss. (#4640)

* [WEB-1325] chore: refactor inbox issue store to avoid data loss.

* chore: inbox store improvement.

* chore: priority dropdown accepts undefined (#4666)

* chore: added buttonClassName prop to label dropdown (#4671)

* chore: created new constants for marketing website page links (#4670)

* chore: added a prop to render default state conditionally (#4669)

* [WEB-1501] dev: multiple select core components (#4667)

* dev: multiple select core components

* chore: added export statement

* chore: created a new constant for archivable state groups (#4668)

* chore: added primary variant to the alert modal (#4664)

* [WEB-1436] chore: pages improvement. (#4657)

* add empty state if no pages are available.
* set access to private in create page modal when the modal is open form private tab.

* [WEB-1440] chore: update cycle empty state to use project level access. (#4672)

* fix: checkbox ui component (#4675)

* fix: ai buttons overlapping issue (#4621)

* [WEB - 1500] chore: add extra fields on instance and create changelog table to store release change logs (#4673)

* chore: add extra fields on instance and create changelog table to store release change logs

* dev: rename new_version to latest_version

* [WEB - 1505] chore: alter instance id field (#4676)

* chore: instance id

* dev: update to max length

* feat: creating new app dir structure for web app

* fix: moving few pages to app dir

* feat: creating new app dir structure for web app

* fix: moving few pages to app dir

* fix: errors on app dir.

* chore: remove pages routes.

* chore: add sign-in/ sign-up, invitations, onboarding pages.

* fix: instance serializer

* fix: instance register script  (#4681)

* fix: instance register script

* dev: remove api key and add latest version and current version in types

* [WEB-1492] fix: resolved issue creation error in layouts while group_by and sub_group_by filters applied in quick add (#4682)

* fix: resolved issue creation error in layouts while group_by and sub_group_by filters applied in quick add

* fix: updated braces in conditions

* fix: inbox issue store update logic. (#4683)

* chore: update package version

* [WEB-1184] feat: issue bulk operations (#4674)

* feat: issue bulk operations

* style: bulk operations action bar

* chore: remove edition separation

* style: fix overlapping of response container in AI popover. (#4684)

* [WEB-1498] style: fix comments reaction alignment. (#4686)

* [WEB-1503] chore: add `autofocus` to name field in inline create/ update state component. (#4685)

* [WEB-1312] fix: trim file name before uploading (#4661)

* fix: trim file name before uploading

* fix: check the cursor position before inserting image

* dev: add trimming for file assets

* dev: add filename validation above if

* dev: make the validation to 50 to support user uploads

---------

Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>

* [WEB-1481] fix: multiple API calls in inbox issues on closed issues tab. (#4691)

* fix: multiple API calls on scroll and closed issues tab.

* fix: pagination loader on initial load.

* feat: Add components required for estimates (#4690)

* Add sortable, radio and typography components

* Remove stray css classes

* Prevent drag of items from other draggable

* Minor cleanup

* Update yarn.lock

* Remove radio input component as it was build on
headless ui v2.0.0 and now we are using v1.7.0

* Fix build errors

* Update dependencies in use memo.

* [WEB-1521] chore: add configuration to enable/disable sign-ups. (#4697)

* fix: regenerating lock file

* fix: docker image build errors

* fix: remove `setupInterceptors` to avoid circular dependency.

* chore: migrate all `accounts` related routes.

* chore: migrate all `profiles` related routes.

* chore: workspace invitation and onboarding migration / fixes.

* chore: installation provider migrations.

* regression: focus changing issue with the peek overview editor (#4700)

* [WEB-1459] chore: save users all / favorite project list collapse state into localstorage. (#4701)

* [WEB-1501] chore: update selected entity details on entities list change (#4702)

* chore: update selected entity detials on entities list change

* chore: addd selectionHelpers as a prop

* [WEB-1517] chore: remove drag handle from list drag block (#4698)

* remove drag handle from list drag block

* align list group header with list item

* rearrange chevron for list subissues and rearrange spaces

* adding default draggable property to control link

* remove unnecessary dependencies for useEffect

* fix: email validation  (#4707)

* fix: email validation on complete login or sign up functionality

* dev: add try catch block

* dev: split up code

* dev: empty return

* fix: cache invalidation on new members invite (#4699)

* fix: build test pull request running on non draft PRs (#4708)

* fix: cache invalidation on new members invite (#4699)

* fix: add version max length (#4713)

* chore: migrations for `routing` hooks.

* [WEB-1533] chore: fix alignment issues in List and Spreadsheet view (#4714)

* fix alignment issues in List and Spreadsheet view

* fix spreadsheet indentation

* chore: migration for workspace dashboard/ views/ analytics/ settings and active-cycles.

* chore: handle undefined identifier case

* fix: Overflowing loader in issue edit modal (#4720)

* [WEB-1529] chore: workspace sidebar updates. (#4710)

* fix: temporary fix exiting lines with slashes (#4725)

* [WEB-1537] fix: inline code block size fixed for headers, etc (#4709)

* fix: inline code block size fixed for headers, etc

* feat: persisting focus accurately post converting the code block into text

* fix: typo in error handling

* [WEB-1526] feat: add auto merge behaviour to task lists and fix infinite backspace case (#4703)

* feat: add auto merge behaviour to task lists

* fix: unhandled cases for taskItem and taskList

* fix: css task list such that toggling task list doesn't shift things

* fix: task list jumps around while trying create/delete things in between two task lists

* fix: remove filtering for generic transactions i.e. transactions with some meta data while tying to join things

* chore: migration for profile activity along with headers refactor.

* [WEB-1201] dev: dropdowns (#4721)

* chore: lodash package added

* chore: dropdown key down hook added

* dev: dropdown component

* chore: build error and code refactor

* chore: readme file updated

* chore: added disabled prop to multiple select components (#4724)

* chore: added disabled prop to mutliple select group hoc

* style: fix empty space

* fix: don't add  as a sub-issue if parent has been removed (#4731)

* fix: member list item custom menu placement (#4729)

* [WEB-1535] chore: project logo picker improvement (#4718)

* chore: emoji icon picker improvement

* chore: emoji icon picker improvement

* fix: resolved border flicker on issue title (#4727)

* chore: profile activity empty state added (#4732)

* [WEB-1481] fix: inbox issue list update after changing issue status. (#4715)

* style: fix ux copy style on project feature preview page. (#4734)

* chore: remove clear seleciton logic on escape key press (#4735)

* chore: migrations for projects and project issues.

* chore: issue and properties filter dropdown improvement (#4733)

* save all filters and properties for views (#4728)

* chore: migrations for issue details route.

* chore: migration for cycle routes.

* chore: migration for module routes.

* chore: migrations for project views routes.

* chore: migrations for project pages routes.

* chore: migration for project inbox routes.

* chore: migration for project settings routes.

* chore: migrations for draft issues routes.

* chore: migrations for project archives routes.

* chore: remove unused headers.

* temp: comment out auth constant and use-reload-confirmation code to avoid errors.

---------

Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
Co-authored-by: rahulramesha <71900764+rahulramesha@users.noreply.github.com>
Co-authored-by: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com>
Co-authored-by: M. Palanikannan <73993394+Palanikannan1437@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Co-authored-by: Nikhil <118773738+pablohashescobar@users.noreply.github.com>
Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: Manish Gupta <59428681+mguptahub@users.noreply.github.com>
Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>
Co-authored-by: guru_sainath <gurusainath007@gmail.com>
Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
Co-authored-by: Henit Chobisa <chobisa.henit@gmail.com>
Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
This commit is contained in:
sriram veeraghanta 2024-06-10 12:37:38 +05:30 committed by GitHub
parent 59fdd611e4
commit 5d807db69e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
417 changed files with 5196 additions and 3918 deletions

View File

@ -1,5 +1,6 @@
import { ReactNode } from "react";
import Link from "next/link";
// import Link from "next/link";
// import { EAuthenticationErrorCodes } from "@/helpers/authentication.helper";
export enum EPageTypes {
PUBLIC = "PUBLIC",
@ -41,7 +42,7 @@ export enum EAuthErrorCodes {
// Password strength
INVALID_PASSWORD = "5020",
// Sign Up
USER_ACCOUNT_DEACTIVATED = "5019",
// USER_ACCOUNT_DEACTIVATED = "5019",
USER_ALREADY_EXIST = "5030",
AUTHENTICATION_FAILED_SIGN_UP = "5035",
REQUIRED_EMAIL_PASSWORD_SIGN_UP = "5040",
@ -91,281 +92,281 @@ export type TAuthErrorInfo = {
message: ReactNode;
};
const errorCodeMessages: {
[key in EAuthErrorCodes]: { title: string; message: (email?: string | undefined) => ReactNode };
} = {
// global
[EAuthErrorCodes.INSTANCE_NOT_CONFIGURED]: {
title: `Instance not configured`,
message: () => `Instance not configured. Please contact your administrator.`,
},
[EAuthErrorCodes.SIGNUP_DISABLED]: {
title: `Sign up disabled`,
message: () => `Sign up disabled. Please contact your administrator.`,
},
[EAuthErrorCodes.INVALID_PASSWORD]: {
title: `Invalid password`,
message: () => `Invalid password. Please try again.`,
},
[EAuthErrorCodes.SMTP_NOT_CONFIGURED]: {
title: `SMTP not configured`,
message: () => `SMTP not configured. Please contact your administrator.`,
},
// const errorCodeMessages: {
// [key in EAuthErrorCodes]: { title: string; message: (email?: string | undefined) => ReactNode };
// } = {
// // global
// [EAuthErrorCodes.INSTANCE_NOT_CONFIGURED]: {
// title: `Instance not configured`,
// message: () => `Instance not configured. Please contact your administrator.`,
// },
// [EAuthErrorCodes.SIGNUP_DISABLED]: {
// title: `Sign up disabled`,
// message: () => `Sign up disabled. Please contact your administrator.`,
// },
// [EAuthErrorCodes.INVALID_PASSWORD]: {
// title: `Invalid password`,
// message: () => `Invalid password. Please try again.`,
// },
// [EAuthErrorCodes.SMTP_NOT_CONFIGURED]: {
// title: `SMTP not configured`,
// message: () => `SMTP not configured. Please contact your administrator.`,
// },
// email check in both sign up and sign in
[EAuthErrorCodes.INVALID_EMAIL]: {
title: `Invalid email`,
message: () => `Invalid email. Please try again.`,
},
[EAuthenticationErrorCodes.EMAIL_REQUIRED]: {
title: `Email required`,
message: () => `Email required. Please try again.`,
},
// [EAuthErrorCodes.INVALID_EMAIL]: {
// title: `Invalid email`,
// message: () => `Invalid email. Please try again.`,
// },
// [EAuthenticationErrorCodes.EMAIL_REQUIRED]: {
// title: `Email required`,
// message: () => `Email required. Please try again.`,
// },
// sign up
[EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
title: `User already exists`,
message: (email = undefined) => (
<div>
Your account is already registered.&nbsp;
<Link
className="underline underline-offset-4 font-medium hover:font-bold transition-all"
href={`/sign-in${email ? `?email=${encodeURIComponent(email)}` : ``}`}
>
Sign In
</Link>
&nbsp;now.
</div>
),
},
[EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP]: {
title: `Email and password required`,
message: () => `Email and password required. Please try again.`,
},
[EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP]: {
title: `Authentication failed`,
message: () => `Authentication failed. Please try again.`,
},
[EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP]: {
title: `Invalid email`,
message: () => `Invalid email. Please try again.`,
},
[EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED]: {
title: `Email and code required`,
message: () => `Email and code required. Please try again.`,
},
[EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP]: {
title: `Invalid email`,
message: () => `Invalid email. Please try again.`,
},
// // sign up
// [EAuthenticationErrorCodes.USER_ALREADY_EXIST]: {
// title: `User already exists`,
// message: (email = undefined) => (
// <div>
// Your account is already registered.&nbsp;
// <Link
// className="underline underline-offset-4 font-medium hover:font-bold transition-all"
// href={`/sign-in${email ? `?email=${encodeURIComponent(email)}` : ``}`}
// >
// Sign In
// </Link>
// &nbsp;now.
// </div>
// ),
// },
// [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP]: {
// title: `Email and password required`,
// message: () => `Email and password required. Please try again.`,
// },
// [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP]: {
// title: `Authentication failed`,
// message: () => `Authentication failed. Please try again.`,
// },
// [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP]: {
// title: `Invalid email`,
// message: () => `Invalid email. Please try again.`,
// },
// [EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED]: {
// title: `Email and code required`,
// message: () => `Email and code required. Please try again.`,
// },
// [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP]: {
// title: `Invalid email`,
// message: () => `Invalid email. Please try again.`,
// },
// sign in
[EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED]: {
title: `User account deactivated`,
message: () => <div>Your account is deactivated. Contact support@plane.so.</div>,
},
[EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
title: `User does not exist`,
message: (email = undefined) => (
<div>
No account found.&nbsp;
<Link
className="underline underline-offset-4 font-medium hover:font-bold transition-all"
href={`/${email ? `?email=${encodeURIComponent(email)}` : ``}`}
>
Create one
</Link>
&nbsp;to get started.
</div>
),
},
[EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN]: {
title: `Email and password required`,
message: () => `Email and password required. Please try again.`,
},
[EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN]: {
title: `Authentication failed`,
message: () => `Authentication failed. Please try again.`,
},
[EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN]: {
title: `Invalid email`,
message: () => `Invalid email. Please try again.`,
},
[EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED]: {
title: `Email and code required`,
message: () => `Email and code required. Please try again.`,
},
[EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN]: {
title: `Invalid email`,
message: () => `Invalid email. Please try again.`,
},
// // sign in
// [EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED]: {
// title: `User account deactivated`,
// message: () => <div>Your account is deactivated. Contact support@plane.so.</div>,
// },
// [EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
// title: `User does not exist`,
// message: (email = undefined) => (
// <div>
// No account found.&nbsp;
// <Link
// className="underline underline-offset-4 font-medium hover:font-bold transition-all"
// href={`/${email ? `?email=${encodeURIComponent(email)}` : ``}`}
// >
// Create one
// </Link>
// &nbsp;to get started.
// </div>
// ),
// },
// [EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN]: {
// title: `Email and password required`,
// message: () => `Email and password required. Please try again.`,
// },
// [EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN]: {
// title: `Authentication failed`,
// message: () => `Authentication failed. Please try again.`,
// },
// [EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN]: {
// title: `Invalid email`,
// message: () => `Invalid email. Please try again.`,
// },
// [EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED]: {
// title: `Email and code required`,
// message: () => `Email and code required. Please try again.`,
// },
// [EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN]: {
// title: `Invalid email`,
// message: () => `Invalid email. Please try again.`,
// },
// Both Sign in and Sign up
[EAuthenticationErrorCodes.INVALID_MAGIC_CODE]: {
title: `Authentication failed`,
message: () => `Invalid magic code. Please try again.`,
},
[EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE]: {
title: `Expired magic code`,
message: () => `Expired magic code. Please try again.`,
},
[EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED]: {
title: `Expired magic code`,
message: () => `Expired magic code. Please try again.`,
},
// // Both Sign in and Sign up
// [EAuthenticationErrorCodes.INVALID_MAGIC_CODE]: {
// title: `Authentication failed`,
// message: () => `Invalid magic code. Please try again.`,
// },
// [EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE]: {
// title: `Expired magic code`,
// message: () => `Expired magic code. Please try again.`,
// },
// [EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED]: {
// title: `Expired magic code`,
// message: () => `Expired magic code. Please try again.`,
// },
// Oauth
[EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED]: {
title: `Google not configured`,
message: () => `Google not configured. Please contact your administrator.`,
},
[EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED]: {
title: `GitHub not configured`,
message: () => `GitHub not configured. Please contact your administrator.`,
},
[EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR]: {
title: `Google OAuth provider error`,
message: () => `Google OAuth provider error. Please try again.`,
},
[EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR]: {
title: `GitHub OAuth provider error`,
message: () => `GitHub OAuth provider error. Please try again.`,
},
// // Oauth
// [EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED]: {
// title: `Google not configured`,
// message: () => `Google not configured. Please contact your administrator.`,
// },
// [EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED]: {
// title: `GitHub not configured`,
// message: () => `GitHub not configured. Please contact your administrator.`,
// },
// [EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR]: {
// title: `Google OAuth provider error`,
// message: () => `Google OAuth provider error. Please try again.`,
// },
// [EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR]: {
// title: `GitHub OAuth provider error`,
// message: () => `GitHub OAuth provider error. Please try again.`,
// },
// Reset Password
[EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN]: {
title: `Invalid password token`,
message: () => `Invalid password token. Please try again.`,
},
[EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN]: {
title: `Expired password token`,
message: () => `Expired password token. Please try again.`,
},
// // Reset Password
// [EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN]: {
// title: `Invalid password token`,
// message: () => `Invalid password token. Please try again.`,
// },
// [EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN]: {
// title: `Expired password token`,
// message: () => `Expired password token. Please try again.`,
// },
// Change password
// // Change password
[EAuthenticationErrorCodes.MISSING_PASSWORD]: {
title: `Password required`,
message: () => `Password required. Please try again.`,
},
[EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD]: {
title: `Incorrect old password`,
message: () => `Incorrect old password. Please try again.`,
},
[EAuthenticationErrorCodes.INVALID_NEW_PASSWORD]: {
title: `Invalid new password`,
message: () => `Invalid new password. Please try again.`,
},
// [EAuthenticationErrorCodes.MISSING_PASSWORD]: {
// title: `Password required`,
// message: () => `Password required. Please try again.`,
// },
// [EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD]: {
// title: `Incorrect old password`,
// message: () => `Incorrect old password. Please try again.`,
// },
// [EAuthenticationErrorCodes.INVALID_NEW_PASSWORD]: {
// title: `Invalid new password`,
// message: () => `Invalid new password. Please try again.`,
// },
// set password
[EAuthenticationErrorCodes.PASSWORD_ALREADY_SET]: {
title: `Password already set`,
message: () => `Password already set. Please try again.`,
},
// // set password
// [EAuthenticationErrorCodes.PASSWORD_ALREADY_SET]: {
// title: `Password already set`,
// message: () => `Password already set. Please try again.`,
// },
// admin
[EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
title: `Admin already exists`,
message: () => `Admin already exists. Please try again.`,
},
[EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME]: {
title: `Email, password and first name required`,
message: () => `Email, password and first name required. Please try again.`,
},
[EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL]: {
title: `Invalid admin email`,
message: () => `Invalid admin email. Please try again.`,
},
[EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD]: {
title: `Invalid admin password`,
message: () => `Invalid admin password. Please try again.`,
},
[EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD]: {
title: `Email and password required`,
message: () => `Email and password required. Please try again.`,
},
[EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED]: {
title: `Authentication failed`,
message: () => `Authentication failed. Please try again.`,
},
[EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST]: {
title: `Admin user already exists`,
message: () => (
<div>
Admin user already exists.&nbsp;
<Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
Sign In
</Link>
&nbsp;now.
</div>
),
},
[EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST]: {
title: `Admin user does not exist`,
message: () => (
<div>
Admin user does not exist.&nbsp;
<Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
Sign In
</Link>
&nbsp;now.
</div>
),
},
};
// // admin
// [EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST]: {
// title: `Admin already exists`,
// message: () => `Admin already exists. Please try again.`,
// },
// [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME]: {
// title: `Email, password and first name required`,
// message: () => `Email, password and first name required. Please try again.`,
// },
// [EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL]: {
// title: `Invalid admin email`,
// message: () => `Invalid admin email. Please try again.`,
// },
// [EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD]: {
// title: `Invalid admin password`,
// message: () => `Invalid admin password. Please try again.`,
// },
// [EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD]: {
// title: `Email and password required`,
// message: () => `Email and password required. Please try again.`,
// },
// [EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED]: {
// title: `Authentication failed`,
// message: () => `Authentication failed. Please try again.`,
// },
// [EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST]: {
// title: `Admin user already exists`,
// message: () => (
// <div>
// Admin user already exists.&nbsp;
// <Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
// Sign In
// </Link>
// &nbsp;now.
// </div>
// ),
// },
// [EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST]: {
// title: `Admin user does not exist`,
// message: () => (
// <div>
// Admin user does not exist.&nbsp;
// <Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
// Sign In
// </Link>
// &nbsp;now.
// </div>
// ),
// },
// };
export const authErrorHandler = (
errorCode: EAuthenticationErrorCodes,
email?: string | undefined
): TAuthErrorInfo | undefined => {
const bannerAlertErrorCodes = [
EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED,
EAuthenticationErrorCodes.INVALID_EMAIL,
EAuthenticationErrorCodes.EMAIL_REQUIRED,
EAuthenticationErrorCodes.SIGNUP_DISABLED,
EAuthenticationErrorCodes.INVALID_PASSWORD,
EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED,
EAuthenticationErrorCodes.USER_ALREADY_EXIST,
EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP,
EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP,
EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP,
EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP,
EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED,
EAuthenticationErrorCodes.USER_DOES_NOT_EXIST,
EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN,
EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN,
EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN,
EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN,
EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED,
EAuthenticationErrorCodes.INVALID_MAGIC_CODE,
EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE,
EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED,
EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED,
EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED,
EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR,
EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR,
EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN,
EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN,
EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD,
EAuthenticationErrorCodes.INVALID_NEW_PASSWORD,
EAuthenticationErrorCodes.PASSWORD_ALREADY_SET,
EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST,
EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL,
EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD,
EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD,
EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED,
EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST,
EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST,
];
// export const authErrorHandler = (
// errorCode: EAuthenticationErrorCodes,
// email?: string | undefined
// ): TAuthErrorInfo | undefined => {
// const bannerAlertErrorCodes = [
// EAuthenticationErrorCodes.INSTANCE_NOT_CONFIGURED,
// EAuthenticationErrorCodes.INVALID_EMAIL,
// EAuthenticationErrorCodes.EMAIL_REQUIRED,
// EAuthenticationErrorCodes.SIGNUP_DISABLED,
// EAuthenticationErrorCodes.INVALID_PASSWORD,
// EAuthenticationErrorCodes.SMTP_NOT_CONFIGURED,
// EAuthenticationErrorCodes.USER_ALREADY_EXIST,
// EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_UP,
// EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_UP,
// EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_UP,
// EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_UP,
// EAuthenticationErrorCodes.MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED,
// EAuthenticationErrorCodes.USER_DOES_NOT_EXIST,
// EAuthenticationErrorCodes.AUTHENTICATION_FAILED_SIGN_IN,
// EAuthenticationErrorCodes.REQUIRED_EMAIL_PASSWORD_SIGN_IN,
// EAuthenticationErrorCodes.INVALID_EMAIL_SIGN_IN,
// EAuthenticationErrorCodes.INVALID_EMAIL_MAGIC_SIGN_IN,
// EAuthenticationErrorCodes.MAGIC_SIGN_IN_EMAIL_CODE_REQUIRED,
// // EAuthenticationErrorCodes.INVALID_MAGIC_CODE,
// // EAuthenticationErrorCodes.EXPIRED_MAGIC_CODE,
// // EAuthenticationErrorCodes.EMAIL_CODE_ATTEMPT_EXHAUSTED,
// EAuthenticationErrorCodes.GOOGLE_NOT_CONFIGURED,
// EAuthenticationErrorCodes.GITHUB_NOT_CONFIGURED,
// EAuthenticationErrorCodes.GOOGLE_OAUTH_PROVIDER_ERROR,
// EAuthenticationErrorCodes.GITHUB_OAUTH_PROVIDER_ERROR,
// EAuthenticationErrorCodes.INVALID_PASSWORD_TOKEN,
// EAuthenticationErrorCodes.EXPIRED_PASSWORD_TOKEN,
// EAuthenticationErrorCodes.INCORRECT_OLD_PASSWORD,
// EAuthenticationErrorCodes.INVALID_NEW_PASSWORD,
// EAuthenticationErrorCodes.PASSWORD_ALREADY_SET,
// EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST,
// EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
// EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL,
// EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD,
// EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD,
// EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED,
// EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST,
// EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST,
// ];
if (bannerAlertErrorCodes.includes(errorCode))
return {
type: EErrorAlertType.BANNER_ALERT,
code: errorCode,
title: errorCodeMessages[errorCode]?.title || "Error",
message: errorCodeMessages[errorCode]?.message(email) || "Something went wrong. Please try again.",
};
// if (bannerAlertErrorCodes.includes(errorCode))
// return {
// type: EErrorAlertType.BANNER_ALERT,
// code: errorCode,
// title: errorCodeMessages[errorCode]?.title || "Error",
// message: errorCodeMessages[errorCode]?.message(email) || "Something went wrong. Please try again.",
// };
return undefined;
};
// return undefined;
// };

View File

@ -8,6 +8,7 @@ module.exports = {
content: {
relative: true,
files: [
"./app/**/*.{js,ts,jsx,tsx}",
"./components/**/*.tsx",
"./constants/**/*.{js,ts,jsx,tsx}",
"./layouts/**/*.tsx",

View File

@ -1,5 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react";
import React from "react";
import { Draggable } from "./draggable";
import { Sortable } from "./sortable";
const meta: Meta<typeof Sortable> = {
@ -12,7 +13,7 @@ type Story = StoryObj<typeof Sortable>;
const data = [
{ id: "1", name: "John Doe" },
{ id: "2", name: "Satish" },
{ id: "2", name: "Jane Doe 2" },
{ id: "3", name: "Alice" },
{ id: "4", name: "Bob" },
{ id: "5", name: "Charlie" },

42
space/types/project.d.ts vendored Normal file
View File

@ -0,0 +1,42 @@
import { TLogoProps } from "@plane/types";
export type TWorkspaceDetails = {
name: string;
slug: string;
id: string;
};
export type TViewDetails = {
list: boolean;
gantt: boolean;
kanban: boolean;
calendar: boolean;
spreadsheet: boolean;
};
export type TProjectDetails = {
id: string;
identifier: string;
name: string;
cover_image: string | undefined;
logo_props: TLogoProps;
description: string;
};
export type TProjectSettings = {
id: string;
anchor: string;
comments: boolean;
reactions: boolean;
votes: boolean;
inbox: unknown;
workspace: string;
workspace_detail: TWorkspaceDetails;
project: string;
project_details: TProjectDetails;
views: TViewDetails;
created_by: string;
updated_by: string;
created_at: string;
updated_at: string;
};

View File

@ -1,3 +1,5 @@
"use client";
import { observer } from "mobx-react";
// ui
import { Crown } from "lucide-react";
@ -5,7 +7,7 @@ import { Breadcrumbs, ContrastIcon } from "@plane/ui";
import { BreadcrumbLink } from "@/components/common";
// icons
export const WorkspaceActiveCycleHeader = observer(() => (
const WorkspaceActiveCycleHeader = observer(() => (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<div className="flex items-center gap-2">
@ -25,3 +27,5 @@ export const WorkspaceActiveCycleHeader = observer(() => (
</div>
</div>
));
export default WorkspaceActiveCycleHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "../../app-header-wrapper";
import WorkspaceActiveCycleHeader from "./header";
const WorkspaceActiveCycleHeaderPage = () => <AppHeaderWrapper header={<WorkspaceActiveCycleHeader />} />;
export default WorkspaceActiveCycleHeaderPage;

View File

@ -1,17 +1,22 @@
"use client";
import { useEffect } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useSearchParams } from "next/navigation";
// icons
import { BarChart2, PanelRight } from "lucide-react";
// ui
import { Breadcrumbs } from "@plane/ui";
// components
import { BreadcrumbLink } from "@/components/common";
// helpers
import { cn } from "@/helpers/common.helper";
// hooks
import { useAppTheme } from "@/hooks/store";
export const WorkspaceAnalyticsHeader = observer(() => {
const router = useRouter();
const { analytics_tab } = router.query;
const WorkspaceAnalyticsHeader = observer(() => {
const searchParams = useSearchParams();
const analytics_tab = searchParams.get("analytics_tab");
// store hooks
const { workspaceAnalyticsSidebarCollapsed, toggleWorkspaceAnalyticsSidebar } = useAppTheme();
@ -66,3 +71,5 @@ export const WorkspaceAnalyticsHeader = observer(() => {
</>
);
});
export default WorkspaceAnalyticsHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "../../app-header-wrapper";
import WorkspaceAnalyticsHeader from "./header";
const WorkspaceAnalyticsHeaderPage = () => <AppHeaderWrapper header={<WorkspaceAnalyticsHeader />} />;
export default WorkspaceAnalyticsHeaderPage;

View File

@ -1,18 +1,21 @@
"use client";
import Image from "next/image";
import { useTheme } from "next-themes";
import { Home, Zap } from "lucide-react";
// images
import githubBlackImage from "/public/logos/github-black.png";
import githubWhiteImage from "/public/logos/github-white.png";
// hooks
// components
// ui
import { Breadcrumbs } from "@plane/ui";
// components
import { BreadcrumbLink } from "@/components/common";
// constants
import { CHANGELOG_REDIRECTED, GITHUB_REDIRECTED } from "@/constants/event-tracker";
// hooks
import { useEventTracker } from "@/hooks/store";
export const WorkspaceDashboardHeader = () => {
const WorkspaceDashboardHeader = () => {
// hooks
const { captureEvent } = useEventTracker();
const { resolvedTheme } = useTheme();
@ -69,3 +72,5 @@ export const WorkspaceDashboardHeader = () => {
</>
);
};
export default WorkspaceDashboardHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "../app-header-wrapper";
import WorkspaceDashboardHeader from "./header";
const WorkspaceDashboardHeaderPage = () => <AppHeaderWrapper header={<WorkspaceDashboardHeader />} />;
export default WorkspaceDashboardHeaderPage;

View File

@ -0,0 +1,8 @@
"use client";
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import UserProfileHeader from "../header";
const ProfileActivityHeader = () => <AppHeaderWrapper header={<UserProfileHeader type="Activity" />} />;
export default ProfileActivityHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import UserProfileHeader from "../header";
import ProfileIssuesMobileHeader from "../mobile-header";
const ProfileAssignedHeader = () => (
<AppHeaderWrapper header={<UserProfileHeader type="Assigned" />} mobileHeader={<ProfileIssuesMobileHeader />} />
);
export default ProfileAssignedHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import UserProfileHeader from "../header";
import ProfileIssuesMobileHeader from "../mobile-header";
const ProfileCreatedHeader = () => (
<AppHeaderWrapper header={<UserProfileHeader type="Created" />} mobileHeader={<ProfileIssuesMobileHeader />} />
);
export default ProfileCreatedHeader;

View File

@ -1,8 +1,10 @@
"use client";
// ui
import { FC } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
import { ChevronDown, PanelRight } from "lucide-react";
import { Breadcrumbs, CustomMenu } from "@plane/ui";
import { BreadcrumbLink } from "@/components/common";
@ -15,11 +17,10 @@ type TUserProfileHeader = {
type?: string | undefined;
};
export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
const { type = undefined } = props;
// router
const router = useRouter();
const { workspaceSlug, userId } = router.query;
const { workspaceSlug, userId } = useParams();
// store hooks
const { toggleProfileSidebar, profileSidebarCollapsed } = useAppTheme();
const {
@ -89,3 +90,5 @@ export const UserProfileHeader: FC<TUserProfileHeader> = observer((props) => {
</div>
);
});
export default UserProfileHeader;

View File

@ -1,6 +1,8 @@
"use client";
import { useCallback } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// icons
import { ChevronDown } from "lucide-react";
// types
@ -18,8 +20,7 @@ import { useIssues, useLabel } from "@/hooks/store";
const ProfileIssuesMobileHeader = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, userId } = router.query;
const { workspaceSlug, userId } = useParams();
// store hook
const {
issuesFilter: { issueFilters, updateFilters },

View File

@ -0,0 +1,8 @@
"use client";
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import UserProfileHeader from "./header";
const ProfileOverviewHeader = () => <AppHeaderWrapper header={<UserProfileHeader type="Summary" />} />;
export default ProfileOverviewHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import UserProfileHeader from "../header";
import ProfileIssuesMobileHeader from "../mobile-header";
const ProfileSubscribedHeader = () => (
<AppHeaderWrapper header={<UserProfileHeader type="Subscribed" />} mobileHeader={<ProfileIssuesMobileHeader />} />
);
export default ProfileSubscribedHeader;

View File

@ -0,0 +1,2 @@
import DefaultProjectArchivesHeader from "../page";
export default DefaultProjectArchivesHeader;

View File

@ -1,6 +1,6 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { useParams, usePathname, useRouter } from "next/navigation";
// ui
import { ArchiveIcon, Breadcrumbs, Tooltip } from "@plane/ui";
// components
@ -12,11 +12,12 @@ import { EIssuesStoreType } from "@/constants/issue";
import { useIssues, useProject } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
export const ProjectArchivesHeader: FC = observer(() => {
const ProjectArchivesHeader: FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const activeTab = router.pathname.split("/").pop();
const { workspaceSlug, projectId } = useParams();
const pathname = usePathname();
const activeTab = pathname.split("/").pop();
// store hooks
const {
issuesFilter: { issueFilters },
@ -93,3 +94,5 @@ export const ProjectArchivesHeader: FC = observer(() => {
</div>
);
});
export default ProjectArchivesHeader;

View File

@ -1,27 +1,23 @@
import { FC } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
import useSWR from "swr";
// hooks
import { ArchiveIcon, Breadcrumbs, LayersIcon } from "@plane/ui";
import { BreadcrumbLink, Logo } from "@/components/common";
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
import { useProject } from "@/hooks/store";
// components
// ui
// types
import { IssueArchiveService } from "@/services/issue";
// constants
// services
// helpers
import { ArchiveIcon, Breadcrumbs, LayersIcon } from "@plane/ui";
// components
import { BreadcrumbLink, Logo } from "@/components/common";
// constants
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
// hooks
import { useProject } from "@/hooks/store";
// services
import { IssueArchiveService } from "@/services/issue";
const issueArchiveService = new IssueArchiveService();
export const ProjectArchivedIssueDetailsHeader: FC = observer(() => {
const ProjectArchivedIssueDetailsHeader: FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, archivedIssueId } = router.query;
const { workspaceSlug, projectId, archivedIssueId } = useParams();
// store hooks
const { currentProjectDetails } = useProject();
@ -96,3 +92,5 @@ export const ProjectArchivedIssueDetailsHeader: FC = observer(() => {
</div>
);
});
export default ProjectArchivedIssueDetailsHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectArchivedIssueDetailsHeader from "./header";
const ProjectArchivedIssueDetailsHeaderPage = () => <AppHeaderWrapper header={<ProjectArchivedIssueDetailsHeader />} />;
export default ProjectArchivedIssueDetailsHeaderPage;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectArchivesHeader from "./header";
const ProjectArchivesHeaderPage = () => <AppHeaderWrapper header={<ProjectArchivesHeader />} />;
export default ProjectArchivesHeaderPage;

View File

@ -1,7 +1,7 @@
import { useCallback, useState } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
// icons
import { ArrowRight, PanelRight } from "lucide-react";
// types
@ -36,8 +36,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
const CycleDropdownOption: React.FC<{ cycleId: string }> = ({ cycleId }) => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store hooks
const { getCycleById } = useCycle();
// derived values
@ -56,12 +55,12 @@ const CycleDropdownOption: React.FC<{ cycleId: string }> = ({ cycleId }) => {
);
};
export const CycleIssuesHeader: React.FC = observer(() => {
const CycleIssuesHeader: React.FC = observer(() => {
// states
const [analyticsModal, setAnalyticsModal] = useState(false);
// router
const router = useRouter();
const { workspaceSlug, projectId, cycleId } = router.query as {
const { workspaceSlug, projectId, cycleId } = useParams() as {
workspaceSlug: string;
projectId: string;
cycleId: string;
@ -206,9 +205,8 @@ export const CycleIssuesHeader: React.FC = observer(() => {
{issuesCount && issuesCount > 0 ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`There are ${issuesCount} ${
issuesCount > 1 ? "issues" : "issue"
} in this cycle`}
tooltipContent={`There are ${issuesCount} ${issuesCount > 1 ? "issues" : "issue"
} in this cycle`}
position="bottom"
>
<span className="flex flex-shrink-0 cursor-default items-center justify-center rounded-xl bg-custom-primary-100/20 px-2 text-center text-xs font-semibold text-custom-primary-100">
@ -303,3 +301,5 @@ export const CycleIssuesHeader: React.FC = observer(() => {
</>
);
});
export default CycleIssuesHeader;

View File

@ -1,5 +1,5 @@
import { useCallback, useState } from "react";
import router from "next/router";
import { useParams } from "next/navigation";
// icons
import { Calendar, ChevronDown, Kanban, List } from "lucide-react";
// types
@ -16,7 +16,7 @@ import { calculateTotalFilters } from "@/helpers/filter.helper";
// hooks
import { useIssues, useCycle, useProjectState, useLabel, useMember, useProject } from "@/hooks/store";
export const CycleMobileHeader = () => {
const CycleIssuesMobileHeader = () => {
const [analyticsModal, setAnalyticsModal] = useState(false);
const { getCycleById } = useCycle();
const layouts = [
@ -25,7 +25,7 @@ export const CycleMobileHeader = () => {
{ key: "calendar", title: "Calendar", icon: Calendar },
];
const { workspaceSlug, projectId, cycleId } = router.query;
const { workspaceSlug, projectId, cycleId } = useParams();
const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined;
// store hooks
const { currentProjectDetails } = useProject();
@ -202,3 +202,5 @@ export const CycleMobileHeader = () => {
</>
);
};
export default CycleIssuesMobileHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import CycleIssuesHeader from "./header";
import CycleIssuesMobileHeader from "./mobile-header";
const CycleIssuesHeaderPage = () => (
<AppHeaderWrapper header={<CycleIssuesHeader />} mobileHeader={<CycleIssuesMobileHeader />} />
);
export default CycleIssuesHeaderPage;

View File

@ -1,6 +1,6 @@
import { FC } from "react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
// ui
import { Breadcrumbs, Button, ContrastIcon } from "@plane/ui";
// components
@ -11,10 +11,10 @@ import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useCommandPalette, useEventTracker, useProject, useUser } from "@/hooks/store";
export const CyclesHeader: FC = observer(() => {
const CyclesHeader: FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug } = router.query;
const { workspaceSlug } = useParams();
// store hooks
const { toggleCreateCycleModal } = useCommandPalette();
const { setTrackElement } = useEventTracker();
@ -72,3 +72,5 @@ export const CyclesHeader: FC = observer(() => {
</div>
);
});
export default CyclesHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import CyclesHeader from "./header";
import CyclesListMobileHeader from "./mobile-header";
const CyclesHeaderPage = () => (
<AppHeaderWrapper header={<CyclesHeader />} mobileHeader={<CyclesListMobileHeader />} />
);
export default CyclesHeaderPage;

View File

@ -1,6 +1,6 @@
import { FC, useCallback } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// types
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types";
// ui
@ -16,10 +16,9 @@ import { calculateTotalFilters } from "@/helpers/filter.helper";
import { useIssues, useLabel, useMember, useProject, useProjectState } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
export const ProjectDraftIssueHeader: FC = observer(() => {
const ProjectDraftIssueHeader: FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string };
// store hooks
const {
issuesFilter: { issueFilters, updateFilters },
@ -168,3 +167,5 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
</div>
);
});
export default ProjectDraftIssueHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectDraftIssueHeader from "./header";
const ProjectDraftIssueHeaderPage = () => <AppHeaderWrapper header={<ProjectDraftIssueHeader />} />;
export default ProjectDraftIssueHeaderPage;

View File

@ -1,6 +1,6 @@
import { FC, useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
import { RefreshCcw } from "lucide-react";
// ui
import { Breadcrumbs, Button, LayersIcon } from "@plane/ui";
@ -10,12 +10,11 @@ import { InboxIssueCreateEditModalRoot } from "@/components/inbox";
// hooks
import { useProject, useProjectInbox } from "@/hooks/store";
export const ProjectInboxHeader: FC = observer(() => {
const ProjectInboxHeader: FC = observer(() => {
// states
const [createIssueModal, setCreateIssueModal] = useState(false);
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store hooks
const { currentProjectDetails } = useProject();
const { loader } = useProjectInbox();
@ -77,3 +76,5 @@ export const ProjectInboxHeader: FC = observer(() => {
</div>
);
});
export default ProjectInboxHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectInboxHeader from "./header";
const ProjectInboxHeaderPage = () => <AppHeaderWrapper header={<ProjectInboxHeader />} />;
export default ProjectInboxHeaderPage;

View File

@ -1,22 +1,20 @@
import { FC } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
// hooks
import { useParams, useRouter } from "next/navigation";
import { PanelRight } from "lucide-react";
import { Breadcrumbs, LayersIcon } from "@plane/ui";
import { BreadcrumbLink, Logo } from "@/components/common";
import { cn } from "@/helpers/common.helper";
import { useAppTheme, useIssueDetail, useProject } from "@/hooks/store";
// ui
// helpers
// services
// constants
import { Breadcrumbs, LayersIcon } from "@plane/ui";
// components
import { BreadcrumbLink, Logo } from "@/components/common";
// helpers
import { cn } from "@/helpers/common.helper";
// hooks
import { useAppTheme, useIssueDetail, useProject } from "@/hooks/store";
export const ProjectIssueDetailsHeader: FC = observer(() => {
const ProjectIssueDetailsHeader: FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, issueId } = router.query;
const { workspaceSlug, projectId, issueId } = useParams();
// store hooks
const { currentProjectDetails } = useProject();
const { issueDetailSidebarCollapsed, toggleIssueDetailSidebar } = useAppTheme();
@ -83,3 +81,5 @@ export const ProjectIssueDetailsHeader: FC = observer(() => {
</div>
);
});
export default ProjectIssueDetailsHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectIssueDetailsHeader from "./header";
const ProjectIssueDetailsHeaderPage = () => <AppHeaderWrapper header={<ProjectIssueDetailsHeader />} />;
export default ProjectIssueDetailsHeaderPage;

View File

@ -1,6 +1,6 @@
import { useCallback, useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
// icons
import { Briefcase, Circle, ExternalLink } from "lucide-react";
// types
@ -30,12 +30,12 @@ import {
import { useIssues } from "@/hooks/store/use-issues";
import { usePlatformOS } from "@/hooks/use-platform-os";
export const ProjectIssuesHeader: React.FC = observer(() => {
const ProjectIssuesHeader: React.FC = observer(() => {
// states
const [analyticsModal, setAnalyticsModal] = useState(false);
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
const { workspaceSlug, projectId } = useParams() as { workspaceSlug: string; projectId: string };
// store hooks
const {
project: { projectMemberIds },
@ -234,3 +234,5 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
</>
);
});
export default ProjectIssuesHeader;

View File

@ -1,6 +1,6 @@
import { useCallback, useState } from "react";
import { observer } from "mobx-react";
import router from "next/router";
import { useParams } from "next/navigation";
// icons
import { Calendar, ChevronDown, Kanban, List } from "lucide-react";
// types
@ -17,14 +17,14 @@ import { calculateTotalFilters } from "@/helpers/filter.helper";
// hooks
import { useIssues, useLabel, useMember, useProject, useProjectState } from "@/hooks/store";
export const IssuesMobileHeader = observer(() => {
const ProjectIssuesMobileHeader = observer(() => {
const layouts = [
{ key: "list", title: "List", icon: List },
{ key: "kanban", title: "Kanban", icon: Kanban },
{ key: "calendar", title: "Calendar", icon: Calendar },
];
const [analyticsModal, setAnalyticsModal] = useState(false);
const { workspaceSlug, projectId } = router.query as {
const { workspaceSlug, projectId } = useParams() as {
workspaceSlug: string;
projectId: string;
};
@ -180,3 +180,5 @@ export const IssuesMobileHeader = observer(() => {
</>
);
});
export default ProjectIssuesMobileHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectIssuesHeader from "./header";
import ProjectIssuesMobileHeader from "./mobile-header";
const ProjectIssuesHeaderPage = () => (
<AppHeaderWrapper header={<ProjectIssuesHeader />} mobileHeader={<ProjectIssuesMobileHeader />} />
);
export default ProjectIssuesHeaderPage;

View File

@ -1,7 +1,7 @@
import { useCallback, useState } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
// icons
import { ArrowRight, PanelRight } from "lucide-react";
// types
@ -37,8 +37,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
const ModuleDropdownOption: React.FC<{ moduleId: string }> = ({ moduleId }) => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store hooks
const { getModuleById } = useModule();
// derived values
@ -59,12 +58,12 @@ const ModuleDropdownOption: React.FC<{ moduleId: string }> = ({ moduleId }) => {
);
};
export const ModuleIssuesHeader: React.FC = observer(() => {
const ModuleIssuesHeader: React.FC = observer(() => {
// states
const [analyticsModal, setAnalyticsModal] = useState(false);
// router
const router = useRouter();
const { workspaceSlug, projectId, moduleId } = router.query;
const { workspaceSlug, projectId, moduleId } = useParams();
// hooks
const { isMobile } = usePlatformOS();
// store hooks
@ -206,9 +205,8 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
{issuesCount && issuesCount > 0 ? (
<Tooltip
isMobile={isMobile}
tooltipContent={`There are ${issuesCount} ${
issuesCount > 1 ? "issues" : "issue"
} in this module`}
tooltipContent={`There are ${issuesCount} ${issuesCount > 1 ? "issues" : "issue"
} in this module`}
position="bottom"
>
<span className="flex flex-shrink-0 cursor-default items-center justify-center rounded-xl bg-custom-primary-100/20 px-2 text-center text-xs font-semibold text-custom-primary-100">
@ -310,3 +308,5 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
</>
);
});
export default ModuleIssuesHeader;

View File

@ -1,6 +1,6 @@
import { useCallback, useState } from "react";
import { observer } from "mobx-react";
import router from "next/router";
import { useParams } from "next/navigation";
// icons
import { Calendar, ChevronDown, Kanban, List } from "lucide-react";
// types
@ -17,7 +17,7 @@ import { calculateTotalFilters } from "@/helpers/filter.helper";
// hooks
import { useIssues, useLabel, useMember, useModule, useProject, useProjectState } from "@/hooks/store";
export const ModuleMobileHeader = observer(() => {
const ModuleIssuesMobileHeader = observer(() => {
const [analyticsModal, setAnalyticsModal] = useState(false);
const { currentProjectDetails } = useProject();
const { getModuleById } = useModule();
@ -26,7 +26,7 @@ export const ModuleMobileHeader = observer(() => {
{ key: "kanban", title: "Kanban", icon: Kanban },
{ key: "calendar", title: "Calendar", icon: Calendar },
];
const { workspaceSlug, projectId, moduleId } = router.query as {
const { workspaceSlug, projectId, moduleId } = useParams() as {
workspaceSlug: string;
projectId: string;
moduleId: string;
@ -183,3 +183,5 @@ export const ModuleMobileHeader = observer(() => {
</div>
);
});
export default ModuleIssuesMobileHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ModuleIssuesHeader from "./header";
import ModuleIssuesMobileHeader from "./mobile-header";
const ModuleIssuesHeaderPage = () => (
<AppHeaderWrapper header={<ModuleIssuesHeader />} mobileHeader={<ModuleIssuesMobileHeader />} />
);
export default ModuleIssuesHeaderPage;

View File

@ -1,5 +1,5 @@
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
// ui
import { Breadcrumbs, Button, DiceIcon } from "@plane/ui";
// components
@ -10,10 +10,10 @@ import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useCommandPalette, useEventTracker, useProject, useUser } from "@/hooks/store";
export const ModulesListHeader: React.FC = observer(() => {
const ModulesListHeader: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug } = router.query;
const { workspaceSlug } = useParams();
// store hooks
const { toggleCreateModuleModal } = useCommandPalette();
const { setTrackElement } = useEventTracker();
@ -72,3 +72,5 @@ export const ModulesListHeader: React.FC = observer(() => {
</div>
);
});
export default ModulesListHeader;

View File

@ -0,0 +1,12 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ModulesListHeader from "./header";
import ModulesListMobileHeader from "./mobile-header";
const ModulesHeaderPage = () => (
<AppHeaderWrapper header={<ModulesListHeader />} mobileHeader={<ModulesListMobileHeader />} />
);
export default ModulesHeaderPage;

View File

@ -0,0 +1,170 @@
import { useState } from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { FileText } from "lucide-react";
// types
import { TLogoProps } from "@plane/types";
// ui
import { Breadcrumbs, Button, EmojiIconPicker, EmojiIconPickerTypes, TOAST_TYPE, setToast } from "@plane/ui";
// components
import { BreadcrumbLink, Logo } from "@/components/common";
// helper
import { convertHexEmojiToDecimal } from "@/helpers/emoji.helper";
// hooks
import { usePage, useProject } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
export interface IPagesHeaderProps {
showButton?: boolean;
}
const PageDetailsHeader = observer(() => {
// router
const { workspaceSlug, pageId } = useParams();
// state
const [isOpen, setIsOpen] = useState(false);
// store hooks
const { currentProjectDetails } = useProject();
const { isContentEditable, isSubmitting, name, logo_props, updatePageLogo } = usePage(pageId?.toString() ?? "");
const handlePageLogoUpdate = async (data: TLogoProps) => {
if (data) {
updatePageLogo(data)
.then(() => {
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Success!",
message: "Logo Updated successfully.",
});
})
.catch(() => {
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: "Something went wrong. Please try again.",
});
});
}
};
// use platform
const { platform } = usePlatformOS();
// derived values
const isMac = platform === "MacOS";
return (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"
link={
<span>
<span className="hidden md:block">
<BreadcrumbLink
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`}
label={currentProjectDetails?.name ?? "Project"}
icon={
currentProjectDetails && (
<span className="grid h-4 w-4 flex-shrink-0 place-items-center">
<Logo logo={currentProjectDetails?.logo_props} size={16} />
</span>
)
}
/>
</span>
<span className="md:hidden">
<BreadcrumbLink
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`}
label={"..."}
/>
</span>
</span>
}
/>
<Breadcrumbs.BreadcrumbItem
type="text"
link={
<BreadcrumbLink
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/pages`}
label="Pages"
icon={<FileText className="h-4 w-4 text-custom-text-300" />}
/>
}
/>
<Breadcrumbs.BreadcrumbItem
type="text"
link={
<BreadcrumbLink
label={name ?? "Page"}
icon={
<EmojiIconPicker
isOpen={isOpen}
handleToggle={(val: boolean) => setIsOpen(val)}
className="flex items-center justify-center"
buttonClassName="flex items-center justify-center"
label={
<>
{logo_props?.in_use ? (
<Logo logo={logo_props} size={16} type="lucide" />
) : (
<FileText className="h-4 w-4 text-custom-text-300" />
)}
</>
}
onChange={(val) => {
let logoValue = {};
if (val?.type === "emoji")
logoValue = {
value: convertHexEmojiToDecimal(val.value.unified),
url: val.value.imageUrl,
};
else if (val?.type === "icon") logoValue = val.value;
handlePageLogoUpdate({
in_use: val?.type,
[val?.type]: logoValue,
}).finally(() => setIsOpen(false));
}}
defaultIconColor={
logo_props?.in_use && logo_props.in_use === "icon" ? logo_props?.icon?.color : undefined
}
defaultOpen={
logo_props?.in_use && logo_props?.in_use === "emoji"
? EmojiIconPickerTypes.EMOJI
: EmojiIconPickerTypes.ICON
}
/>
}
/>
}
/>
</Breadcrumbs>
</div>
</div>
{isContentEditable && (
<Button
variant="primary"
size="sm"
onClick={() => {
// ctrl/cmd + s to save the changes
const event = new KeyboardEvent("keydown", {
key: "s",
ctrlKey: !isMac,
metaKey: isMac,
});
window.dispatchEvent(event);
}}
className="flex-shrink-0"
loading={isSubmitting === "submitting"}
>
{isSubmitting === "submitting" ? "Saving" : "Save changes"}
</Button>
)}
</div>
);
});
export default PageDetailsHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import PageDetailsHeader from "./header";
const PageDetailsHeaderPage = () => <AppHeaderWrapper header={<PageDetailsHeader />} />;
export default PageDetailsHeaderPage;

View File

@ -1,5 +1,5 @@
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useSearchParams } from "next/navigation";
import { FileText } from "lucide-react";
// ui
import { Breadcrumbs, Button } from "@plane/ui";
@ -11,10 +11,11 @@ import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useCommandPalette, useEventTracker, useProject, useUser } from "@/hooks/store";
export const PagesHeader = observer(() => {
const PagesHeader = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, type: pageType } = router.query;
const { workspaceSlug } = useParams();
const searchParams = useSearchParams();
const pageType = searchParams.get("type");
// store hooks
const { toggleCreatePageModal } = useCommandPalette();
const {
@ -74,3 +75,5 @@ export const PagesHeader = observer(() => {
</div>
);
});
export default PagesHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import PagesHeader from "./header";
const PagesHeaderPage = () => <AppHeaderWrapper header={<PagesHeader />} />;
export default PagesHeaderPage;

View File

@ -0,0 +1,2 @@
import DefaultProjectSettingHeader from "../page";
export default DefaultProjectSettingHeader;

View File

@ -1,6 +1,6 @@
import { FC } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
// ui
import { Settings } from "lucide-react";
import { Breadcrumbs, CustomMenu } from "@plane/ui";
@ -11,10 +11,10 @@ import { EUserProjectRoles, PROJECT_SETTINGS_LINKS } from "@/constants/project";
// hooks
import { useProject, useUser } from "@/hooks/store";
export const ProjectSettingHeader: FC = observer(() => {
const ProjectSettingHeader: FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store hooks
const {
membership: { currentProjectRole },
@ -80,3 +80,5 @@ export const ProjectSettingHeader: FC = observer(() => {
</div>
);
});
export default ProjectSettingHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectSettingHeader from "./header";
const ProjectSettingHeaderPage = () => <AppHeaderWrapper header={<ProjectSettingHeader />} />;
export default ProjectSettingHeaderPage;

View File

@ -1,7 +1,7 @@
import { useCallback } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// types
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions, TIssueLayouts } from "@plane/types";
// ui
@ -28,10 +28,9 @@ import {
useUser,
} from "@/hooks/store";
export const ProjectViewIssuesHeader: React.FC = observer(() => {
const ProjectViewIssuesHeader: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, viewId } = router.query;
const { workspaceSlug, projectId, viewId } = useParams();
// store hooks
const {
issuesFilter: { issueFilters, updateFilters },
@ -256,3 +255,5 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
</div>
);
});
export default ProjectViewIssuesHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectViewIssuesHeader from "./header";
const ProjectViewIssuesHeaderPage = () => <AppHeaderWrapper header={<ProjectViewIssuesHeader />} />;
export default ProjectViewIssuesHeaderPage;

View File

@ -1,5 +1,5 @@
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// ui
import { Breadcrumbs, PhotoFilterIcon, Button } from "@plane/ui";
// components
@ -10,10 +10,9 @@ import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useCommandPalette, useProject, useUser } from "@/hooks/store";
export const ProjectViewsHeader: React.FC = observer(() => {
const ProjectViewsHeader: React.FC = observer(() => {
// router
const router = useRouter();
const { workspaceSlug } = router.query;
const { workspaceSlug } = useParams();
// store hooks
const { toggleCreateViewModal } = useCommandPalette();
const {
@ -69,3 +68,5 @@ export const ProjectViewsHeader: React.FC = observer(() => {
</>
);
});
export default ProjectViewsHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectViewsHeader from "./header";
const ProjectViewsHeaderPage = () => <AppHeaderWrapper header={<ProjectViewsHeader />} />;
export default ProjectViewsHeaderPage;

View File

@ -18,7 +18,7 @@ import { calculateTotalFilters } from "@/helpers/filter.helper";
import { useAppRouter, useCommandPalette, useEventTracker, useMember, useProjectFilter, useUser } from "@/hooks/store";
import useOutsideClickDetector from "@/hooks/use-outside-click-detector";
export const ProjectsHeader = observer(() => {
const ProjectsHeader = observer(() => {
// states
const [isSearchOpen, setIsSearchOpen] = useState(false);
// refs
@ -181,3 +181,5 @@ export const ProjectsHeader = observer(() => {
</div>
);
});
export default ProjectsHeader;

View File

@ -0,0 +1,13 @@
"use client";
// components
import AppHeaderWrapper from "@/app/[workspaceSlug]/app-header-wrapper";
import ProjectsHeader from "./header";
import ProjectsMobileHeader from "./mobile-header";
const ProjectsHeaderPage = () => (
<AppHeaderWrapper header={<ProjectsHeader />} mobileHeader={<ProjectsMobileHeader />} />
);
export default ProjectsHeaderPage;

View File

@ -0,0 +1,2 @@
import DefaultWorkspaceSettingsHeader from "../page";
export default DefaultWorkspaceSettingsHeader;

View File

@ -1,3 +1,5 @@
"use client";
import { FC } from "react";
import { observer } from "mobx-react";;
import { Settings } from "lucide-react";
@ -8,7 +10,7 @@ import { BreadcrumbLink } from "@/components/common";
// hooks
import { useWorkspace } from "@/hooks/store";
export const WorkspaceSettingHeader: FC = observer(() => {
const WorkspaceSettingHeader: FC = observer(() => {
const { currentWorkspace } = useWorkspace();
return (
@ -33,3 +35,5 @@ export const WorkspaceSettingHeader: FC = observer(() => {
</div>
);
});
export default WorkspaceSettingHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "../../app-header-wrapper";
import WorkspaceSettingHeader from "./header";
const WorkspaceSettingHeaderPage = () => <AppHeaderWrapper header={<WorkspaceSettingHeader />} />;
export default WorkspaceSettingHeaderPage;

View File

@ -0,0 +1,2 @@
import DefaultWorkspaceViewsHeader from "../page";
export default DefaultWorkspaceViewsHeader;

View File

@ -1,6 +1,8 @@
"use client";
import { useCallback, useState } from "react";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// types
import { IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueFilterOptions } from "@plane/types";
// ui
@ -17,12 +19,11 @@ import { calculateTotalFilters } from "@/helpers/filter.helper";
// hooks
import { useLabel, useMember, useUser, useIssues } from "@/hooks/store";
export const GlobalIssuesHeader: React.FC = observer(() => {
const GlobalIssuesHeader: React.FC = observer(() => {
// states
const [createViewModal, setCreateViewModal] = useState(false);
// router
const router = useRouter();
const { workspaceSlug, globalViewId } = router.query;
const { workspaceSlug, globalViewId } = useParams();
// store hooks
const {
issuesFilter: { filters, updateFilters },
@ -143,3 +144,5 @@ export const GlobalIssuesHeader: React.FC = observer(() => {
</>
);
});
export default GlobalIssuesHeader;

View File

@ -0,0 +1,9 @@
"use client";
// components
import AppHeaderWrapper from "../../app-header-wrapper";
import GlobalIssuesHeader from "./header";
const GlobalIssuesHeaderPage = () => <AppHeaderWrapper header={<GlobalIssuesHeader />} />;
export default GlobalIssuesHeaderPage;

View File

@ -1,17 +1,13 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
// components
import { PageHead } from "@/components/core";
import { WorkspaceActiveCycleHeader } from "@/components/headers";
import { WorkspaceActiveCyclesUpgrade } from "@/components/workspace";
// layouts
import { useWorkspace } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
// hooks
import { useWorkspace } from "@/hooks/store";
const WorkspaceActiveCyclesPage: NextPageWithLayout = observer(() => {
const WorkspaceActiveCyclesPage = observer(() => {
const { currentWorkspace } = useWorkspace();
// derived values
const pageTitle = currentWorkspace?.name ? `${currentWorkspace?.name} - Active Cycles` : undefined;
@ -24,8 +20,4 @@ const WorkspaceActiveCyclesPage: NextPageWithLayout = observer(() => {
);
});
WorkspaceActiveCyclesPage.getLayout = function getLayout(page: ReactElement) {
return <AppLayout header={<WorkspaceActiveCycleHeader />}>{page}</AppLayout>;
};
export default WorkspaceActiveCyclesPage;
export default WorkspaceActiveCyclesPage;

View File

@ -1,25 +1,22 @@
import React, { Fragment, ReactElement } from "react";
"use client";
import React, { Fragment } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useSearchParams } from "next/navigation";
import { Tab } from "@headlessui/react";
// components
import { CustomAnalytics, ScopeAndDemand } from "@/components/analytics";
import { PageHead } from "@/components/core";
import { EmptyState } from "@/components/empty-state";
import { WorkspaceAnalyticsHeader } from "@/components/headers";
// constants
import { ANALYTICS_TABS } from "@/constants/analytics";
import { EmptyStateType } from "@/constants/empty-state";
// hooks
import { useCommandPalette, useEventTracker, useProject, useWorkspace } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
import { useCommandPalette, useEventTracker, useProject, useWorkspace } from "@/hooks/store";;
const AnalyticsPage: NextPageWithLayout = observer(() => {
const router = useRouter();
const { analytics_tab } = router.query;
const AnalyticsPage = observer(() => {
const searchParams = useSearchParams();
const analytics_tab = searchParams.get("analytics_tab");
// store hooks
const { toggleCreateProjectModal } = useCommandPalette();
const { setTrackElement } = useEventTracker();
@ -39,9 +36,8 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
<Tab key={tab.key} as={Fragment}>
{({ selected }) => (
<button
className={`text-sm group relative flex items-center gap-1 h-[50px] px-3 cursor-pointer transition-all font-medium outline-none ${
selected ? "text-custom-primary-100 " : "hover:text-custom-text-200"
}`}
className={`text-sm group relative flex items-center gap-1 h-[50px] px-3 cursor-pointer transition-all font-medium outline-none ${selected ? "text-custom-primary-100 " : "hover:text-custom-text-200"
}`}
>
{tab.title}
<div
@ -75,8 +71,4 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
);
});
AnalyticsPage.getLayout = function getLayout(page: ReactElement) {
return <AppLayout header={<WorkspaceAnalyticsHeader />}>{page}</AppLayout>;
};
export default AnalyticsPage;
export default AnalyticsPage;

View File

@ -0,0 +1,26 @@
"use client";
import { ReactNode } from "react";
// components
import { SidebarHamburgerToggle } from "@/components/core";
export interface IAppHeaderWrapper {
header: ReactNode;
mobileHeader?: ReactNode;
}
const AppHeaderWrapper = ({ header, mobileHeader }: IAppHeaderWrapper) => (
<>
<div className="z-[15]">
<div className="z-10 flex w-full items-center border-b border-custom-border-200">
<div className="block bg-custom-sidebar-background-100 py-4 pl-5 md:hidden">
<SidebarHamburgerToggle />
</div>
<div className="w-full">{header}</div>
</div>
{mobileHeader && mobileHeader}
</div>
</>
);
export default AppHeaderWrapper;

View File

@ -0,0 +1,25 @@
"use client";
import { CommandPalette } from "@/components/command-palette";
import { WorkspaceAuthWrapper } from "@/layouts/auth-layout";
import { AuthenticationWrapper } from "@/lib/wrappers";
import AppSidebar from "./sidebar";
export default function WorkspaceLayout({ header, children }: { header: React.ReactNode; children: React.ReactNode }) {
return (
<AuthenticationWrapper>
<CommandPalette />
<WorkspaceAuthWrapper>
<div className="relative flex h-screen w-full overflow-hidden">
<AppSidebar />
<main className="relative flex h-full w-full flex-col overflow-hidden bg-custom-background-100">
{header}
<div className="h-full w-full overflow-hidden">
<div className="relative h-full w-full overflow-x-hidden overflow-y-scroll">{children}</div>
</div>
</main>
</div>
</WorkspaceAuthWrapper>
</AuthenticationWrapper>
);
}

View File

@ -1,17 +1,13 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
// layouts
// components
import { PageHead } from "@/components/core";
import { WorkspaceDashboardHeader } from "@/components/headers/workspace-dashboard";
import { WorkspaceDashboardView } from "@/components/page-views";
// types
// hooks
import { useWorkspace } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
import { NextPageWithLayout } from "@/lib/types";
const WorkspacePage: NextPageWithLayout = observer(() => {
const WorkspacePage = observer(() => {
const { currentWorkspace } = useWorkspace();
// derived values
const pageTitle = currentWorkspace?.name ? `${currentWorkspace?.name} - Home` : undefined;
@ -24,8 +20,4 @@ const WorkspacePage: NextPageWithLayout = observer(() => {
);
});
WorkspacePage.getLayout = function getLayout(page: ReactElement) {
return <AppLayout header={<WorkspaceDashboardHeader />}>{page}</AppLayout>;
};
export default WorkspacePage;

View File

@ -1,31 +1,27 @@
import { ReactElement, useState } from "react";
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
// hooks
import { Button } from "@plane/ui";
import { UserProfileHeader } from "@/components/headers";
import { DownloadActivityButton, WorkspaceActivityListPage } from "@/components/profile";
import { EUserWorkspaceRoles } from "@/constants/workspace";
import { useUser } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
import { ProfileAuthWrapper } from "@/layouts/user-profile-layout";
// components
import { useParams } from "next/navigation";
// ui
// types
import { NextPageWithLayout } from "@/lib/types";
import { Button } from "@plane/ui";
// components
import { DownloadActivityButton, WorkspaceActivityListPage } from "@/components/profile";
// constants
import { EUserWorkspaceRoles } from "@/constants/workspace";
// hooks
import { useUser } from "@/hooks/store";
const PER_PAGE = 100;
const ProfileActivityPage: NextPageWithLayout = observer(() => {
const ProfileActivityPage = observer(() => {
// states
const [pageCount, setPageCount] = useState(1);
const [totalPages, setTotalPages] = useState(0);
const [resultsCount, setResultsCount] = useState(0);
// router
const router = useRouter();
const { userId } = router.query;
const { userId } = useParams();
// store hooks
const { data: currentUser } = useUser();
const {
@ -73,12 +69,4 @@ const ProfileActivityPage: NextPageWithLayout = observer(() => {
);
});
ProfileActivityPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<UserProfileHeader type="Activity" />}>
<ProfileAuthWrapper>{page}</ProfileAuthWrapper>
</AppLayout>
);
};
export default ProfileActivityPage;

View File

@ -0,0 +1,15 @@
"use client";
import React from "react";
// components
import { PageHead } from "@/components/core";
import { ProfileIssuesPage } from "@/components/profile/profile-issues";
const ProfileAssignedIssuesPage = () => (
<>
<PageHead title="Profile - Assigned" />
<ProfileIssuesPage type="assigned" />
</>
);
export default ProfileAssignedIssuesPage;

View File

@ -0,0 +1,16 @@
"use client";
// store
import { observer } from "mobx-react-lite";
// components
import { PageHead } from "@/components/core";
import { ProfileIssuesPage } from "@/components/profile/profile-issues";
const ProfileCreatedIssuesPage = () => (
<>
<PageHead title="Profile - Created" />
<ProfileIssuesPage type="created" />
</>
);
export default observer(ProfileCreatedIssuesPage);

View File

@ -1,45 +1,51 @@
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { usePathname } from "next/navigation";
// components
import { ProfileNavbar, ProfileSidebar } from "@/components/profile";
import { ProfileSidebar } from "@/components/profile";
// constants
import { EUserWorkspaceRoles } from "@/constants/workspace";
// hooks
import { useUser } from "@/hooks/store";
// local components
import { ProfileNavbar } from "./navbar";
type Props = {
children: React.ReactNode;
className?: string;
showProfileIssuesFilter?: boolean;
};
const AUTHORIZED_ROLES = [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER, EUserWorkspaceRoles.VIEWER];
export const ProfileAuthWrapper: React.FC<Props> = observer((props) => {
const { children, className, showProfileIssuesFilter } = props;
const ProfileAuthWrapper: React.FC<Props> = observer((props) => {
const { children } = props;
// router
const router = useRouter();
const pathname = usePathname();
// store hooks
const {
membership: { currentWorkspaceRole },
} = useUser();
// derived values
const isAuthorized = currentWorkspaceRole && AUTHORIZED_ROLES.includes(currentWorkspaceRole);
const isAuthorizedPath = router.pathname.includes("assigned" || "created" || "subscribed");
const isAuthorizedPath =
pathname.includes("assigned") || pathname.includes("created") || pathname.includes("subscribed");
const isIssuesTab = pathname.includes("assigned") || pathname.includes("created") || pathname.includes("subscribed");
return (
<div className="h-full w-full flex md:overflow-hidden">
<div className="flex w-full flex-col md:h-full md:overflow-hidden">
<ProfileNavbar isAuthorized={!!isAuthorized} showProfileIssuesFilter={showProfileIssuesFilter} />
<ProfileNavbar isAuthorized={!!isAuthorized} showProfileIssuesFilter={isIssuesTab} />
{isAuthorized || !isAuthorizedPath ? (
<div className={`w-full overflow-hidden md:h-full ${className}`}>{children}</div>
<div className={`w-full overflow-hidden md:h-full`}>{children}</div>
) : (
<div className="grid h-full w-full place-items-center text-custom-text-200">
You do not have the permission to access this page.
</div>
)}
</div>
<ProfileSidebar />
<ProfileSidebar />
</div>
);
});
export default ProfileAuthWrapper;

View File

@ -1,7 +1,7 @@
import React from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useParams, usePathname } from "next/navigation";
// components
import { ProfileIssuesFilter } from "@/components/profile";
@ -16,8 +16,8 @@ type Props = {
export const ProfileNavbar: React.FC<Props> = (props) => {
const { isAuthorized, showProfileIssuesFilter } = props;
const router = useRouter();
const { workspaceSlug, userId } = router.query;
const { workspaceSlug, userId } = useParams();
const pathname = usePathname();
const tabsList = isAuthorized ? [...PROFILE_VIEWER_TAB, ...PROFILE_ADMINS_TAB] : PROFILE_VIEWER_TAB;
@ -28,7 +28,7 @@ export const ProfileNavbar: React.FC<Props> = (props) => {
<Link key={tab.route} href={`/${workspaceSlug}/profile/${userId}/${tab.route}`}>
<span
className={`flex whitespace-nowrap border-b-2 p-4 text-sm font-medium outline-none ${
router.pathname === tab.selected
pathname === `/${workspaceSlug}/profile/${userId}${tab.selected}`
? "border-custom-primary-100 text-custom-primary-100"
: "border-transparent"
}`}

View File

@ -1,12 +1,11 @@
import { ReactElement } from "react";
import { useRouter } from "next/router";
"use client";
import { useParams } from "next/navigation";
import useSWR from "swr";
// types
import { IUserStateDistribution, TStateGroups } from "@plane/types";
// services
// layouts
// components
import { PageHead } from "@/components/core";
import { UserProfileHeader } from "@/components/headers";
import {
ProfileActivity,
ProfilePriorityDistribution,
@ -14,21 +13,17 @@ import {
ProfileStats,
ProfileWorkload,
} from "@/components/profile";
// types
// constants
import { USER_PROFILE_DATA } from "@/constants/fetch-keys";
import { GROUP_CHOICES } from "@/constants/project";
import { AppLayout } from "@/layouts/app-layout";
import { ProfileAuthWrapper } from "@/layouts/user-profile-layout";
import { NextPageWithLayout } from "@/lib/types";
// services
import { UserService } from "@/services/user.service";
// services
const userService = new UserService();
const ProfileOverviewPage: NextPageWithLayout = () => {
const router = useRouter();
const { workspaceSlug, userId } = router.query;
const ProfileOverviewPage = () => {
const { workspaceSlug, userId } = useParams();
const { data: userProfile } = useSWR(
workspaceSlug && userId ? USER_PROFILE_DATA(workspaceSlug.toString(), userId.toString()) : null,
@ -58,12 +53,4 @@ const ProfileOverviewPage: NextPageWithLayout = () => {
);
};
ProfileOverviewPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<UserProfileHeader type="Summary" />}>
<ProfileAuthWrapper>{page}</ProfileAuthWrapper>
</AppLayout>
);
};
export default ProfileOverviewPage;
export default ProfileOverviewPage;

View File

@ -0,0 +1,16 @@
"use client";
// store
import { observer } from "mobx-react-lite";
// components
import { PageHead } from "@/components/core";
import { ProfileIssuesPage } from "@/components/profile/profile-issues";
const ProfileSubscribedIssuesPage = () => (
<>
<PageHead title="Profile - Subscribed" />
<ProfileIssuesPage type="subscribed" />
</>
);
export default observer(ProfileSubscribedIssuesPage);

View File

@ -1,21 +1,16 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core";
import { ArchivedCycleLayoutRoot, ArchivedCyclesHeader } from "@/components/cycles";
import { ProjectArchivesHeader } from "@/components/headers";
// hooks
import { useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const ProjectArchivedCyclesPage: NextPageWithLayout = observer(() => {
const ProjectArchivedCyclesPage = observer(() => {
// router
const router = useRouter();
const { projectId } = router.query;
const { projectId } = useParams();
// store hooks
const { getProjectById } = useProject();
// derived values
@ -33,12 +28,4 @@ const ProjectArchivedCyclesPage: NextPageWithLayout = observer(() => {
);
});
ProjectArchivedCyclesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectArchivesHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectArchivedCyclesPage;
export default ProjectArchivedCyclesPage;

View File

@ -1,6 +1,8 @@
import { useState, ReactElement } from "react";
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
import useSWR from "swr";
// icons
import { ArchiveRestoreIcon } from "lucide-react";
@ -8,22 +10,17 @@ import { ArchiveRestoreIcon } from "lucide-react";
import { ArchiveIcon, Button, Loader, TOAST_TYPE, setToast } from "@plane/ui";
// components
import { PageHead } from "@/components/core";
import { ProjectArchivedIssueDetailsHeader } from "@/components/headers";
import { IssueDetailRoot } from "@/components/issues";
// constants
import { EIssuesStoreType } from "@/constants/issue";
import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useIssueDetail, useIssues, useProject, useUser } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const ArchivedIssueDetailsPage: NextPageWithLayout = observer(() => {
const ArchivedIssueDetailsPage = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, archivedIssueId } = router.query;
const { workspaceSlug, projectId, archivedIssueId } = useParams();
// states
const [isRestoring, setIsRestoring] = useState(false);
// hooks
@ -137,12 +134,4 @@ const ArchivedIssueDetailsPage: NextPageWithLayout = observer(() => {
);
});
ArchivedIssueDetailsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectArchivedIssueDetailsHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ArchivedIssueDetailsPage;
export default ArchivedIssueDetailsPage;

View File

@ -1,21 +1,16 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core";
import { ProjectArchivesHeader } from "@/components/headers";
import { ArchivedIssueLayoutRoot, ArchivedIssuesHeader } from "@/components/issues";
// hooks
import { useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const ProjectArchivedIssuesPage: NextPageWithLayout = observer(() => {
const ProjectArchivedIssuesPage = observer(() => {
// router
const router = useRouter();
const { projectId } = router.query;
const { projectId } = useParams();
// store hooks
const { getProjectById } = useProject();
// derived values
@ -33,12 +28,4 @@ const ProjectArchivedIssuesPage: NextPageWithLayout = observer(() => {
);
});
ProjectArchivedIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectArchivesHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectArchivedIssuesPage;
export default ProjectArchivedIssuesPage;

View File

@ -1,21 +1,16 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core";
import { ProjectArchivesHeader } from "@/components/headers";
import { ArchivedModuleLayoutRoot, ArchivedModulesHeader } from "@/components/modules";
// hooks
import { useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const ProjectArchivedModulesPage: NextPageWithLayout = observer(() => {
const ProjectArchivedModulesPage = observer(() => {
// router
const router = useRouter();
const { projectId } = router.query;
const { projectId } = useParams();
// store hooks
const { getProjectById } = useProject();
// derived values
@ -33,12 +28,4 @@ const ProjectArchivedModulesPage: NextPageWithLayout = observer(() => {
);
});
ProjectArchivedModulesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectArchivesHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectArchivedModulesPage;

View File

@ -1,29 +1,23 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
import useSWR from "swr";
// hooks
// components
import { EmptyState } from "@/components/common";
import { PageHead } from "@/components/core";
import { CycleDetailsSidebar } from "@/components/cycles";
import { CycleMobileHeader } from "@/components/cycles/cycle-mobile-header";
import { CycleIssuesHeader } from "@/components/headers";
import { CycleLayoutRoot } from "@/components/issues/issue-layouts";
// hooks
import { useCycle, useProject } from "@/hooks/store";
import useLocalStorage from "@/hooks/use-local-storage";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// components
// ui
// assets
import { NextPageWithLayout } from "@/lib/types";
import emptyCycle from "public/empty-state/cycle.svg";
// types
const CycleDetailPage: NextPageWithLayout = observer(() => {
const CycleDetailPage = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, cycleId } = router.query;
const { workspaceSlug, projectId, cycleId } = useParams();
// store hooks
const { fetchCycleDetails, getCycleById } = useCycle();
const { getProjectById } = useProject();
@ -84,12 +78,4 @@ const CycleDetailPage: NextPageWithLayout = observer(() => {
);
});
CycleDetailPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<CycleIssuesHeader />} mobileHeader={<CycleMobileHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default CycleDetailPage;

View File

@ -1,14 +1,14 @@
import { useState, ReactElement } from "react";
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// types
import { TCycleFilters } from "@plane/types";
// components
import { PageHead } from "@/components/core";
import { CyclesView, CycleCreateUpdateModal, CycleAppliedFiltersList } from "@/components/cycles";
import CyclesListMobileHeader from "@/components/cycles/cycles-list-mobile-header";
import { EmptyState } from "@/components/empty-state";
import { CyclesHeader } from "@/components/headers";
import { CycleModuleListLayout } from "@/components/ui";
// constants
import { EmptyStateType } from "@/constants/empty-state";
@ -16,12 +16,8 @@ import { EmptyStateType } from "@/constants/empty-state";
import { calculateTotalFilters } from "@/helpers/filter.helper";
// hooks
import { useEventTracker, useCycle, useProject, useCycleFilter } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
const ProjectCyclesPage = observer(() => {
// states
const [createModal, setCreateModal] = useState(false);
// store hooks
@ -29,8 +25,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
const { currentProjectCycleIds, loader } = useCycle();
const { getProjectById, currentProjectDetails } = useProject();
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// cycle filters hook
const { clearAllFilters, currentProjectFilters, updateFilters } = useCycleFilter();
// derived values
@ -103,12 +98,4 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
);
});
ProjectCyclesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<CyclesHeader />} mobileHeader={<CyclesListMobileHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectCyclesPage;
export default ProjectCyclesPage;

View File

@ -1,21 +1,17 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
import { X, PenSquare } from "lucide-react";
// layouts
// components
import { PageHead } from "@/components/core";
import { ProjectDraftIssueHeader } from "@/components/headers";
import { DraftIssueLayoutRoot } from "@/components/issues/issue-layouts/roots/draft-issue-layout-root";
// types
// hooks
import { useProject } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
import { NextPageWithLayout } from "@/lib/types";
const ProjectDraftIssuesPage: NextPageWithLayout = observer(() => {
const ProjectDraftIssuesPage = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store
const { getProjectById } = useProject();
// derived values
@ -43,12 +39,4 @@ const ProjectDraftIssuesPage: NextPageWithLayout = observer(() => {
);
});
ProjectDraftIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectDraftIssueHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectDraftIssuesPage;
export default ProjectDraftIssuesPage;

View File

@ -0,0 +1,63 @@
"use client";
import { observer } from "mobx-react";
import { useParams, useSearchParams } from "next/navigation";
// components
import { PageHead } from "@/components/core";
import { EmptyState } from "@/components/empty-state";
import { InboxIssueRoot } from "@/components/inbox";
// constants
import { EmptyStateType } from "@/constants/empty-state";
// helpers
import { EInboxIssueCurrentTab } from "@/helpers/inbox.helper";
// hooks
import { useProject } from "@/hooks/store";
const ProjectInboxPage = observer(() => {
/// router
const { workspaceSlug, projectId } = useParams();
const searchParams = useSearchParams();
const navigationTab = searchParams.get("currentTab");
const inboxIssueId = searchParams.get("inboxIssueId");
// hooks
const { currentProjectDetails } = useProject();
// No access to inbox
if (currentProjectDetails?.inbox_view === false)
return (
<div className="flex items-center justify-center h-full w-full">
<EmptyState
type={EmptyStateType.DISABLED_PROJECT_INBOX}
primaryButtonLink={`/${workspaceSlug}/projects/${projectId}/settings/features`}
/>
</div>
);
// derived values
const pageTitle = currentProjectDetails?.name ? `${currentProjectDetails?.name} - Inbox` : "Plane - Inbox";
const currentNavigationTab = navigationTab
? navigationTab === "open"
? EInboxIssueCurrentTab.OPEN
: EInboxIssueCurrentTab.CLOSED
: undefined;
if (!workspaceSlug || !projectId) return <></>;
return (
<div className="flex h-full flex-col">
<PageHead title={pageTitle} />
<div className="w-full h-full overflow-hidden">
<InboxIssueRoot
workspaceSlug={workspaceSlug.toString()}
projectId={projectId.toString()}
inboxIssueId={inboxIssueId?.toString() || undefined}
inboxAccessible={currentProjectDetails?.inbox_view || false}
navigationTab={currentNavigationTab}
/>
</div>
</div>
);
});
export default ProjectInboxPage;

View File

@ -1,6 +1,8 @@
import React, { ReactElement, useEffect } from "react";
"use client";
import React, { useEffect } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
import { useTheme } from "next-themes";
import useSWR from "swr";
// ui
@ -8,22 +10,17 @@ import { Loader } from "@plane/ui";
// components
import { EmptyState } from "@/components/common";
import { PageHead } from "@/components/core";
import { ProjectIssueDetailsHeader } from "@/components/headers";
import { IssueDetailRoot } from "@/components/issues";
// hooks
import { useAppTheme, useIssueDetail, useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
// assets
import emptyIssueDark from "@/public/empty-state/search/issues-dark.webp";
import emptyIssueLight from "@/public/empty-state/search/issues-light.webp";
const IssueDetailsPage: NextPageWithLayout = observer(() => {
const IssueDetailsPage = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, issueId } = router.query;
const { workspaceSlug, projectId, issueId } = useParams();
// hooks
const { resolvedTheme } = useTheme();
// store hooks
@ -108,12 +105,4 @@ const IssueDetailsPage: NextPageWithLayout = observer(() => {
);
});
IssueDetailsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectIssueDetailsHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default IssueDetailsPage;

View File

@ -1,22 +1,16 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import Head from "next/head";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core";
import { ProjectIssuesHeader } from "@/components/headers";
import { ProjectLayoutRoot } from "@/components/issues";
// types
import { IssuesMobileHeader } from "@/components/issues/issues-mobile-header";
import { useProject } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
import { NextPageWithLayout } from "@/lib/types";
// layouts
// hooks
import { useProject } from "@/hooks/store";
const ProjectIssuesPage: NextPageWithLayout = observer(() => {
const router = useRouter();
const { projectId } = router.query;
const ProjectIssuesPage = observer(() => {
const { projectId } = useParams();
// store
const { getProjectById } = useProject();
@ -41,12 +35,4 @@ const ProjectIssuesPage: NextPageWithLayout = observer(() => {
);
});
ProjectIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectIssuesHeader />} mobileHeader={<IssuesMobileHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectIssuesPage;

View File

@ -0,0 +1,13 @@
"use client";
import { ReactNode } from "react"
// layouts
import { ProjectAuthWrapper } from "@/layouts/auth-layout"
const ProjectLayout = ({ children }: { children: ReactNode }) => (
<ProjectAuthWrapper>
{children}
</ProjectAuthWrapper>
);
export default ProjectLayout;

View File

@ -1,28 +1,23 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
import useSWR from "swr";
// hooks
// components
import { EmptyState } from "@/components/common";
import { PageHead } from "@/components/core";
import { ModuleIssuesHeader } from "@/components/headers";
import { ModuleLayoutRoot } from "@/components/issues";
import { ModuleDetailsSidebar } from "@/components/modules";
import { ModuleMobileHeader } from "@/components/modules/module-mobile-header";
// hooks
import { useModule, useProject } from "@/hooks/store";
import useLocalStorage from "@/hooks/use-local-storage";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// components
// assets
import { NextPageWithLayout } from "@/lib/types";
import emptyModule from "public/empty-state/module.svg";
// types
const ModuleIssuesPage: NextPageWithLayout = observer(() => {
const ModuleIssuesPage = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, moduleId } = router.query;
const { workspaceSlug, projectId, moduleId } = useParams();
// store hooks
const { fetchModuleDetails, getModuleById } = useModule();
const { getProjectById } = useProject();
@ -82,12 +77,4 @@ const ModuleIssuesPage: NextPageWithLayout = observer(() => {
);
});
ModuleIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ModuleIssuesHeader />} mobileHeader={<ModuleMobileHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ModuleIssuesPage;

View File

@ -1,28 +1,23 @@
import { ReactElement, useCallback } from "react";
"use client";
import { useCallback } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// types
import { TModuleFilters } from "@plane/types";
// components
import { PageHead } from "@/components/core";
import { EmptyState } from "@/components/empty-state";
import { ModulesListHeader } from "@/components/headers";
import { ModuleAppliedFiltersList, ModulesListView } from "@/components/modules";
import ModulesListMobileHeader from "@/components/modules/moduels-list-mobile-header";
// constants
import { EmptyStateType } from "@/constants/empty-state";
// helpers
import { calculateTotalFilters } from "@/helpers/filter.helper";
// hooks
import { useModuleFilter, useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const ProjectModulesPage: NextPageWithLayout = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const ProjectModulesPage = observer(() => {
const { workspaceSlug, projectId } = useParams();
// store
const { getProjectById, currentProjectDetails } = useProject();
const { currentProjectFilters, currentProjectDisplayFilters, clearAllFilters, updateFilters, updateDisplayFilters } =
@ -82,12 +77,4 @@ const ProjectModulesPage: NextPageWithLayout = observer(() => {
);
});
ProjectModulesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ModulesListHeader />} mobileHeader={<ModulesListMobileHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectModulesPage;

View File

@ -1,7 +1,9 @@
import { ReactElement, useRef, useState } from "react";
"use client";
import { useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import Link from "next/link";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
import useSWR from "swr";
// document-editor
import { EditorRefApi, useEditorMarkings } from "@plane/document-editor";
@ -12,19 +14,14 @@ import { TOAST_TYPE, getButtonStyling, setToast } from "@plane/ui";
// components
import { LogoSpinner } from "@/components/common";
import { PageHead } from "@/components/core";
import { PageDetailsHeader } from "@/components/headers";
import { IssuePeekOverview } from "@/components/issues";
import { PageEditorBody, PageEditorHeaderRoot } from "@/components/pages";
// helpers
import { cn } from "@/helpers/common.helper";
// hooks
import { usePage, useProjectPages } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// lib
import { NextPageWithLayout } from "@/lib/types";
const PageDetailsPage: NextPageWithLayout = observer(() => {
const PageDetailsPage = observer(() => {
// states
const [sidePeekVisible, setSidePeekVisible] = useState(window.innerWidth >= 768 ? true : false);
const [editorReady, setEditorReady] = useState(false);
@ -34,7 +31,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
const readOnlyEditorRef = useRef<EditorRefApi>(null);
// router
const router = useRouter();
const { workspaceSlug, projectId, pageId } = router.query;
const { workspaceSlug, projectId, pageId } = useParams();
// store hooks
const { createPage, getPageById } = useProjectPages();
const page = usePage(pageId?.toString() ?? "");
@ -131,12 +128,4 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
);
});
PageDetailsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<PageDetailsHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default PageDetailsPage;

View File

@ -1,23 +1,19 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useSearchParams } from "next/navigation";
// types
import { TPageNavigationTabs } from "@plane/types";
// components
import { PageHead } from "@/components/core";
import { PagesHeader } from "@/components/headers";
import { PagesListRoot, PagesListView } from "@/components/pages";
// hooks
import { useAppRouter, useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// lib
import { NextPageWithLayout } from "@/lib/types";
const ProjectPagesPage: NextPageWithLayout = observer(() => {
const ProjectPagesPage = observer(() => {
// router
const router = useRouter();
const { type } = router.query;
const searchParams = useSearchParams();
const type = searchParams.get("type");
// store hooks
const { workspaceSlug, projectId } = useAppRouter();
const { getProjectById } = useProject();
@ -51,12 +47,4 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
);
});
ProjectPagesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<PagesHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectPagesPage;

View File

@ -1,30 +1,22 @@
import React, { ReactElement } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { IProject } from "@plane/types";
// hooks
import { TOAST_TYPE, setToast } from "@plane/ui";
import { AutoArchiveAutomation, AutoCloseAutomation } from "@/components/automation";
// layouts
// ui
// components
import { PageHead } from "@/components/core";
import { ProjectSettingHeader } from "@/components/headers";
import { EUserProjectRoles } from "@/constants/project";
import { useProject, useUser } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
// layouts
import { ProjectSettingLayout } from "@/layouts/settings-layout";
// hooks
// components
// types
import { NextPageWithLayout } from "@/lib/types";
// constants
"use client";
const AutomationSettingsPage: NextPageWithLayout = observer(() => {
import React from "react";
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import { IProject } from "@plane/types";
// ui
import { TOAST_TYPE, setToast } from "@plane/ui";
// components
import { AutoArchiveAutomation, AutoCloseAutomation } from "@/components/automation";
import { PageHead } from "@/components/core";
// constants
import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useProject, useUser } from "@/hooks/store";
const AutomationSettingsPage = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store hooks
const {
membership: { currentProjectRole },
@ -61,12 +53,4 @@ const AutomationSettingsPage: NextPageWithLayout = observer(() => {
);
});
AutomationSettingsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectSettingHeader />} withProjectWrapper>
<ProjectSettingLayout>{page}</ProjectSettingLayout>
</AppLayout>
);
};
export default AutomationSettingsPage;

View File

@ -1,23 +1,17 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
// components
import { PageHead } from "@/components/core";
import { EstimateRoot } from "@/components/estimates";
import { ProjectSettingHeader } from "@/components/headers";
// constants
import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useUser, useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
import { ProjectSettingLayout } from "@/layouts/settings-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const EstimatesSettingsPage: NextPageWithLayout = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const EstimatesSettingsPage = observer(() => {
const { workspaceSlug, projectId } = useParams();
const {
membership: { currentProjectRole },
} = useUser();
@ -38,12 +32,4 @@ const EstimatesSettingsPage: NextPageWithLayout = observer(() => {
);
});
EstimatesSettingsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectSettingHeader />} withProjectWrapper>
<ProjectSettingLayout>{page}</ProjectSettingLayout>
</AppLayout>
);
};
export default EstimatesSettingsPage;

View File

@ -1,24 +1,18 @@
import { ReactElement } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import useSWR from "swr";
// hooks
import { PageHead } from "@/components/core";
import { ProjectSettingHeader } from "@/components/headers";
import { ProjectFeaturesList } from "@/components/project";
import { EUserProjectRoles } from "@/constants/project";
import { useProject, useUser } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
import { ProjectSettingLayout } from "@/layouts/settings-layout";
// components
// types
import { NextPageWithLayout } from "@/lib/types";
// constants
"use client";
const FeaturesSettingsPage: NextPageWithLayout = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
import { observer } from "mobx-react";
import { useParams } from "next/navigation";
import useSWR from "swr";
// components
import { PageHead } from "@/components/core";
import { ProjectFeaturesList } from "@/components/project";
// constants
import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useProject, useUser } from "@/hooks/store";
const FeaturesSettingsPage = observer(() => {
const { workspaceSlug, projectId } = useParams();
// store
const {
membership: { fetchUserProjectInfo },
@ -52,12 +46,4 @@ const FeaturesSettingsPage: NextPageWithLayout = observer(() => {
);
});
FeaturesSettingsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectSettingHeader />} withProjectWrapper>
<ProjectSettingLayout>{page}</ProjectSettingLayout>
</AppLayout>
);
};
export default FeaturesSettingsPage;
export default FeaturesSettingsPage;

View File

@ -1,20 +1,16 @@
import { ReactElement, useEffect, useRef } from "react";
"use client";
import { useEffect, useRef } from "react";
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
import { observer } from "mobx-react";
// layouts
import { PageHead } from "@/components/core";
import { ProjectSettingHeader } from "@/components/headers";
import { ProjectSettingsLabelList } from "@/components/labels";
import { useProject } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
import { ProjectSettingLayout } from "@/layouts/settings-layout";
// components
// types
import { NextPageWithLayout } from "@/lib/types";
import { PageHead } from "@/components/core";
import { ProjectSettingsLabelList } from "@/components/labels";
// hooks
import { useProject } from "@/hooks/store";
const LabelsSettingsPage: NextPageWithLayout = observer(() => {
const LabelsSettingsPage = observer(() => {
const { currentProjectDetails } = useProject();
const pageTitle = currentProjectDetails?.name ? `${currentProjectDetails?.name} - Labels` : undefined;
@ -43,12 +39,4 @@ const LabelsSettingsPage: NextPageWithLayout = observer(() => {
);
});
LabelsSettingsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout withProjectWrapper header={<ProjectSettingHeader />}>
<ProjectSettingLayout>{page}</ProjectSettingLayout>
</AppLayout>
);
};
export default LabelsSettingsPage;

View File

@ -1,26 +1,28 @@
"use client";
import { FC, ReactNode } from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useRouter } from "next/router";
// hooks
// components
import { Button, LayersIcon } from "@plane/ui";
import { NotAuthorizedView } from "@/components/auth-screens";
import { useParams } from "next/navigation";
// ui
import { Button, LayersIcon } from "@plane/ui";
// components
import { NotAuthorizedView } from "@/components/auth-screens";
// constants
import { EUserProjectRoles } from "@/constants/project";
// hooks
import { useUser } from "@/hooks/store";
import { ProjectSettingsSidebar } from "./sidebar";
// local components
import ProjectSettingsSidebar from "./sidebar";
export interface IProjectSettingLayout {
children: ReactNode;
}
export const ProjectSettingLayout: FC<IProjectSettingLayout> = observer((props) => {
const ProjectSettingLayout: FC<IProjectSettingLayout> = observer((props) => {
const { children } = props;
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store hooks
const {
membership: { currentProjectRole },
@ -51,3 +53,5 @@ export const ProjectSettingLayout: FC<IProjectSettingLayout> = observer((props)
</div>
);
});
export default ProjectSettingLayout;

View File

@ -1,18 +1,13 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
// layouts
// components
import { PageHead } from "@/components/core";
import { ProjectSettingHeader } from "@/components/headers";
import { ProjectMemberList, ProjectSettingsMemberDefaults } from "@/components/project";
// types
// hooks
import { useProject } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
import { ProjectSettingLayout } from "@/layouts/settings-layout";
import { NextPageWithLayout } from "@/lib/types";
const MembersSettingsPage: NextPageWithLayout = observer(() => {
const MembersSettingsPage = observer(() => {
// store
const { currentProjectDetails } = useProject();
// derived values
@ -29,12 +24,4 @@ const MembersSettingsPage: NextPageWithLayout = observer(() => {
);
});
MembersSettingsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectSettingHeader />} withProjectWrapper>
<ProjectSettingLayout>{page}</ProjectSettingLayout>
</AppLayout>
);
};
export default MembersSettingsPage;

View File

@ -1,10 +1,11 @@
import { useState, ReactElement } from "react";
"use client";
import { useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams } from "next/navigation";
import useSWR from "swr";
// components
import { PageHead } from "@/components/core";
import { ProjectSettingHeader } from "@/components/headers";
import {
ArchiveRestoreProjectModal,
ArchiveProjectSelection,
@ -15,19 +16,13 @@ import {
} from "@/components/project";
// hooks
import { useProject } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
import { ProjectSettingLayout } from "@/layouts/settings-layout";
// types
import { NextPageWithLayout } from "@/lib/types";
const GeneralSettingsPage: NextPageWithLayout = observer(() => {
const GeneralSettingsPage = observer(() => {
// states
const [selectProject, setSelectedProject] = useState<string | null>(null);
const [archiveProject, setArchiveProject] = useState<boolean>(false);
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { workspaceSlug, projectId } = useParams();
// store hooks
const { currentProjectDetails, fetchProjectDetails } = useProject();
// api call to fetch project details
@ -91,12 +86,4 @@ const GeneralSettingsPage: NextPageWithLayout = observer(() => {
);
});
GeneralSettingsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectSettingHeader />} withProjectWrapper>
<ProjectSettingLayout>{page}</ProjectSettingLayout>
</AppLayout>
);
};
export default GeneralSettingsPage;

View File

@ -1,16 +1,16 @@
import React from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useParams, usePathname } from "next/navigation";
// ui
import { Loader } from "@plane/ui";
// hooks
import { EUserProjectRoles, PROJECT_SETTINGS_LINKS } from "@/constants/project";
import { useUser } from "@/hooks/store";
// constants
import { EUserProjectRoles, PROJECT_SETTINGS_LINKS } from "@/constants/project";
// hooks
import { useUser } from "@/hooks/store";
export const ProjectSettingsSidebar = () => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const ProjectSettingsSidebar = () => {
const { workspaceSlug, projectId } = useParams();
const pathname = usePathname();
// mobx store
const {
membership: { currentProjectRole },
@ -43,11 +43,10 @@ export const ProjectSettingsSidebar = () => {
projectMemberInfo >= link.access && (
<Link key={link.key} href={`/${workspaceSlug}/projects/${projectId}${link.href}`}>
<div
className={`rounded-md px-4 py-2 text-sm font-medium ${
link.highlight(router.asPath, `/${workspaceSlug}/projects/${projectId}`)
className={`rounded-md px-4 py-2 text-sm font-medium ${link.highlight(pathname, `/${workspaceSlug}/projects/${projectId}`)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
}`}
}`}
>
{link.label}
</div>
@ -59,3 +58,5 @@ export const ProjectSettingsSidebar = () => {
</div>
);
};
export default ProjectSettingsSidebar;

View File

@ -1,18 +1,13 @@
import { ReactElement } from "react";
import { observer } from "mobx-react";
// layout
import { PageHead } from "@/components/core";
import { ProjectSettingHeader } from "@/components/headers";
import { ProjectSettingStateList } from "@/components/states";
import { useProject } from "@/hooks/store";
import { AppLayout } from "@/layouts/app-layout";
import { ProjectSettingLayout } from "@/layouts/settings-layout";
// components
// types
import { NextPageWithLayout } from "@/lib/types";
// hook
"use client";
const StatesSettingsPage: NextPageWithLayout = observer(() => {
import { observer } from "mobx-react";
// components
import { PageHead } from "@/components/core";
import { ProjectSettingStateList } from "@/components/states";
// hook
import { useProject } from "@/hooks/store";
const StatesSettingsPage = observer(() => {
// store
const { currentProjectDetails } = useProject();
// derived values
@ -30,12 +25,4 @@ const StatesSettingsPage: NextPageWithLayout = observer(() => {
);
});
StatesSettingsPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout withProjectWrapper header={<ProjectSettingHeader />}>
<ProjectSettingLayout>{page}</ProjectSettingLayout>
</AppLayout>
);
};
export default StatesSettingsPage;

View File

@ -1,26 +1,21 @@
import { ReactElement } from "react";
"use client";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
import { useParams, useRouter } from "next/navigation";
import useSWR from "swr";
// hooks
// components
import { EmptyState } from "@/components/common";
import { PageHead } from "@/components/core";
import { ProjectViewIssuesHeader } from "@/components/headers";
import { ProjectViewLayoutRoot } from "@/components/issues";
// hooks
import { useProject, useProjectView } from "@/hooks/store";
// layouts
import { AppLayout } from "@/layouts/app-layout";
// components
// ui
// assets
import { NextPageWithLayout } from "@/lib/types";
import emptyView from "public/empty-state/view.svg";
// types
const ProjectViewIssuesPage: NextPageWithLayout = observer(() => {
const ProjectViewIssuesPage = observer(() => {
// router
const router = useRouter();
const { workspaceSlug, projectId, viewId } = router.query;
const { workspaceSlug, projectId, viewId } = useParams();
// store hooks
const { fetchViewDetails, getViewById } = useProjectView();
const { getProjectById } = useProject();
@ -58,12 +53,4 @@ const ProjectViewIssuesPage: NextPageWithLayout = observer(() => {
);
});
ProjectViewIssuesPage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout header={<ProjectViewIssuesHeader />} withProjectWrapper>
{page}
</AppLayout>
);
};
export default ProjectViewIssuesPage;
export default ProjectViewIssuesPage;

Some files were not shown because too many files have changed in this diff Show More