Skip to content

Commit

Permalink
chore: Error Handling and Validation Updates (#3351)
Browse files Browse the repository at this point in the history
* fix: handled undefined issue_id in list layout

* chore: updated label select dropdown in the issue detail

* fix: peekoverview issue is resolved

* chore: user role validation for issue details.

* fix: Link, Attachement, parent mutation

* build-error: build error resolved in peekoverview

* chore: user role validation for issue details.

* chore: user role validation for `issue description`, `parent`, `relation` and `subscription`.

* chore: issue subscription mutation

* chore: user role validation for `labels` in issue details.

---------

Co-authored-by: Prateek Shourya <prateekshourya29@gmail.com>
  • Loading branch information
gurusainath and prateekshourya29 authored Jan 11, 2024
1 parent 3c9926d commit 57d5ff7
Show file tree
Hide file tree
Showing 23 changed files with 431 additions and 189 deletions.
28 changes: 17 additions & 11 deletions web/components/issues/attachment/attachment-detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ import { getFileIcon } from "components/icons";
import { truncateText } from "helpers/string.helper";
import { renderFormattedDate } from "helpers/date-time.helper";
import { convertBytesToSize, getFileExtension, getFileName } from "helpers/attachment.helper";
// type
import { TIssueAttachmentsList } from "./attachments-list";
// types
import { TAttachmentOperations } from "./root";

export type TIssueAttachmentsDetail = TIssueAttachmentsList & {
type TAttachmentOperationsRemoveModal = Exclude<TAttachmentOperations, "create">;

type TIssueAttachmentsDetail = {
attachmentId: string;
handleAttachmentOperations: TAttachmentOperationsRemoveModal;
disabled?: boolean;
};

export const IssueAttachmentsDetail: FC<TIssueAttachmentsDetail> = (props) => {
// props
const { attachmentId, handleAttachmentOperations } = props;
const { attachmentId, handleAttachmentOperations, disabled } = props;
// store hooks
const { getUserDetails } = useMember();
const {
Expand Down Expand Up @@ -75,13 +79,15 @@ export const IssueAttachmentsDetail: FC<TIssueAttachmentsDetail> = (props) => {
</div>
</Link>

<button
onClick={() => {
setAttachmentDeleteModal(true);
}}
>
<X className="h-4 w-4 text-custom-text-200 hover:text-custom-text-100" />
</button>
{!disabled && (
<button
onClick={() => {
setAttachmentDeleteModal(true);
}}
>
<X className="h-4 w-4 text-custom-text-200 hover:text-custom-text-100" />
</button>
)}
</div>
</>
);
Expand Down
20 changes: 15 additions & 5 deletions web/components/issues/attachment/attachments-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,35 @@ import { IssueAttachmentsDetail } from "./attachment-detail";
// types
import { TAttachmentOperations } from "./root";

export type TAttachmentOperationsRemoveModal = Exclude<TAttachmentOperations, "create">;
type TAttachmentOperationsRemoveModal = Exclude<TAttachmentOperations, "create">;

export type TIssueAttachmentsList = {
type TIssueAttachmentsList = {
issueId: string;
handleAttachmentOperations: TAttachmentOperationsRemoveModal;
disabled?: boolean;
};

export const IssueAttachmentsList: FC<TIssueAttachmentsList> = observer((props) => {
const { handleAttachmentOperations } = props;
const { issueId, handleAttachmentOperations, disabled } = props;
// store hooks
const {
attachment: { issueAttachments },
attachment: { getAttachmentsByIssueId },
} = useIssueDetail();

const issueAttachments = getAttachmentsByIssueId(issueId);

if (!issueAttachments) return <></>;

return (
<>
{issueAttachments &&
issueAttachments.length > 0 &&
issueAttachments.map((attachmentId) => (
<IssueAttachmentsDetail attachmentId={attachmentId} handleAttachmentOperations={handleAttachmentOperations} />
<IssueAttachmentsDetail
attachmentId={attachmentId}
disabled={disabled}
handleAttachmentOperations={handleAttachmentOperations}
/>
))}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import { Button } from "@plane/ui";
import { getFileName } from "helpers/attachment.helper";
// types
import type { TIssueAttachment } from "@plane/types";
import { TIssueAttachmentsList } from "./attachments-list";
import { TAttachmentOperations } from "./root";

type Props = TIssueAttachmentsList & {
export type TAttachmentOperationsRemoveModal = Exclude<TAttachmentOperations, "create">;

type Props = {
isOpen: boolean;
setIsOpen: Dispatch<SetStateAction<boolean>>;
data: TIssueAttachment;
handleAttachmentOperations: TAttachmentOperationsRemoveModal;
};

export const IssueAttachmentDeleteModal: FC<Props> = (props) => {
Expand Down
13 changes: 8 additions & 5 deletions web/components/issues/attachment/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ export type TIssueAttachmentRoot = {
workspaceSlug: string;
projectId: string;
issueId: string;
is_archived: boolean;
is_editable: boolean;
disabled?: boolean;
};

export type TAttachmentOperations = {
Expand All @@ -21,7 +20,7 @@ export type TAttachmentOperations = {

export const IssueAttachmentRoot: FC<TIssueAttachmentRoot> = (props) => {
// props
const { workspaceSlug, projectId, issueId, is_archived, is_editable } = props;
const { workspaceSlug, projectId, issueId, disabled = false } = props;
// hooks
const { createAttachment, removeAttachment } = useIssueDetail();
const { setToastAlert } = useToast();
Expand Down Expand Up @@ -72,10 +71,14 @@ export const IssueAttachmentRoot: FC<TIssueAttachmentRoot> = (props) => {
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4">
<IssueAttachmentUpload
workspaceSlug={workspaceSlug}
disabled={is_editable}
disabled={disabled}
handleAttachmentOperations={handleAttachmentOperations}
/>
<IssueAttachmentsList
issueId={issueId}
disabled={disabled}
handleAttachmentOperations={handleAttachmentOperations}
/>
<IssueAttachmentsList handleAttachmentOperations={handleAttachmentOperations} />
</div>
</div>
);
Expand Down
65 changes: 36 additions & 29 deletions web/components/issues/description-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import useReloadConfirmations from "hooks/use-reload-confirmation";
import debounce from "lodash/debounce";
// components
import { TextArea } from "@plane/ui";
import { RichTextEditor } from "@plane/rich-text-editor";
import { RichReadOnlyEditor, RichTextEditor } from "@plane/rich-text-editor";
// types
import { TIssue } from "@plane/types";
import { TIssueOperations } from "./issue-detail";
Expand All @@ -29,15 +29,15 @@ export interface IssueDetailsProps {
project_id?: string;
};
issueOperations: TIssueOperations;
isAllowed: boolean;
disabled: boolean;
isSubmitting: "submitting" | "submitted" | "saved";
setIsSubmitting: (value: "submitting" | "submitted" | "saved") => void;
}

const fileService = new FileService();

export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
const { workspaceSlug, projectId, issueId, issue, issueOperations, isAllowed, isSubmitting, setIsSubmitting } = props;
const { workspaceSlug, projectId, issueId, issue, issueOperations, disabled, isSubmitting, setIsSubmitting } = props;
// states
const [characterLimit, setCharacterLimit] = useState(false);

Expand Down Expand Up @@ -119,7 +119,7 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
return (
<div className="relative">
<div className="relative">
{isAllowed ? (
{!disabled ? (
<Controller
name="name"
control={control}
Expand All @@ -141,14 +141,13 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
className="min-h-min block w-full resize-none overflow-hidden rounded border-none bg-transparent px-3 py-2 text-2xl font-medium outline-none ring-0 focus:ring-1 focus:ring-custom-primary"
hasError={Boolean(errors?.name)}
role="textbox"
disabled={!isAllowed}
/>
)}
/>
) : (
<h4 className="break-words text-2xl font-semibold">{issue.name}</h4>
)}
{characterLimit && isAllowed && (
{characterLimit && !disabled && (
<div className="pointer-events-none absolute bottom-1 right-1 z-[2] rounded bg-custom-background-100 p-0.5 text-xs text-custom-text-200">
<span className={`${watch("name").length === 0 || watch("name").length > 255 ? "text-red-500" : ""}`}>
{watch("name").length}
Expand All @@ -162,29 +161,37 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
<Controller
name="description_html"
control={control}
render={({ field: { onChange } }) => (
<RichTextEditor
cancelUploadImage={fileService.cancelUpload}
uploadFile={fileService.getUploadFileFunction(workspaceSlug)}
deleteFile={fileService.deleteImage}
restoreFile={fileService.restoreImage}
value={localIssueDescription.description_html}
rerenderOnPropsChange={localIssueDescription}
setShouldShowAlert={setShowAlert}
setIsSubmitting={setIsSubmitting}
dragDropEnabled
customClassName={isAllowed ? "min-h-[150px] shadow-sm" : "!p-0 !pt-2 text-custom-text-200"}
noBorder={!isAllowed}
onChange={(description: Object, description_html: string) => {
setShowAlert(true);
setIsSubmitting("submitting");
onChange(description_html);
debouncedFormSave();
}}
mentionSuggestions={mentionSuggestions}
mentionHighlights={mentionHighlights}
/>
)}
render={({ field: { onChange } }) =>
!disabled ? (
<RichTextEditor
cancelUploadImage={fileService.cancelUpload}
uploadFile={fileService.getUploadFileFunction(workspaceSlug)}
deleteFile={fileService.deleteImage}
restoreFile={fileService.restoreImage}
value={localIssueDescription.description_html}
rerenderOnPropsChange={localIssueDescription}
setShouldShowAlert={setShowAlert}
setIsSubmitting={setIsSubmitting}
dragDropEnabled
customClassName="min-h-[150px] shadow-sm"
onChange={(description: Object, description_html: string) => {
setShowAlert(true);
setIsSubmitting("submitting");
onChange(description_html);
debouncedFormSave();
}}
mentionSuggestions={mentionSuggestions}
mentionHighlights={mentionHighlights}
/>
) : (
<RichReadOnlyEditor
value={localIssueDescription.description_html}
customClassName="!p-0 !pt-2 text-custom-text-200"
noBorder={disabled}
mentionHighlights={mentionHighlights}
/>
)
}
/>
</div>
</div>
Expand Down
8 changes: 2 additions & 6 deletions web/components/issues/issue-detail/label/create-label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,11 @@ export const LabelCreate: FC<ILabelCreate> = (props) => {
return (
<>
<div
className="flex-shrink-0 transition-all relative flex items-center gap-1 cursor-pointer border border-custom-border-100 rounded-full text-xs p-0.5 px-2 group hover:border-red-500/50 hover:bg-red-500/20"
className="flex-shrink-0 transition-all relative flex items-center gap-1 cursor-pointer border border-custom-border-100 rounded-full text-xs p-0.5 px-2 hover:bg-custom-background-90 text-custom-text-300 hover:text-custom-text-200"
onClick={handleIsCreateToggle}
>
<div className="flex-shrink-0">
{isCreateToggle ? (
<X className="transition-all h-2.5 w-2.5 group-hover:text-red-500" />
) : (
<Plus className="transition-all h-2.5 w-2.5 group-hover:text-red-500" />
)}
{isCreateToggle ? <X className="h-2.5 w-2.5" /> : <Plus className="h-2.5 w-2.5" />}
</div>
<div className="flex-shrink-0">{isCreateToggle ? "Cancel" : "New"}</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions web/components/issues/issue-detail/label/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ export * from "./root";
export * from "./label-list";
export * from "./label-list-item";
export * from "./create-label";
export * from "./select/root";
export * from "./select/label-select";
15 changes: 10 additions & 5 deletions web/components/issues/issue-detail/label/label-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ type TLabelListItem = {
issueId: string;
labelId: string;
labelOperations: TLabelOperations;
disabled: boolean;
};

export const LabelListItem: FC<TLabelListItem> = (props) => {
const { workspaceSlug, projectId, issueId, labelId, labelOperations } = props;
const { workspaceSlug, projectId, issueId, labelId, labelOperations, disabled } = props;
// hooks
const {
issue: { getIssueById },
Expand All @@ -34,7 +35,9 @@ export const LabelListItem: FC<TLabelListItem> = (props) => {
return (
<div
key={labelId}
className="transition-all relative flex items-center gap-1 cursor-pointer border border-custom-border-100 rounded-full text-xs p-0.5 px-1 group hover:border-red-500/50 hover:bg-red-500/20"
className={`transition-all relative flex items-center gap-1 border border-custom-border-100 rounded-full text-xs p-0.5 px-1 group ${
!disabled ? "cursor-pointer hover:border-red-500/50 hover:bg-red-500/20" : "cursor-not-allowed"
} `}
onClick={handleLabel}
>
<div
Expand All @@ -44,9 +47,11 @@ export const LabelListItem: FC<TLabelListItem> = (props) => {
}}
/>
<div className="flex-shrink-0">{label.name}</div>
<div className="flex-shrink-0">
<X className="transition-all h-2.5 w-2.5 group-hover:text-red-500" />
</div>
{!disabled && (
<div className="flex-shrink-0">
<X className="transition-all h-2.5 w-2.5 group-hover:text-red-500" />
</div>
)}
</div>
);
};
4 changes: 3 additions & 1 deletion web/components/issues/issue-detail/label/label-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ type TLabelList = {
projectId: string;
issueId: string;
labelOperations: TLabelOperations;
disabled: boolean;
};

export const LabelList: FC<TLabelList> = (props) => {
const { workspaceSlug, projectId, issueId, labelOperations } = props;
const { workspaceSlug, projectId, issueId, labelOperations, disabled } = props;
// hooks
const {
issue: { getIssueById },
Expand All @@ -33,6 +34,7 @@ export const LabelList: FC<TLabelList> = (props) => {
issueId={issueId}
labelId={labelId}
labelOperations={labelOperations}
disabled={disabled}
/>
))}
</>
Expand Down
27 changes: 18 additions & 9 deletions web/components/issues/issue-detail/label/root.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { FC, useMemo } from "react";
import { observer } from "mobx-react-lite";
// components
import { LabelList, LabelCreate } from "./";

import { LabelList, LabelCreate, IssueLabelSelectRoot } from "./";
// hooks
import { useIssueDetail, useLabel } from "hooks/store";
// types
Expand Down Expand Up @@ -77,16 +76,26 @@ export const IssueLabel: FC<TIssueLabel> = observer((props) => {
projectId={projectId}
issueId={issueId}
labelOperations={labelOperations}
disabled={disabled}
/>

{/* <div>select existing labels</div> */}
{!disabled && (
<IssueLabelSelectRoot
workspaceSlug={workspaceSlug}
projectId={projectId}
issueId={issueId}
labelOperations={labelOperations}
/>
)}

<LabelCreate
workspaceSlug={workspaceSlug}
projectId={projectId}
issueId={issueId}
labelOperations={labelOperations}
/>
{!disabled && (
<LabelCreate
workspaceSlug={workspaceSlug}
projectId={projectId}
issueId={issueId}
labelOperations={labelOperations}
/>
)}
</div>
);
});
9 changes: 0 additions & 9 deletions web/components/issues/issue-detail/label/select-existing.tsx

This file was deleted.

Loading

0 comments on commit 57d5ff7

Please sign in to comment.