style: spreadsheet columns (#2554)

* style: spreadsheet columns

* fix: build errors
This commit is contained in:
Aaryan Khandelwal 2023-10-31 12:18:04 +05:30 committed by GitHub
parent cb533849e8
commit 442c83eea2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 171 additions and 263 deletions

View File

@ -144,7 +144,7 @@ export const CommandModal: React.FC<Props> = (props) => {
} else {
updatedAssignees.push(assignee);
}
updateIssue({ assignees_list: updatedAssignees });
updateIssue({ assignees: updatedAssignees });
};
const redirect = (path: string) => {

View File

@ -79,7 +79,7 @@ export const ChangeIssueAssignee: FC<Props> = ({ setIsPaletteOpen, issue, user }
);
const handleIssueAssignees = (assignee: string) => {
const updatedAssignees = issue.assignees_list ?? [];
const updatedAssignees = issue.assignees ?? [];
if (updatedAssignees.includes(assignee)) {
updatedAssignees.splice(updatedAssignees.indexOf(assignee), 1);
@ -87,7 +87,7 @@ export const ChangeIssueAssignee: FC<Props> = ({ setIsPaletteOpen, issue, user }
updatedAssignees.push(assignee);
}
updateIssue({ assignees_list: updatedAssignees });
updateIssue({ assignees: updatedAssignees });
setIsPaletteOpen(false);
};

View File

@ -198,8 +198,7 @@ export const InlineCreateIssueFormWrapper: React.FC<Props> = (props) => {
if (onSuccess) await onSuccess(res);
if (formData.assignees_list?.some((assignee) => assignee === user?.id))
mutate(USER_ISSUE(workspaceSlug as string));
if (formData.assignees?.some((assignee) => assignee === user?.id)) mutate(USER_ISSUE(workspaceSlug as string));
if (formData.parent && formData.parent !== "") mutate(SUB_ISSUES(formData.parent));
})

View File

@ -22,10 +22,10 @@ import { IInboxIssue, IIssue } from "types";
const defaultValues: Partial<IInboxIssue> = {
name: "",
description_html: "",
assignees_list: [],
assignees: [],
priority: "low",
target_date: new Date().toString(),
labels_list: [],
labels: [],
};
export const InboxMainContent: React.FC = observer(() => {
@ -122,8 +122,8 @@ export const InboxMainContent: React.FC = observer(() => {
reset({
...issueDetails,
assignees_list: issueDetails.assignees_list ?? (issueDetails.assignee_details ?? []).map((user) => user.id),
labels_list: issueDetails.labels_list ?? issueDetails.labels,
assignees: issueDetails.assignees ?? (issueDetails.assignee_details ?? []).map((user) => user.id),
labels: issueDetails.labels ?? issueDetails.labels,
});
}, [issueDetails, reset, inboxIssueId]);

View File

@ -51,9 +51,7 @@ const defaultValues: Partial<IIssue> = {
parent: null,
priority: "none",
assignees: [],
assignees_list: [],
labels: [],
labels_list: [],
start_date: null,
target_date: null,
};
@ -310,10 +308,7 @@ export const DraftIssueForm: FC<IssueFormProps> = (props) => {
handleClose={() => setLabelModal(false)}
projectId={projectId}
user={user}
onSuccess={(response) => {
setValue("labels", [...watch("labels"), response.id]);
setValue("labels_list", [...watch("labels_list"), response.id]);
}}
onSuccess={(response) => setValue("labels", [...watch("labels"), response.id])}
/>
</>
)}

View File

@ -208,8 +208,7 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = observer(
message: "Issue created successfully.",
});
if (payload.assignees_list?.some((assignee) => assignee === user?.id))
mutate(USER_ISSUE(workspaceSlug as string));
if (payload.assignees?.some((assignee) => assignee === user?.id)) mutate(USER_ISSUE(workspaceSlug as string));
})
.catch(() => {
setToastAlert({
@ -325,8 +324,7 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = observer(
if (!createMore) onClose();
if (payload.assignees_list?.some((assignee) => assignee === user?.id))
mutate(USER_ISSUE(workspaceSlug as string));
if (payload.assignees?.some((assignee) => assignee === user?.id)) mutate(USER_ISSUE(workspaceSlug as string));
if (payload.parent && payload.parent !== "") mutate(SUB_ISSUES(payload.parent));
})
@ -347,8 +345,6 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = observer(
const payload: Partial<IIssue> = {
...formData,
assignees_list: formData.assignees ?? [],
labels_list: formData.labels ?? [],
description: formData.description ?? "",
description_html: formData.description_html ?? "<p></p>",
};

View File

@ -41,9 +41,7 @@ const defaultValues: Partial<IIssue> = {
parent: null,
priority: "none",
assignees: [],
assignees_list: [],
labels: [],
labels_list: [],
start_date: null,
target_date: null,
};
@ -262,10 +260,7 @@ export const IssueForm: FC<IssueFormProps> = observer((props) => {
handleClose={() => setLabelModal(false)}
projectId={projectId}
user={user ?? undefined}
onSuccess={(response) => {
setValue("labels", [...watch("labels"), response.id]);
setValue("labels_list", [...watch("labels_list"), response.id]);
}}
onSuccess={(response) => setValue("labels", [...watch("labels"), response.id])}
/>
</>
)}

View File

@ -147,18 +147,6 @@ export const CalendarInlineCreateIssueForm: React.FC<Props> = observer((props) =
const payload = createIssuePayload(workspaceDetail!, projectDetails!, {
...(prePopulatedData ?? {}),
...formData,
labels_list:
formData.labels_list?.length !== 0
? formData.labels_list
: prePopulatedData?.labels && prePopulatedData?.labels.toString() !== "none"
? [prePopulatedData.labels as any]
: [],
assignees_list:
formData.assignees_list?.length !== 0
? formData.assignees_list
: prePopulatedData?.assignees && prePopulatedData?.assignees.toString() !== "none"
? [prePopulatedData.assignees as any]
: [],
});
try {

View File

@ -113,12 +113,6 @@ export const GanttInlineCreateIssueForm: React.FC<Props> = observer((props) => {
const payload = createIssuePayload(workspaceDetail!, projectDetails!, {
...(prePopulatedData ?? {}),
...formData,
labels_list:
formData.labels_list?.length !== 0
? formData.labels_list
: prePopulatedData?.labels && prePopulatedData?.labels.toString() !== "none"
? [prePopulatedData.labels as any]
: [],
start_date: renderDateFormat(new Date()),
target_date: renderDateFormat(new Date(new Date().getTime() + 24 * 60 * 60 * 1000)),
});

View File

@ -65,9 +65,9 @@ export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
)}
</div>
<div
className={`text-sm rounded p-2 px-3 shadow-custom-shadow-2xs space-y-[8px] border transition-all bg-custom-background-100 hover:cursor-grab ${
snapshot.isDragging ? `border-custom-primary-100` : `border-transparent`
}`}
className={`text-sm rounded p-2 px-3 shadow-custom-shadow-2xs space-y-[8px] border transition-all bg-custom-background-100 ${
isDragDisabled ? "" : "hover:cursor-grab"
} ${snapshot.isDragging ? `border-custom-primary-100` : `border-transparent`}`}
>
{displayProperties && displayProperties?.key && (
<div className="text-xs line-clamp-1 text-custom-text-300">

View File

@ -117,18 +117,6 @@ export const BoardInlineCreateIssueForm: React.FC<Props> = observer((props) => {
const payload = createIssuePayload(workspaceDetail!, projectDetails!, {
...(prePopulatedData ?? {}),
...formData,
labels_list:
formData.labels_list && formData.labels_list.length !== 0
? formData.labels_list
: prePopulatedData?.labels && prePopulatedData?.labels.toString() !== "none"
? [prePopulatedData.labels as any]
: [],
assignees_list:
formData.assignees_list && formData.assignees_list.length !== 0
? formData.assignees_list
: prePopulatedData?.assignees && prePopulatedData?.assignees.toString() !== "none"
? [prePopulatedData.assignees as any]
: [],
});
try {

View File

@ -65,7 +65,7 @@ export const KanBanProperties: React.FC<IKanBanProperties> = observer((props) =>
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, labels_list: ids }
{ ...issue, labels: ids }
);
};
@ -73,7 +73,7 @@ export const KanBanProperties: React.FC<IKanBanProperties> = observer((props) =>
handleIssues(
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
!group_id && group_id === "null" ? null : group_id,
{ ...issue, assignees_list: ids }
{ ...issue, assignees: ids }
);
};

View File

@ -116,18 +116,6 @@ export const ListInlineCreateIssueForm: React.FC<Props> = observer((props) => {
const payload = createIssuePayload(workspaceDetail!, projectDetails!, {
...(prePopulatedData ?? {}),
...formData,
labels_list:
formData.labels_list?.length !== 0
? formData.labels_list
: prePopulatedData?.labels && prePopulatedData?.labels.toString() !== "none"
? [prePopulatedData.labels as any]
: [],
assignees_list:
formData.assignees_list?.length !== 0
? formData.assignees_list
: prePopulatedData?.assignees && prePopulatedData?.assignees.toString() !== "none"
? [prePopulatedData.assignees as any]
: [],
});
try {

View File

@ -36,11 +36,11 @@ export const KanBanProperties: FC<IKanBanProperties> = observer((props) => {
};
const handleLabel = (ids: string[]) => {
handleIssues(!group_id && group_id === "null" ? null : group_id, { ...issue, labels_list: ids });
handleIssues(!group_id && group_id === "null" ? null : group_id, { ...issue, labels: ids });
};
const handleAssignee = (ids: string[]) => {
handleIssues(!group_id && group_id === "null" ? null : group_id, { ...issue, assignees_list: ids });
handleIssues(!group_id && group_id === "null" ? null : group_id, { ...issue, assignees: ids });
};
const handleStartDate = (date: string) => {

View File

@ -21,12 +21,12 @@ export const SpreadsheetAssigneeColumn: React.FC<Props> = ({ issue, members, onC
const { subIssues, isLoading } = useSubIssue(issue.project_detail.id, issue.id, isExpanded);
return (
<>
<div className="flex items-center h-full px-4">
<MembersSelect
value={issue.assignees}
onChange={(data) => onChange({ assignees_list: data })}
onChange={(data) => onChange({ assignees: data })}
members={members ?? []}
buttonClassName="!p-0 !rounded-none !shadow-none !border-0"
buttonClassName="!p-0 !rounded-none !border-0"
hideDropdownArrow
disabled={disabled}
multiple
@ -46,6 +46,6 @@ export const SpreadsheetAssigneeColumn: React.FC<Props> = ({ issue, members, onC
disabled={disabled}
/>
))}
</>
</div>
);
};

View File

@ -1,5 +1,5 @@
// components
import { ViewEstimateSelect } from "components/issues";
import { EstimateSelect } from "components/estimates";
// hooks
import useSubIssue from "hooks/use-sub-issue";
// types
@ -21,7 +21,15 @@ export const SpreadsheetEstimateColumn: React.FC<Props> = (props) => {
return (
<>
<ViewEstimateSelect issue={issue} onChange={(data) => onChange({ estimate_point: data })} disabled={disabled} />
<EstimateSelect
value={issue.estimate_point}
onChange={(data) => onChange({ estimate_point: data })}
className="h-full"
buttonClassName="!border-0 !h-full !w-full !rounded-none px-4"
estimatePoints={undefined}
disabled={disabled}
hideDropdownArrow
/>
{isExpanded &&
!isLoading &&

View File

@ -5,13 +5,12 @@ import { MoreHorizontal, Pencil, Trash2, ChevronRight, Link } from "lucide-react
// hooks
import useToast from "hooks/use-toast";
// helpers
import { copyTextToClipboard } from "helpers/string.helper";
import { copyUrlToClipboard } from "helpers/string.helper";
// types
import { IIssue, IIssueDisplayProperties } from "types";
type Props = {
issue: IIssue;
projectId: string;
expanded: boolean;
handleToggleExpand: (issueId: string) => void;
properties: IIssueDisplayProperties;
@ -23,7 +22,6 @@ type Props = {
export const IssueColumn: React.FC<Props> = ({
issue,
projectId,
expanded,
handleToggleExpand,
properties,
@ -50,8 +48,7 @@ export const IssueColumn: React.FC<Props> = ({
};
const handleCopyText = () => {
const originURL = typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
copyTextToClipboard(`${originURL}/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`).then(() => {
copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`).then(() => {
setToastAlert({
type: "success",
title: "Link Copied!",

View File

@ -9,7 +9,6 @@ import { IIssue, IIssueDisplayProperties } from "types";
type Props = {
issue: IIssue;
projectId: string;
expandedIssues: string[];
setExpandedIssues: React.Dispatch<React.SetStateAction<string[]>>;
properties: IIssueDisplayProperties;
@ -20,7 +19,6 @@ type Props = {
export const SpreadsheetIssuesColumn: React.FC<Props> = ({
issue,
projectId,
expandedIssues,
setExpandedIssues,
properties,
@ -48,7 +46,6 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
<>
<IssueColumn
issue={issue}
projectId={projectId}
expanded={isExpanded}
handleToggleExpand={handleToggleExpand}
properties={properties}
@ -66,7 +63,6 @@ export const SpreadsheetIssuesColumn: React.FC<Props> = ({
<SpreadsheetIssuesColumn
key={subIssue.id}
issue={subIssue}
projectId={subIssue.project_detail.id}
expandedIssues={expandedIssues}
setExpandedIssues={setExpandedIssues}
properties={properties}

View File

@ -26,8 +26,10 @@ export const SpreadsheetLabelColumn: React.FC<Props> = (props) => {
<>
<LabelSelect
value={issue.labels}
onChange={(data) => onChange({ labels_list: data })}
onChange={(data) => onChange({ labels: data })}
labels={labels ?? []}
className="h-full"
buttonClassName="!border-0 !h-full !w-full !rounded-none"
hideDropdownArrow
maxRender={1}
disabled={disabled}

View File

@ -20,11 +20,14 @@ export const SpreadsheetPriorityColumn: React.FC<Props> = ({ issue, onChange, ex
const { subIssues, isLoading } = useSubIssue(issue.project_detail.id, issue.id, isExpanded);
return (
<div>
<>
<PrioritySelect
value={issue.priority}
onChange={(data) => onChange({ priority: data })}
buttonClassName="!p-0 !rounded-none !shadow-none !border-0"
className="h-full"
buttonClassName="!border-0 !h-full !w-full !rounded-none px-4"
showTitle
highlightUrgentPriority={false}
hideDropdownArrow
disabled={disabled}
/>
@ -42,6 +45,6 @@ export const SpreadsheetPriorityColumn: React.FC<Props> = ({ issue, onChange, ex
disabled={disabled}
/>
))}
</div>
</>
);
};

View File

@ -32,7 +32,8 @@ export const SpreadsheetStateColumn: React.FC<Props> = (props) => {
value={issue.state_detail}
onChange={(data) => onChange({ state: data.id, state_detail: data })}
states={statesList}
buttonClassName="!shadow-none !border-0"
className="h-full"
buttonClassName="!border-0 !h-full !w-full !rounded-none"
hideDropdownArrow
disabled={disabled}
/>

View File

@ -120,18 +120,6 @@ export const SpreadsheetInlineCreateIssueForm: React.FC<Props> = observer((props
const payload = createIssuePayload(workspaceDetail!, projectDetails!, {
...(prePopulatedData ?? {}),
...formData,
labels_list:
formData.labels_list && formData.labels_list?.length !== 0
? formData.labels_list
: prePopulatedData?.labels && prePopulatedData?.labels.toString() !== "none"
? [prePopulatedData.labels as any]
: [],
assignees_list:
formData.assignees_list && formData.assignees_list?.length !== 0
? formData.assignees_list
: prePopulatedData?.assignees && prePopulatedData?.assignees.toString() !== "none"
? [prePopulatedData.assignees as any]
: [],
});
try {

View File

@ -100,6 +100,7 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
</div>
}
width="xl"
placement="bottom-end"
>
<CustomMenu.MenuItem onClick={() => handleOrderBy(propertyDetails.ascendingOrderKey, property)}>
<div
@ -163,7 +164,9 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
{issues?.map((issue) => (
<div
key={`${property}-${issue.id}`}
className="h-11 flex items-center px-4 py-2.5 border-b-[0.5px] border-custom-border-200"
className={`h-11 border-b-[0.5px] border-custom-border-200 ${
disableUserActions ? "" : "cursor-pointer hover:bg-custom-background-80"
}`}
>
{property === "state" ? (
<SpreadsheetStateColumn

View File

@ -99,11 +99,10 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
<span className="flex items-center px-4 py-2.5 h-full w-full flex-grow">Issue</span>
</div>
{issues.map((issue: IIssue, index) => (
{issues.map((issue, index) => (
<SpreadsheetIssuesColumn
key={`${issue.id}_${index}`}
issue={issue}
projectId={issue.project_detail.id}
expandedIssues={expandedIssues}
setExpandedIssues={setExpandedIssues}
properties={displayProperties}

View File

@ -229,8 +229,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
setFormDirtyState(null);
setShowConfirmDiscard(false);
if (payload.assignees_list?.some((assignee) => assignee === user?.id))
mutate(USER_ISSUE(workspaceSlug as string));
if (payload.assignees?.some((assignee) => assignee === user?.id)) mutate(USER_ISSUE(workspaceSlug as string));
if (payload.parent && payload.parent !== "") mutate(SUB_ISSUES(payload.parent));
})
@ -271,8 +270,6 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
const payload: Partial<IIssue> = {
...formData,
assignees_list: formData.assignees ?? [],
labels_list: formData.labels ?? [],
description: formData.description ?? "",
description_html: formData.description_html ?? "<p></p>",
};

View File

@ -93,7 +93,7 @@ export const PeekOverviewIssueProperties: FC<Props> = (props) => {
<div className="w-3/4">
<SidebarAssigneeSelect
value={issue.assignees}
onChange={(val: string[]) => handleUpdateIssue({ assignees_list: val })}
onChange={(val: string[]) => handleUpdateIssue({ assignees: val })}
disabled={readOnly}
/>
</div>

View File

@ -77,7 +77,7 @@ export const SidebarLabelSelect: React.FC<Props> = ({
issueLabelMutate((prevData: any) => [...(prevData ?? []), res], false);
submitChanges({ labels_list: [...(issueDetails?.labels ?? []), res.id] });
submitChanges({ labels: [...(issueDetails?.labels ?? []), res.id] });
setCreateLabelForm(false);
});
@ -99,7 +99,7 @@ export const SidebarLabelSelect: React.FC<Props> = ({
</div>
<div className="basis-1/2">
<div className="flex flex-wrap gap-1">
{watchIssue("labels_list")?.map((labelId) => {
{watchIssue("labels")?.map((labelId) => {
const label = issueLabels?.find((l) => l.id === labelId);
if (label)
@ -108,9 +108,9 @@ export const SidebarLabelSelect: React.FC<Props> = ({
key={label.id}
className="group flex cursor-pointer items-center gap-1 rounded-2xl border border-custom-border-100 px-1 py-0.5 text-xs hover:border-red-500/20 hover:bg-red-500/20"
onClick={() => {
const updatedLabels = watchIssue("labels_list")?.filter((l) => l !== labelId);
const updatedLabels = watchIssue("labels")?.filter((l) => l !== labelId);
submitChanges({
labels_list: updatedLabels,
labels: updatedLabels,
});
}}
>
@ -127,12 +127,12 @@ export const SidebarLabelSelect: React.FC<Props> = ({
})}
<Controller
control={issueControl}
name="labels_list"
name="labels"
render={({ field: { value } }) => (
<Listbox
as="div"
value={value}
onChange={(val: any) => submitChanges({ labels_list: val })}
onChange={(val: any) => submitChanges({ labels: val })}
className="flex-shrink-0"
multiple
disabled={isNotAllowed || uneditable}

View File

@ -357,11 +357,11 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
<div className="sm:basis-1/2">
<Controller
control={control}
name="assignees_list"
name="assignees"
render={({ field: { value } }) => (
<SidebarAssigneeSelect
value={value}
onChange={(val: string[]) => submitChanges({ assignees_list: val })}
onChange={(val: string[]) => submitChanges({ assignees: val })}
disabled={memberRole.isGuest || memberRole.isViewer || uneditable}
/>
)}

View File

@ -72,7 +72,7 @@ export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
};
const handleAssigneeChange = (data: string[]) => {
partialUpdateIssue({ assignees_list: data, assignees: data });
partialUpdateIssue({ assignees: data });
trackEventService.trackIssuePartialPropertyUpdateEvent(
{

View File

@ -90,7 +90,7 @@ export const ViewAssigneeSelect: React.FC<Props> = ({
if (newData.includes(data)) newData.splice(newData.indexOf(data), 1);
else newData.push(data);
partialUpdateIssue({ assignees_list: data }, issue);
partialUpdateIssue({ assignees: data }, issue);
trackEventService.trackIssuePartialPropertyUpdateEvent(
{

View File

@ -139,7 +139,7 @@ export const ViewLabelSelect: FC<Props> = ({
<CustomSearchSelect
value={issue.labels}
onChange={(data: string[]) => {
partialUpdateIssue({ labels_list: data }, issue);
partialUpdateIssue({ labels: data }, issue);
}}
options={options}
{...(customButton ? { customButton: labelsLabel } : { label: labelsLabel })}

View File

@ -23,7 +23,7 @@ const defaultValues: Partial<IModule> = {
description: "",
status: "backlog",
lead: null,
members_list: [],
members: [],
};
export const ModuleForm: React.FC<Props> = ({
@ -47,7 +47,7 @@ export const ModuleForm: React.FC<Props> = ({
description: data?.description || "",
status: data?.status || "backlog",
lead: data?.lead || null,
members_list: data?.members_list || [],
members: data?.members || [],
},
});

View File

@ -24,7 +24,7 @@ const defaultValues: Partial<IModule> = {
description: "",
status: "backlog",
lead: null,
members_list: [],
members: [],
};
export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
@ -98,7 +98,6 @@ export const CreateUpdateModuleModal: React.FC<Props> = observer((props) => {
const payload: Partial<IModule> = {
...formData,
members_list: formData.members,
};
if (!data) await createModule(payload);

View File

@ -32,7 +32,7 @@ import { MODULE_STATUS } from "constants/module";
const defaultValues: Partial<IModule> = {
lead: "",
members_list: [],
members: [],
start_date: null,
target_date: null,
status: "backlog",
@ -186,7 +186,6 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
if (moduleDetails)
reset({
...moduleDetails,
members_list: moduleDetails.members_list ?? moduleDetails.members_detail?.map((m) => m.id),
});
}, [moduleDetails, reset]);
@ -301,12 +300,12 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
/>
<Controller
control={control}
name="members_list"
name="members"
render={({ field: { value } }) => (
<SidebarMembersSelect
value={value}
onChange={(val: string[]) => {
submitChanges({ members_list: val });
submitChanges({ members: val });
}}
/>
)}

View File

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { usePopper } from "react-popper";
import { Placement } from "@popperjs/core";
import { Combobox } from "@headlessui/react";
import { Check, ChevronDown, PlusIcon, Search } from "lucide-react";
import { Check, ChevronDown, Search } from "lucide-react";
// ui
import { Tooltip } from "components/ui";
// types
@ -21,7 +21,8 @@ type Props = {
disabled?: boolean;
};
export const LabelSelect: React.FC<Props> = ({
export const LabelSelect: React.FC<Props> = (props) => {
const {
value,
onChange,
labels,
@ -32,7 +33,8 @@ export const LabelSelect: React.FC<Props> = ({
placement,
hideDropdownArrow = false,
disabled = false,
}) => {
} = props;
const [query, setQuery] = useState("");
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
@ -79,27 +81,16 @@ export const LabelSelect: React.FC<Props> = ({
multiple
>
<Combobox.Button as={React.Fragment}>
<button
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 w-full text-xs ${
disabled
? "cursor-not-allowed text-custom-text-200"
: value.length <= maxRender
? "cursor-pointer"
: "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
>
<div className="flex items-center gap-2 text-custom-text-200 h-full">
<button ref={setReferenceElement} type="button" className="h-full w-full">
{value.length > 0 ? (
value.length <= maxRender ? (
<>
<div className="flex items-center gap-2 px-4 overflow-x-scroll">
{labels
?.filter((l) => value.includes(l.id))
.map((label) => (
<div
key={label.id}
className="flex cursor-default items-center flex-shrink-0 rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 text-xs h-full"
className="flex items-center flex-shrink-0 rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 text-xs h-full"
>
<div className="flex items-center gap-1.5 text-custom-text-200">
<span
@ -112,9 +103,11 @@ export const LabelSelect: React.FC<Props> = ({
</div>
</div>
))}
</>
</div>
) : (
<div className="h-full flex cursor-default items-center flex-shrink-0 rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 text-xs">
<div
className={`h-full flex items-center flex-shrink-0 rounded border-[0.5px] border-custom-border-300 px-4 text-xs ${buttonClassName}`}
>
<Tooltip
position="top"
tooltipHeading="Labels"
@ -131,11 +124,14 @@ export const LabelSelect: React.FC<Props> = ({
</div>
)
) : (
<div className="h-full flex items-center justify-center text-xs rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 hover:bg-custom-background-80">
<div
className={`flex items-center justify-between gap-1 w-full text-xs px-4 ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
} ${buttonClassName}`}
>
Select labels
</div>
)}
</div>
{!hideDropdownArrow && !disabled && <ChevronDown className="h-3 w-3" aria-hidden="true" />}
</button>
</Combobox.Button>

View File

@ -20,6 +20,8 @@ type Props = {
buttonClassName?: string;
optionsClassName?: string;
placement?: Placement;
showTitle?: boolean;
highlightUrgentPriority?: boolean;
hideDropdownArrow?: boolean;
disabled?: boolean;
};
@ -31,6 +33,8 @@ export const PrioritySelect: React.FC<Props> = ({
buttonClassName = "",
optionsClassName = "",
placement,
showTitle = false,
highlightUrgentPriority = true,
hideDropdownArrow = false,
disabled = false,
}) => {
@ -69,20 +73,21 @@ export const PrioritySelect: React.FC<Props> = ({
const label = (
<Tooltip tooltipHeading="Priority" tooltipContent={selectedOption} position="top">
<div className="flex items-center gap-2">
<PriorityIcon
priority={value}
className={`h-3.5 w-3.5 ${
value === "urgent"
? "text-white"
: value === "high"
value === "high"
? "text-orange-500"
: value === "medium"
? "text-yellow-500"
: value === "low"
? "text-green-500"
: "text-custom-text-200"
}`}
} ${value === "urgent" && highlightUrgentPriority ? "text-white" : "text-red-500"}`}
/>
{showTitle && <span className="capitalize text-xs">{value}</span>}
</div>
</Tooltip>
);
@ -99,9 +104,13 @@ export const PrioritySelect: React.FC<Props> = ({
ref={setReferenceElement}
type="button"
className={`flex items-center justify-between gap-1 h-full w-full text-xs rounded border-[0.5px] ${
value === "urgent" ? "border-red-500/20 bg-red-500" : "border-custom-border-300"
} ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer hover:bg-custom-background-80"
value === "urgent"
? highlightUrgentPriority
? "border-red-500/20 bg-red-500"
: "border-custom-border-300"
: "border-custom-border-300"
} ${!disabled ? "hover:bg-custom-background-80" : ""} ${
disabled ? "cursor-not-allowed text-custom-text-200" : "cursor-pointer"
} ${buttonClassName}`}
>
{label}

View File

@ -144,7 +144,7 @@ export const IssuePropertiesDetail: React.FC<Props> = (props) => {
<div>
<Controller
control={control}
name="assignees_list"
name="assignees"
render={({ field: { value } }) => (
<AssigneeSelect
value={value}
@ -152,7 +152,7 @@ export const IssuePropertiesDetail: React.FC<Props> = (props) => {
onChange={(val: string) => {
const assignees = value?.includes(val) ? value?.filter((i) => i !== val) : [...(value ?? []), val];
submitChanges({ assignees_list: assignees });
submitChanges({ assignees: assignees });
}}
/>
)}
@ -232,7 +232,7 @@ export const IssuePropertiesDetail: React.FC<Props> = (props) => {
JSON.stringify({
issue_id: relation.issue_detail?.id,
project_id: relation.issue_detail?.project_detail.id,
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`,
})
)
}
@ -295,7 +295,7 @@ export const IssuePropertiesDetail: React.FC<Props> = (props) => {
JSON.stringify({
issue_id: relation.issue_detail?.id,
project_id: relation.issue_detail?.project_detail.id,
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`,
})
)
}
@ -358,7 +358,7 @@ export const IssuePropertiesDetail: React.FC<Props> = (props) => {
JSON.stringify({
issue_id: relation.issue_detail?.id,
project_id: relation.issue_detail?.project_detail.id,
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`,
})
)
}
@ -421,7 +421,7 @@ export const IssuePropertiesDetail: React.FC<Props> = (props) => {
JSON.stringify({
issue_id: relation.issue_detail?.id,
project_id: relation.issue_detail?.project_detail.id,
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`
issue_identifier: `${relation.issue_detail?.project_detail.identifier}-${relation.issue_detail?.sequence_id}`,
})
)
}

View File

@ -437,7 +437,6 @@ export const createIssuePayload: (
archived_at: null,
assignees: [],
assignee_details: [],
assignees_list: [],
attachment_count: 0,
attachments: [],
issue_relations: [],
@ -459,7 +458,6 @@ export const createIssuePayload: (
labels: [],
label_details: [],
is_draft: false,
labels_list: [],
links_list: [],
link_count: 0,
module: null,

View File

@ -37,8 +37,6 @@ export const handleIssuesMutation: THandleIssuesMutation = (
const updatedIssue = {
...prevData[issueIndex],
...formData,
assignees: formData?.assignees_list ?? prevData[issueIndex]?.assignees,
labels: formData?.labels_list ?? prevData[issueIndex]?.labels,
};
prevData.splice(issueIndex, 1, updatedIssue);
@ -55,8 +53,6 @@ export const handleIssuesMutation: THandleIssuesMutation = (
const updatedIssue = {
...oldGroup[issueIndex],
...formData,
assignees: formData?.assignees_list ?? oldGroup[issueIndex]?.assignees,
labels: formData?.labels_list ?? oldGroup[issueIndex]?.labels,
};
if (selectedGroupBy !== Object.keys(formData)[0])

View File

@ -32,12 +32,10 @@ const defaultValues: Partial<IIssue> = {
description_html: "",
estimate_point: null,
state: "",
assignees_list: [],
priority: "low",
target_date: new Date().toString(),
issue_cycle: null,
issue_module: null,
labels_list: [],
};
// services
@ -109,9 +107,6 @@ const ArchivedIssueDetailsPage: NextPage = () => {
mutate(PROJECT_ISSUES_ACTIVITY(archivedIssueId as string));
reset({
...issueDetails,
assignees_list: issueDetails.assignees_list ?? issueDetails.assignee_details?.map((user) => user.id),
labels_list: issueDetails.labels_list ?? issueDetails.labels,
labels: issueDetails.labels_list ?? issueDetails.labels,
});
}, [issueDetails, reset, archivedIssueId]);

View File

@ -27,13 +27,11 @@ import { PROJECT_ISSUES_ACTIVITY, ISSUE_DETAILS } from "constants/fetch-keys";
// helper
const defaultValues: Partial<IIssue> = {
assignees_list: [],
description: "",
description_html: "",
estimate_point: null,
issue_cycle: null,
issue_module: null,
labels_list: [],
name: "",
priority: "low",
start_date: null,
@ -109,9 +107,6 @@ const IssueDetailsPage: NextPage = () => {
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
reset({
...issueDetails,
assignees_list: issueDetails.assignees_list ?? issueDetails.assignee_details?.map((user) => user.id),
labels_list: issueDetails.labels_list ?? issueDetails.labels,
labels: issueDetails.labels_list ?? issueDetails.labels,
});
}, [issueDetails, reset, issueId]);

View File

@ -133,7 +133,6 @@ const SinglePage: NextPage = () => {
(prevData) => ({
...(prevData as IPage),
...formData,
labels: formData.labels_list ? formData.labels_list : (prevData as IPage).labels,
}),
false
);
@ -361,7 +360,7 @@ const SinglePage: NextPage = () => {
className="group flex cursor-pointer items-center gap-1 rounded-2xl border border-custom-border-200 px-2 py-0.5 text-xs hover:border-red-500 hover:bg-red-50"
onClick={() => {
const updatedLabels = pageDetails.labels.filter((l) => l !== labelId);
partialUpdatePage({ labels_list: updatedLabels });
partialUpdatePage({ labels: updatedLabels });
}}
style={{
backgroundColor: `${label?.color && label.color !== "" ? label.color : "#000000"}20`,
@ -402,7 +401,7 @@ const SinglePage: NextPage = () => {
</span>
</button>
}
onChange={(val: string[]) => partialUpdatePage({ labels_list: val })}
onChange={(val: string[]) => partialUpdatePage({ labels: val })}
options={options}
multiple
noChevron
@ -606,7 +605,7 @@ const SinglePage: NextPage = () => {
user={user}
onSuccess={(response) => {
partialUpdatePage({
labels_list: [...(pageDetails.labels ?? []), response.id],
labels: [...(pageDetails.labels ?? []), response.id],
});
}}
/>

View File

@ -69,15 +69,13 @@ const MobileWebViewIssueDetail_ = () => {
useEffect(() => {
if (!issueDetails) return;
reset({
...issueDetails,
name: issueDetails.name,
description: issueDetails.description,
description_html: issueDetails.description_html,
state: issueDetails.state,
assignees_list: issueDetails.assignees_list ?? issueDetails.assignee_details?.map((user) => user.id),
labels_list: issueDetails.labels_list ?? issueDetails.labels,
labels: issueDetails.labels_list ?? issueDetails.labels,
});
}, [issueDetails, reset]);

View File

@ -122,7 +122,6 @@ export class DraftIssuesStore {
// immediately update the issue in the store
const updatedIssue = { ...this.issues[issueId], ...issueForm };
if (updatedIssue.assignees_list) updatedIssue.assignees = updatedIssue.assignees_list;
try {
runInAction(() => {

View File

@ -80,7 +80,6 @@ export interface IIssue {
archived_at: string;
assignees: string[];
assignee_details: IUser[];
assignees_list: string[];
attachment_count: number;
attachments: any[];
issue_relations: IssueRelation[];
@ -105,7 +104,6 @@ export interface IIssue {
labels: string[];
label_details: any[];
is_draft: boolean;
labels_list: string[];
links_list: IIssueLink[];
link_count: number;
module: string | null;

View File

@ -10,13 +10,7 @@ import type {
linkDetails,
} from "types";
export type TModuleStatus =
| "backlog"
| "planned"
| "in-progress"
| "paused"
| "completed"
| "cancelled";
export type TModuleStatus = "backlog" | "planned" | "in-progress" | "paused" | "completed" | "cancelled";
export interface IModule {
backlog_issues: number;
@ -38,7 +32,6 @@ export interface IModule {
link_module: linkDetails[];
links_list: ModuleLink[];
members: string[];
members_list: string[];
members_detail: IUserLite[];
is_favorite: boolean;
name: string;
@ -80,8 +73,6 @@ export type ModuleLink = {
url: string;
};
export type SelectModuleType =
| (IModule & { actionType: "edit" | "delete" | "create-issue" })
| undefined;
export type SelectModuleType = (IModule & { actionType: "edit" | "delete" | "create-issue" }) | undefined;
export type SelectIssue = (IIssue & { actionType: "edit" | "delete" | "create" }) | undefined;

View File

@ -14,7 +14,6 @@ export interface IPage {
is_favorite: boolean;
label_details: IIssueLabels[];
labels: string[];
labels_list: string[];
name: string;
owned_by: string;
project: string;