From 7278b5727ff341a407706f0c143d3ecbce06de9d Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Tue, 31 Jan 2023 19:23:51 +0530 Subject: [PATCH 1/5] refactor: issue details page (#211) --- .../projects/[projectId]/issues/[issueId].tsx | 80 +++++-------------- apps/app/types/issues.d.ts | 12 ++- 2 files changed, 30 insertions(+), 62 deletions(-) diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx index a97c94ca7..dd291c8df 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/issues/[issueId].tsx @@ -18,27 +18,17 @@ import AddAsSubIssue from "components/project/issues/issue-detail/add-as-sub-iss import IssueDetailSidebar from "components/project/issues/issue-detail/issue-detail-sidebar"; import AddIssueComment from "components/project/issues/issue-detail/comment/issue-comment-section"; import IssueActivitySection from "components/project/issues/issue-detail/activity"; -import { - IssueDescriptionForm, - IssueDescriptionFormValues, - SubIssueList, - CreateUpdateIssueModal, -} from "components/issues"; +import { IssueDescriptionForm, SubIssueList, CreateUpdateIssueModal } from "components/issues"; // ui -import { Loader, HeaderButton, CustomMenu } from "components/ui"; +import { Loader, CustomMenu } from "components/ui"; import { Breadcrumbs } from "components/breadcrumbs"; // icons -import { ChevronLeftIcon, ChevronRightIcon, PlusIcon } from "@heroicons/react/24/outline"; +import { PlusIcon } from "@heroicons/react/24/outline"; // types import { IIssue } from "types"; import type { NextPage, NextPageContext } from "next"; // fetch-keys -import { - PROJECT_ISSUES_LIST, - PROJECT_ISSUES_ACTIVITY, - ISSUE_DETAILS, - SUB_ISSUES, -} from "constants/fetch-keys"; +import { PROJECT_ISSUES_ACTIVITY, ISSUE_DETAILS, SUB_ISSUES } from "constants/fetch-keys"; const defaultValues = { name: "", @@ -81,15 +71,6 @@ const IssueDetailsPage: NextPage = () => { : null ); - const { data: issues } = useSWR( - workspaceSlug && projectId - ? PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string) - : null, - workspaceSlug && projectId - ? () => issuesService.getIssues(workspaceSlug as string, projectId as string) - : null - ); - const { data: issueActivities, mutate: mutateIssueActivities } = useSWR( workspaceSlug && projectId && issueId ? PROJECT_ISSUES_ACTIVITY(issueId as string) : null, workspaceSlug && projectId && issueId @@ -102,17 +83,22 @@ const IssueDetailsPage: NextPage = () => { : null ); + const { data: siblingIssues } = useSWR( + workspaceSlug && projectId && issueDetails?.parent ? SUB_ISSUES(issueDetails.parent) : null, + workspaceSlug && projectId && issueDetails?.parent + ? () => + issuesService.subIssues( + workspaceSlug as string, + projectId as string, + issueDetails.parent ?? "" + ) + : null + ); + const { reset, control, watch } = useForm({ defaultValues, }); - const prevIssue = issues?.results[issues?.results.findIndex((issue) => issue.id === issueId) - 1]; - const nextIssue = issues?.results[issues?.results.findIndex((issue) => issue.id === issueId) + 1]; - - const siblingIssues = - issueDetails && - issues?.results.filter((i) => i.parent === issueDetails.parent && i.id !== issueId); - useEffect(() => { if (issueDetails) { mutateIssueActivities(); @@ -191,32 +177,6 @@ const IssueDetailsPage: NextPage = () => { /> } - right={ -
- { - if (!prevIssue) return; - router.push(`/${workspaceSlug}/projects/${prevIssue.project}/issues/${prevIssue.id}`); - }} - /> - { - if (!nextIssue) return; - router.push( - `/${workspaceSlug}/projects/${nextIssue.project}/issues/${nextIssue?.id}` - ); - }} - position="reverse" - /> -
- } > {isOpen && ( { /> {issueDetails.project_detail.identifier}- - {issues?.results.find((i) => i.id === issueDetails.parent)?.sequence_id} + {issueDetails.parent_detail?.sequence_id} - {issues?.results - .find((i) => i.id === issueDetails.parent) - ?.name.substring(0, 50)} + {issueDetails.parent_detail?.name.substring(0, 50)} {siblingIssues && siblingIssues.length > 0 ? ( - siblingIssues.map((issue) => ( + siblingIssues.map((issue: IIssue) => ( Date: Tue, 31 Jan 2023 19:24:45 +0530 Subject: [PATCH 2/5] fix: consistent icons and modal fixes (#216) * fix: consistent icons and modal fixes * fix: total worspace members * fix: sub issue mutation --- .../components/account/email-signin-form.tsx | 4 +- .../common/bulk-delete-issues-modal.tsx | 94 +++++++++---------- apps/app/components/cycles/select.tsx | 5 +- apps/app/components/issues/form.tsx | 7 +- .../project/cycles/stats-view/single-stat.tsx | 12 +-- .../issues/issue-detail/add-as-sub-issue.tsx | 18 +++- .../comment/issue-comment-card.tsx | 9 +- .../comment/issue-comment-section.tsx | 8 +- .../issue-detail-sidebar/select-cycle.tsx | 8 +- .../rich-text-editor/toolbar/index.tsx | 7 +- .../components/workspace/sidebar-dropdown.tsx | 3 +- apps/app/layouts/app-layout/app-header.tsx | 40 ++++---- apps/app/layouts/app-layout/app-sidebar.tsx | 2 - .../projects/[projectId]/cycles/[cycleId].tsx | 13 +-- .../projects/[projectId]/issues/[issueId].tsx | 19 +++- .../pages/[workspaceSlug]/settings/index.tsx | 1 + apps/app/styles/editor.css | 4 + 17 files changed, 137 insertions(+), 117 deletions(-) diff --git a/apps/app/components/account/email-signin-form.tsx b/apps/app/components/account/email-signin-form.tsx index 3d13ca5a1..5e47f36d3 100644 --- a/apps/app/components/account/email-signin-form.tsx +++ b/apps/app/components/account/email-signin-form.tsx @@ -28,7 +28,7 @@ export const EmailSignInForm: FC = (props) => { or -
+ {/*
-
+
*/} ); diff --git a/apps/app/components/common/bulk-delete-issues-modal.tsx b/apps/app/components/common/bulk-delete-issues-modal.tsx index 8b8125b48..64a65c22a 100644 --- a/apps/app/components/common/bulk-delete-issues-modal.tsx +++ b/apps/app/components/common/bulk-delete-issues-modal.tsx @@ -24,8 +24,7 @@ import { IIssue, IssueResponse } from "types"; import { PROJECT_ISSUES_LIST, PROJECT_DETAILS } from "constants/fetch-keys"; type FormInput = { - issue_ids: string[]; - cycleId: string; + delete_issue_ids: string[]; }; type Props = { @@ -61,17 +60,27 @@ const BulkDeleteIssuesModal: React.FC = ({ isOpen, setIsOpen }) => { const { setToastAlert } = useToast(); const { - register, handleSubmit, + watch, reset, + setValue, formState: { isSubmitting }, - } = useForm(); + } = useForm({ + defaultValues: { + delete_issue_ids: [], + }, + }); const filteredIssues: IIssue[] = query === "" ? issues?.results ?? [] - : issues?.results.filter((issue) => issue.name.toLowerCase().includes(query.toLowerCase())) ?? - []; + : issues?.results.filter( + (issue) => + issue.name.toLowerCase().includes(query.toLowerCase()) || + `${issue.project_detail.identifier}-${issue.sequence_id}` + .toLowerCase() + .includes(query.toLowerCase()) + ) ?? []; const handleClose = () => { setIsOpen(false); @@ -80,7 +89,7 @@ const BulkDeleteIssuesModal: React.FC = ({ isOpen, setIsOpen }) => { }; const handleDelete: SubmitHandler = async (data) => { - if (!data.issue_ids || data.issue_ids.length === 0) { + if (!data.delete_issue_ids || data.delete_issue_ids.length === 0) { setToastAlert({ title: "Error", type: "error", @@ -89,30 +98,34 @@ const BulkDeleteIssuesModal: React.FC = ({ isOpen, setIsOpen }) => { return; } - if (!Array.isArray(data.issue_ids)) data.issue_ids = [data.issue_ids]; + if (!Array.isArray(data.delete_issue_ids)) data.delete_issue_ids = [data.delete_issue_ids]; if (workspaceSlug && projectId) { await issuesServices - .bulkDeleteIssues(workspaceSlug as string, projectId as string, data) + .bulkDeleteIssues(workspaceSlug as string, projectId as string, { + issue_ids: data.delete_issue_ids, + }) .then((res) => { setToastAlert({ title: "Success", type: "success", message: res.message, }); + mutate( PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), (prevData) => ({ ...(prevData as IssueResponse), count: (prevData?.results ?? []).filter( - (p) => !data.issue_ids.some((id) => p.id === id) + (p) => !data.delete_issue_ids.some((id) => p.id === id) ).length, results: (prevData?.results ?? []).filter( - (p) => !data.issue_ids.some((id) => p.id === id) + (p) => !data.delete_issue_ids.some((id) => p.id === id) ), }), false ); + handleClose(); }) .catch((e) => { console.log(e); @@ -123,18 +136,6 @@ const BulkDeleteIssuesModal: React.FC = ({ isOpen, setIsOpen }) => { return ( setQuery("")} appear> - -
- -
= ({ isOpen, setIsOpen }) => { leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > - +
- + { + const selectedIssues = watch("delete_issue_ids"); + if (selectedIssues.includes(val)) + setValue( + "delete_issue_ids", + selectedIssues.filter((i) => i !== val) + ); + else { + const newToDelete = selectedIssues; + newToDelete.push(val); + + setValue("delete_issue_ids", newToDelete); + } + }} + >
-
diff --git a/apps/app/components/project/issues/issue-detail/add-as-sub-issue.tsx b/apps/app/components/project/issues/issue-detail/add-as-sub-issue.tsx index 46dc55594..95eae4555 100644 --- a/apps/app/components/project/issues/issue-detail/add-as-sub-issue.tsx +++ b/apps/app/components/project/issues/issue-detail/add-as-sub-issue.tsx @@ -11,7 +11,7 @@ import { RectangleStackIcon, MagnifyingGlassIcon } from "@heroicons/react/24/out // services import issuesServices from "services/issues.service"; // types -import { IIssue } from "types"; +import { IIssue, IssueResponse } from "types"; // constants import { PROJECT_ISSUES_LIST, SUB_ISSUES } from "constants/fetch-keys"; @@ -54,6 +54,22 @@ const AddAsSubIssue: React.FC = ({ isOpen, setIsOpen, parent }) => { .patchIssue(workspaceSlug as string, projectId as string, issueId, { parent: parent?.id }) .then((res) => { mutate(SUB_ISSUES(parent?.id ?? "")); + mutate( + PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), + (prevData) => ({ + ...(prevData as IssueResponse), + results: (prevData?.results ?? []).map((p) => { + if (p.id === res.id) + return { + ...p, + ...res, + }; + + return p; + }), + }), + false + ); }) .catch((e) => { console.log(e); diff --git a/apps/app/components/project/issues/issue-detail/comment/issue-comment-card.tsx b/apps/app/components/project/issues/issue-detail/comment/issue-comment-card.tsx index e2b17ea00..ec270ff25 100644 --- a/apps/app/components/project/issues/issue-detail/comment/issue-comment-card.tsx +++ b/apps/app/components/project/issues/issue-detail/comment/issue-comment-card.tsx @@ -1,6 +1,5 @@ -// react import React, { useEffect, useState } from "react"; -// next + import Image from "next/image"; import dynamic from "next/dynamic"; @@ -8,14 +7,14 @@ import dynamic from "next/dynamic"; import { useForm } from "react-hook-form"; // icons import { CheckIcon, XMarkIcon } from "@heroicons/react/24/outline"; -// types -import type { IIssueComment } from "types"; // hooks import useUser from "hooks/use-user"; // ui import { CustomMenu } from "components/ui"; // helpers import { timeAgo } from "helpers/date-time.helper"; +// types +import type { IIssueComment } from "types"; const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), { ssr: false }); @@ -76,7 +75,7 @@ const CommentCard: React.FC = ({ comment, onSubmit, handleCommentDeletion {timeAgo(comment.created_at)}

-
+
{isEditing ? ( import("components/rich-text-editor"), { ssr: false, @@ -83,7 +83,7 @@ const AddIssueComment: React.FC<{ return (
-
+
= ({ issueDetail, handleCycleChange }) => { return (
- +

Cycle

diff --git a/apps/app/components/rich-text-editor/toolbar/index.tsx b/apps/app/components/rich-text-editor/toolbar/index.tsx index 3a3292eeb..f5ff2db70 100644 --- a/apps/app/components/rich-text-editor/toolbar/index.tsx +++ b/apps/app/components/rich-text-editor/toolbar/index.tsx @@ -32,11 +32,8 @@ export const RichTextToolbar: React.FC = () => (
- {/*
- -
*/} -
+ {/*
-
+
*/}
); diff --git a/apps/app/components/workspace/sidebar-dropdown.tsx b/apps/app/components/workspace/sidebar-dropdown.tsx index fef4a8fee..5a892e069 100644 --- a/apps/app/components/workspace/sidebar-dropdown.tsx +++ b/apps/app/components/workspace/sidebar-dropdown.tsx @@ -155,7 +155,8 @@ export const WorkspaceSidebarDropdown = () => {
{workspace.name}
- {workspace.total_members} members + {workspace.total_members}{" "} + {workspace.total_members > 1 ? "members" : "member"}
diff --git a/apps/app/layouts/app-layout/app-header.tsx b/apps/app/layouts/app-layout/app-header.tsx index 4bafcc544..439db92ba 100644 --- a/apps/app/layouts/app-layout/app-header.tsx +++ b/apps/app/layouts/app-layout/app-header.tsx @@ -10,28 +10,24 @@ type Props = { setToggleSidebar: React.Dispatch>; }; -const Header: React.FC = ({ breadcrumbs, left, right, setToggleSidebar }) => { - return ( - <> -
-
-
- -
- {breadcrumbs} - {left} -
- {right} +const Header: React.FC = ({ breadcrumbs, left, right, setToggleSidebar }) => ( +
+
+
+
- - ); -}; + {breadcrumbs} + {left} +
+ {right} +
+); export default Header; diff --git a/apps/app/layouts/app-layout/app-sidebar.tsx b/apps/app/layouts/app-layout/app-sidebar.tsx index 48370636e..5a58384a6 100644 --- a/apps/app/layouts/app-layout/app-sidebar.tsx +++ b/apps/app/layouts/app-layout/app-sidebar.tsx @@ -1,5 +1,3 @@ -import { Dispatch, SetStateAction } from "react"; - // hooks import useTheme from "hooks/use-theme"; // components diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx index f4512a985..1438a6831 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/cycles/[cycleId].tsx @@ -10,13 +10,6 @@ import { requiredAdmin, requiredAuth } from "lib/auth"; import AppLayout from "layouts/app-layout"; // contexts import { IssueViewContextProvider } from "contexts/issue-view.context"; -// icons -import { - ArrowLeftIcon, - ArrowPathIcon, - ListBulletIcon, - PlusIcon, -} from "@heroicons/react/24/outline"; // components import CyclesListView from "components/project/cycles/list-view"; import CyclesBoardView from "components/project/cycles/board-view"; @@ -33,6 +26,8 @@ import projectService from "services/project.service"; import { CustomMenu, EmptySpace, EmptySpaceItem, Spinner } from "components/ui"; import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs"; // icons +import { ArrowLeftIcon, ListBulletIcon, PlusIcon } from "@heroicons/react/24/outline"; +import { CyclesIcon } from "components/icons"; // types import { CycleIssueResponse, IIssue, SelectIssue, UserAuth } from "types"; import { NextPageContext } from "next"; @@ -203,7 +198,7 @@ const SingleCycle: React.FC = (props) => { - + {cycles?.find((c) => c.id === cycleId)?.name} } @@ -268,7 +263,7 @@ const SingleCycle: React.FC = (props) => { { .then((res) => { mutate(SUB_ISSUES(issueDetails?.id ?? "")); mutateIssueActivities(); + + mutate( + PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), + (prevData) => ({ + ...(prevData as IssueResponse), + results: (prevData?.results ?? []).map((p) => { + if (p.id === res.id) + return { + ...p, + ...res, + }; + + return p; + }), + }), + false + ); }) .catch((e) => { console.error(e); diff --git a/apps/app/pages/[workspaceSlug]/settings/index.tsx b/apps/app/pages/[workspaceSlug]/settings/index.tsx index 4d7c53dce..a3cc32903 100644 --- a/apps/app/pages/[workspaceSlug]/settings/index.tsx +++ b/apps/app/pages/[workspaceSlug]/settings/index.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from "react"; import Image from "next/image"; import { useRouter } from "next/router"; import useSWR, { mutate } from "swr"; + // react-hook-form import { Controller, useForm } from "react-hook-form"; // react-dropzone diff --git a/apps/app/styles/editor.css b/apps/app/styles/editor.css index 07fcec355..45deb0dc6 100644 --- a/apps/app/styles/editor.css +++ b/apps/app/styles/editor.css @@ -354,6 +354,10 @@ img.ProseMirror-separator { margin-bottom: 1em; } +.remirror-editor-wrapper .remirror-editor { + min-height: 150px; +} + .issue-comments-section .remirror-editor-wrapper .remirror-editor { min-height: 50px; } From 0cb4edab545204f201dd4744d737579cb4aa602d Mon Sep 17 00:00:00 2001 From: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com> Date: Tue, 31 Jan 2023 19:49:02 +0530 Subject: [PATCH 3/5] fix: back migration for identifiers without workspaces (#212) --- apiserver/back_migration.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/apiserver/back_migration.py b/apiserver/back_migration.py index 33513f15c..57ded0ba4 100644 --- a/apiserver/back_migration.py +++ b/apiserver/back_migration.py @@ -1,5 +1,5 @@ # All the python scripts that are used for back migrations - +from plane.db.models import ProjectIdentifier from plane.db.models import Issue, IssueComment # Update description and description html values for old descriptions @@ -40,3 +40,21 @@ def update_comments(): except Exception as e: print(e) print("Failed") + + +def update_project_identifiers(): + try: + project_identifiers = ProjectIdentifier.objects.filter(workspace_id=None).select_related("project", "project__workspace") + updated_identifiers = [] + + for identifier in project_identifiers: + identifier.workspace_id = identifier.project.workspace_id + updated_identifiers.append(identifier) + + ProjectIdentifier.objects.bulk_update( + updated_identifiers, ["workspace_id"], batch_size=50 + ) + print("Success") + except Exception as e: + print(e) + print("Failed") From fbb045436cb301e5bfbcaa6d7d5937e237f4d6c0 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Tue, 31 Jan 2023 19:51:33 +0530 Subject: [PATCH 4/5] fix: text ellipsis fix (#217) Co-authored-by: Anmol Singh Bhatia --- apps/app/components/project/card.tsx | 2 +- apps/app/components/project/sidebar-list.tsx | 4 +++- apps/app/components/sidebar/projects-list.tsx | 6 ++++-- apps/app/pages/[workspaceSlug]/index.tsx | 4 +++- apps/app/pages/onboarding/index.tsx | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/app/components/project/card.tsx b/apps/app/components/project/card.tsx index dd6d96e32..0ddaf1cd7 100644 --- a/apps/app/components/project/card.tsx +++ b/apps/app/components/project/card.tsx @@ -52,7 +52,7 @@ export const ProjectCard: React.FC = (props) => { {project.icon && ( {String.fromCodePoint(parseInt(project.icon))} )} - + {project.name} {project.identifier} diff --git a/apps/app/components/project/sidebar-list.tsx b/apps/app/components/project/sidebar-list.tsx index 17fbb84c8..e5ff937f4 100644 --- a/apps/app/components/project/sidebar-list.tsx +++ b/apps/app/components/project/sidebar-list.tsx @@ -99,7 +99,9 @@ export const ProjectSidebarList: FC = () => { {!sidebarCollapse && ( - {project?.name} + + {project?.name} + = ({ navigation, sidebarCollapse }) => { )} {!sidebarCollapse && ( - - {project?.name} + + + {project?.name} + { {project?.name.charAt(0)} )} -

{project.name}

+

+ {project.name} +

diff --git a/apps/app/pages/onboarding/index.tsx b/apps/app/pages/onboarding/index.tsx index 4702034ca..68d8f70f9 100644 --- a/apps/app/pages/onboarding/index.tsx +++ b/apps/app/pages/onboarding/index.tsx @@ -48,7 +48,7 @@ const Onboarding: NextPage = () => { )}
) : ( -
+
{step === 4 ? ( From d2df3330fafcad6ad22903177b53dd62681830b1 Mon Sep 17 00:00:00 2001 From: sriram veeraghanta Date: Tue, 31 Jan 2023 19:52:03 +0530 Subject: [PATCH 5/5] Turbo Repo Env Fixes for Docs App. (#218) * turbo js env update * turbo repo env fixes --- apps/docs/src/components/Search.jsx | 2 +- turbo.json | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/docs/src/components/Search.jsx b/apps/docs/src/components/Search.jsx index 78b345d69..3b63d8a4d 100644 --- a/apps/docs/src/components/Search.jsx +++ b/apps/docs/src/components/Search.jsx @@ -41,7 +41,7 @@ function useAutocomplete() { return item.query }, getItemUrl({ item }) { - let url = new URL(item.url) + const url = new URL(item.url) return `${url.pathname}${url.hash}` }, onSelect({ itemUrl }) { diff --git a/turbo.json b/turbo.json index 7df2292e8..ddc3b9cc5 100644 --- a/turbo.json +++ b/turbo.json @@ -3,7 +3,10 @@ "globalEnv": [ "NEXT_PUBLIC_GITHUB_ID", "NEXT_PUBLIC_GOOGLE_CLIENTID", - "NEXT_PUBLIC_API_BASE_URL" + "NEXT_PUBLIC_API_BASE_URL", + "NEXT_PUBLIC_DOCSEARCH_API_KEY", + "NEXT_PUBLIC_DOCSEARCH_APP_ID", + "NEXT_PUBLIC_DOCSEARCH_INDEX_NAME" ], "pipeline": { "build": {