mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
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:
parent
59fdd611e4
commit
5d807db69e
@ -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.
|
||||
<Link
|
||||
className="underline underline-offset-4 font-medium hover:font-bold transition-all"
|
||||
href={`/sign-in${email ? `?email=${encodeURIComponent(email)}` : ``}`}
|
||||
>
|
||||
Sign In
|
||||
</Link>
|
||||
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.
|
||||
// <Link
|
||||
// className="underline underline-offset-4 font-medium hover:font-bold transition-all"
|
||||
// href={`/sign-in${email ? `?email=${encodeURIComponent(email)}` : ``}`}
|
||||
// >
|
||||
// Sign In
|
||||
// </Link>
|
||||
// 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.
|
||||
<Link
|
||||
className="underline underline-offset-4 font-medium hover:font-bold transition-all"
|
||||
href={`/${email ? `?email=${encodeURIComponent(email)}` : ``}`}
|
||||
>
|
||||
Create one
|
||||
</Link>
|
||||
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.
|
||||
// <Link
|
||||
// className="underline underline-offset-4 font-medium hover:font-bold transition-all"
|
||||
// href={`/${email ? `?email=${encodeURIComponent(email)}` : ``}`}
|
||||
// >
|
||||
// Create one
|
||||
// </Link>
|
||||
// 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.
|
||||
<Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
|
||||
Sign In
|
||||
</Link>
|
||||
now.
|
||||
</div>
|
||||
),
|
||||
},
|
||||
[EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST]: {
|
||||
title: `Admin user does not exist`,
|
||||
message: () => (
|
||||
<div>
|
||||
Admin user does not exist.
|
||||
<Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
|
||||
Sign In
|
||||
</Link>
|
||||
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.
|
||||
// <Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
|
||||
// Sign In
|
||||
// </Link>
|
||||
// now.
|
||||
// </div>
|
||||
// ),
|
||||
// },
|
||||
// [EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST]: {
|
||||
// title: `Admin user does not exist`,
|
||||
// message: () => (
|
||||
// <div>
|
||||
// Admin user does not exist.
|
||||
// <Link className="underline underline-offset-4 font-medium hover:font-bold transition-all" href={`/admin`}>
|
||||
// Sign In
|
||||
// </Link>
|
||||
// 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;
|
||||
// };
|
||||
|
@ -8,6 +8,7 @@ module.exports = {
|
||||
content: {
|
||||
relative: true,
|
||||
files: [
|
||||
"./app/**/*.{js,ts,jsx,tsx}",
|
||||
"./components/**/*.tsx",
|
||||
"./constants/**/*.{js,ts,jsx,tsx}",
|
||||
"./layouts/**/*.tsx",
|
||||
|
@ -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
42
space/types/project.d.ts
vendored
Normal 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;
|
||||
};
|
@ -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;
|
9
web/app/[workspaceSlug]/@header/active-cycles/page.tsx
Normal file
9
web/app/[workspaceSlug]/@header/active-cycles/page.tsx
Normal 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;
|
@ -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;
|
9
web/app/[workspaceSlug]/@header/analytics/page.tsx
Normal file
9
web/app/[workspaceSlug]/@header/analytics/page.tsx
Normal 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;
|
@ -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;
|
9
web/app/[workspaceSlug]/@header/page.tsx
Normal file
9
web/app/[workspaceSlug]/@header/page.tsx
Normal 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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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 },
|
@ -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;
|
@ -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;
|
@ -0,0 +1,2 @@
|
||||
import DefaultProjectArchivesHeader from "../page";
|
||||
export default DefaultProjectArchivesHeader;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -0,0 +1,2 @@
|
||||
import DefaultProjectSettingHeader from "../page";
|
||||
export default DefaultProjectSettingHeader;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
13
web/app/[workspaceSlug]/@header/projects/page.tsx
Normal file
13
web/app/[workspaceSlug]/@header/projects/page.tsx
Normal 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;
|
@ -0,0 +1,2 @@
|
||||
import DefaultWorkspaceSettingsHeader from "../page";
|
||||
export default DefaultWorkspaceSettingsHeader;
|
@ -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;
|
9
web/app/[workspaceSlug]/@header/settings/page.tsx
Normal file
9
web/app/[workspaceSlug]/@header/settings/page.tsx
Normal 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;
|
@ -0,0 +1,2 @@
|
||||
import DefaultWorkspaceViewsHeader from "../page";
|
||||
export default DefaultWorkspaceViewsHeader;
|
@ -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;
|
9
web/app/[workspaceSlug]/@header/workspace-views/page.tsx
Normal file
9
web/app/[workspaceSlug]/@header/workspace-views/page.tsx
Normal 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;
|
@ -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;
|
@ -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;
|
26
web/app/[workspaceSlug]/app-header-wrapper.tsx
Normal file
26
web/app/[workspaceSlug]/app-header-wrapper.tsx
Normal 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;
|
25
web/app/[workspaceSlug]/layout.tsx
Normal file
25
web/app/[workspaceSlug]/layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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;
|
@ -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;
|
15
web/app/[workspaceSlug]/profile/[userId]/assigned/page.tsx
Normal file
15
web/app/[workspaceSlug]/profile/[userId]/assigned/page.tsx
Normal 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;
|
16
web/app/[workspaceSlug]/profile/[userId]/created/page.tsx
Normal file
16
web/app/[workspaceSlug]/profile/[userId]/created/page.tsx
Normal 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);
|
@ -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;
|
@ -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"
|
||||
}`}
|
@ -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;
|
16
web/app/[workspaceSlug]/profile/[userId]/subscribed/page.tsx
Normal file
16
web/app/[workspaceSlug]/profile/[userId]/subscribed/page.tsx
Normal 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);
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
63
web/app/[workspaceSlug]/projects/[projectId]/inbox/page.tsx
Normal file
63
web/app/[workspaceSlug]/projects/[projectId]/inbox/page.tsx
Normal 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;
|
@ -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;
|
@ -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;
|
13
web/app/[workspaceSlug]/projects/[projectId]/layout.tsx
Normal file
13
web/app/[workspaceSlug]/projects/[projectId]/layout.tsx
Normal 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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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;
|
@ -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
Loading…
Reference in New Issue
Block a user