fix: blocked issues, style: issue details sidebar

This commit is contained in:
Aaryan Khandelwal 2022-12-20 20:20:45 +05:30
parent afcf1083ff
commit 8ae9c3f15a
15 changed files with 163 additions and 141 deletions

View File

@ -28,7 +28,7 @@ type Props = {
}; };
type FormInput = { type FormInput = {
issue: string[]; issues: string[];
}; };
const CycleIssuesListModal: React.FC<Props> = ({ const CycleIssuesListModal: React.FC<Props> = ({
@ -56,12 +56,12 @@ const CycleIssuesListModal: React.FC<Props> = ({
formState: { isSubmitting }, formState: { isSubmitting },
} = useForm<FormInput>({ } = useForm<FormInput>({
defaultValues: { defaultValues: {
issue: [], issues: [],
}, },
}); });
const handleAddToCycle: SubmitHandler<FormInput> = (data) => { const handleAddToCycle: SubmitHandler<FormInput> = (data) => {
if (!data.issue || data.issue.length === 0) { if (!data.issues || data.issues.length === 0) {
setToastAlert({ setToastAlert({
title: "Error", title: "Error",
type: "error", type: "error",
@ -120,7 +120,7 @@ const CycleIssuesListModal: React.FC<Props> = ({
<form> <form>
<Controller <Controller
control={control} control={control}
name="issue" name="issues"
render={({ field }) => ( render={({ field }) => (
<Combobox as="div" {...field} multiple> <Combobox as="div" {...field} multiple>
<div className="relative m-1"> <div className="relative m-1">

View File

@ -63,7 +63,7 @@ const SingleStat: React.FC<Props> = ({ cycle, handleEditCycle, handleDeleteCycle
return ( return (
<> <>
<div className="bg-white p-3"> <div className="border bg-white p-3 rounded-md">
<div className="grid grid-cols-8 gap-2 divide-x"> <div className="grid grid-cols-8 gap-2 divide-x">
<div className="col-span-3 space-y-3"> <div className="col-span-3 space-y-3">
<div className="flex justify-between items-center gap-2"> <div className="flex justify-between items-center gap-2">
@ -74,7 +74,15 @@ const SingleStat: React.FC<Props> = ({ cycle, handleEditCycle, handleDeleteCycle
</Link> </Link>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-xs bg-gray-100 px-2 py-1 rounded-xl"> <span
className={`text-xs border px-3 py-0.5 rounded-xl ${
today < startDate
? "text-orange-500 border-orange-500"
: today > endDate
? "text-red-500 border-red-500"
: "text-green-500 border-green-500"
}`}
>
{today < startDate ? "Not started" : today > endDate ? "Over" : "Active"} {today < startDate ? "Not started" : today > endDate ? "Over" : "Active"}
</span> </span>
</div> </div>
@ -86,20 +94,19 @@ const SingleStat: React.FC<Props> = ({ cycle, handleEditCycle, handleDeleteCycle
</CustomMenu> </CustomMenu>
</div> </div>
</div> </div>
<div className="grid grid-cols-3 gap-x-2 gap-y-3 text-xs">
<div className="grid grid-cols-2 gap-x-2 gap-y-3 text-xs">
<div className="flex items-center gap-2 text-gray-500"> <div className="flex items-center gap-2 text-gray-500">
<CalendarDaysIcon className="h-4 w-4" /> <CalendarDaysIcon className="h-4 w-4" />
Cycle dates Cycle dates
</div> </div>
<div> <div className="col-span-2">
{renderShortNumericDateFormat(startDate)} - {renderShortNumericDateFormat(endDate)} {renderShortNumericDateFormat(startDate)} - {renderShortNumericDateFormat(endDate)}
</div> </div>
<div className="flex items-center gap-2 text-gray-500"> <div className="flex items-center gap-2 text-gray-500">
<UserIcon className="h-4 w-4" /> <UserIcon className="h-4 w-4" />
Created by Created by
</div> </div>
<div className="flex items-center gap-2"> <div className="col-span-2 flex items-center gap-2">
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? ( {cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
<Image <Image
src={cycle.owned_by.avatar} src={cycle.owned_by.avatar}
@ -119,7 +126,7 @@ const SingleStat: React.FC<Props> = ({ cycle, handleEditCycle, handleDeleteCycle
<CalendarDaysIcon className="h-4 w-4" /> <CalendarDaysIcon className="h-4 w-4" />
Active members Active members
</div> </div>
<div></div> <div className="col-span-2"></div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button theme="secondary" className="flex items-center gap-2" disabled> <Button theme="secondary" className="flex items-center gap-2" disabled>

View File

@ -118,7 +118,7 @@ const CreateUpdateIssuesModal: React.FC<Props> = ({
if (!activeWorkspace || !activeProject) return; if (!activeWorkspace || !activeProject) return;
await issuesServices await issuesServices
.addIssueToCycle(activeWorkspace.slug, activeProject.id, cycleId, { .addIssueToCycle(activeWorkspace.slug, activeProject.id, cycleId, {
issue: [issueId], issues: [issueId],
}) })
.then((res) => { .then((res) => {
mutate(CYCLE_ISSUES(cycleId)); mutate(CYCLE_ISSUES(cycleId));

View File

@ -101,7 +101,7 @@ const IssueDetailSidebar: React.FC<Props> = ({
if (activeWorkspace && activeProject && issueDetail) if (activeWorkspace && activeProject && issueDetail)
issuesServices issuesServices
.addIssueToCycle(activeWorkspace.slug, activeProject.id, cycleId, { .addIssueToCycle(activeWorkspace.slug, activeProject.id, cycleId, {
issue: [issueDetail.id], issues: [issueDetail.id],
}) })
.then(() => { .then(() => {
submitChanges({}); submitChanges({});
@ -211,7 +211,7 @@ const IssueDetailSidebar: React.FC<Props> = ({
watch={watchIssue} watch={watchIssue}
/> />
<SelectBlocked <SelectBlocked
submitChanges={submitChanges} issueDetail={issueDetail}
issuesList={issues?.results.filter((i) => i.id !== issueDetail?.id) ?? []} issuesList={issues?.results.filter((i) => i.id !== issueDetail?.id) ?? []}
watch={watchIssue} watch={watchIssue}
/> />
@ -227,6 +227,7 @@ const IssueDetailSidebar: React.FC<Props> = ({
render={({ field: { value, onChange } }) => ( render={({ field: { value, onChange } }) => (
<input <input
type="date" type="date"
id="issueDate"
value={value ?? ""} value={value ?? ""}
onChange={(e: any) => { onChange={(e: any) => {
submitChanges({ target_date: e.target.value }); submitChanges({ target_date: e.target.value });

View File

@ -128,7 +128,7 @@ const SelectAssignee: React.FC<Props> = ({ control, submitChanges }) => {
leaveFrom="transform opacity-100 scale-100" leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95" leaveTo="transform opacity-0 scale-95"
> >
<Listbox.Options className="absolute z-10 right-0 mt-1 w-auto bg-white shadow-lg max-h-28 rounded-md py-1 text-xs ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none"> <Listbox.Options className="absolute z-10 right-0 mt-1 w-auto bg-white shadow-lg max-h-48 rounded-md py-1 text-xs ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none">
<div className="py-1"> <div className="py-1">
{people ? ( {people ? (
people.length > 0 ? ( people.length > 0 ? (

View File

@ -10,32 +10,28 @@ import { Combobox, Dialog, Transition } from "@headlessui/react";
// ui // ui
import { Button } from "ui"; import { Button } from "ui";
// icons // icons
import { import { FolderIcon, MagnifyingGlassIcon, FlagIcon, XMarkIcon } from "@heroicons/react/24/outline";
FolderIcon,
MagnifyingGlassIcon,
UserGroupIcon,
XMarkIcon,
} from "@heroicons/react/24/outline";
// types // types
import { IIssue } from "types"; import { IIssue, IssueResponse } from "types";
// constants // constants
import { classNames } from "constants/common"; import { classNames } from "constants/common";
import issuesService from "lib/services/issues.service";
type FormInput = { type FormInput = {
issue_ids: string[]; issue_ids: string[];
}; };
type Props = { type Props = {
submitChanges: (formData: Partial<IIssue>) => void; issueDetail: IIssue | undefined;
issuesList: IIssue[]; issuesList: IIssue[];
watch: UseFormWatch<IIssue>; watch: UseFormWatch<IIssue>;
}; };
const SelectBlocked: React.FC<Props> = ({ submitChanges, issuesList, watch }) => { const SelectBlocked: React.FC<Props> = ({ issueDetail, issuesList, watch }) => {
const [query, setQuery] = useState(""); const [query, setQuery] = useState("");
const [isBlockedModalOpen, setIsBlockedModalOpen] = useState(false); const [isBlockedModalOpen, setIsBlockedModalOpen] = useState(false);
const { activeProject, issues } = useUser(); const { activeWorkspace, activeProject, issues, mutateIssues } = useUser();
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const { register, handleSubmit, reset, watch: watchIssues } = useForm<FormInput>(); const { register, handleSubmit, reset, watch: watchIssues } = useForm<FormInput>();
@ -54,16 +50,73 @@ const SelectBlocked: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
}); });
return; return;
} }
const newBlocked = [...watch("blocked_list"), ...data.issue_ids];
submitChanges({ blocked_list: newBlocked }); data.issue_ids.map((issue) => {
handleClose(); if (!activeWorkspace || !activeProject || !issueDetail) return;
const currentBlockers =
issues?.results
.find((i) => i.id === issue)
?.blocker_issues.map((b) => b.blocker_issue_detail?.id ?? "") ?? [];
issuesService
.patchIssue(activeWorkspace.slug, activeProject.id, issue, {
blockers_list: [...currentBlockers, issueDetail.id],
})
.then((response) => {
mutateIssues((prevData) => ({
...(prevData as IssueResponse),
results: (prevData?.results ?? []).map((issue) => {
if (issue.id === issueDetail.id) {
return { ...issue, ...response };
}
return issue;
}),
}));
})
.catch((error) => {
console.log(error);
});
});
// handleClose();
};
const removeBlocked = (issueId: string) => {
if (!activeWorkspace || !activeProject || !issueDetail) return;
const currentBlockers =
issues?.results
.find((i) => i.id === issueId)
?.blocker_issues.map((b) => b.blocker_issue_detail?.id ?? "") ?? [];
const updatedBlockers = currentBlockers.filter((b) => b !== issueDetail.id);
issuesService
.patchIssue(activeWorkspace.slug, activeProject.id, issueId, {
blockers_list: updatedBlockers,
})
.then((response) => {
mutateIssues((prevData) => ({
...(prevData as IssueResponse),
results: (prevData?.results ?? []).map((issue) => {
if (issue.id === issueDetail.id) {
return { ...issue, ...response };
}
return issue;
}),
}));
})
.catch((error) => {
console.log(error);
});
}; };
return ( return (
<div className="flex items-start py-2 flex-wrap"> <div className="flex items-start py-2 flex-wrap">
<div className="flex items-center gap-x-2 text-sm sm:basis-1/2"> <div className="flex items-center gap-x-2 text-sm sm:basis-1/2">
<UserGroupIcon className="flex-shrink-0 h-4 w-4" /> <FlagIcon className="flex-shrink-0 h-4 w-4" />
<p>Blocked issues</p> <p>Blocked by</p>
</div> </div>
<div className="sm:basis-1/2 space-y-1"> <div className="sm:basis-1/2 space-y-1">
<div className="flex gap-1 flex-wrap"> <div className="flex gap-1 flex-wrap">
@ -71,13 +124,8 @@ const SelectBlocked: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
? watch("blocked_list").map((issue) => ( ? watch("blocked_list").map((issue) => (
<span <span
key={issue} key={issue}
className="group flex items-center gap-1 border rounded-2xl text-xs px-1 py-0.5 hover:bg-red-50 hover:border-red-500 cursor-pointer" className="group flex items-center gap-1 border rounded-2xl text-xs px-1.5 py-0.5 text-red-500 hover:bg-red-50 border-red-500 cursor-pointer"
onClick={() => { onClick={() => removeBlocked(issue)}
const updatedBlockers = watch("blocked_list").filter((i) => i !== issue);
submitChanges({
blocked_list: updatedBlockers,
});
}}
> >
{`${activeProject?.identifier}-${ {`${activeProject?.identifier}-${
issues?.results.find((i) => i.id === issue)?.sequence_id issues?.results.find((i) => i.id === issue)?.sequence_id
@ -145,7 +193,10 @@ const SelectBlocked: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
)} )}
<ul className="text-sm text-gray-700"> <ul className="text-sm text-gray-700">
{issuesList.map((issue) => { {issuesList.map((issue) => {
if (!watch("blocked_list").includes(issue.id)) { if (
!watch("blocked_list").includes(issue.id) &&
!watch("blockers_list").includes(issue.id)
) {
return ( return (
<Combobox.Option <Combobox.Option
key={issue.id} key={issue.id}

View File

@ -10,12 +10,7 @@ import { Combobox, Dialog, Transition } from "@headlessui/react";
// ui // ui
import { Button } from "ui"; import { Button } from "ui";
// icons // icons
import { import { FlagIcon, FolderIcon, MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline";
FolderIcon,
MagnifyingGlassIcon,
UserGroupIcon,
XMarkIcon,
} from "@heroicons/react/24/outline";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
// constants // constants
@ -62,8 +57,8 @@ const SelectBlocker: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
return ( return (
<div className="flex items-start py-2 flex-wrap"> <div className="flex items-start py-2 flex-wrap">
<div className="flex items-center gap-x-2 text-sm sm:basis-1/2"> <div className="flex items-center gap-x-2 text-sm sm:basis-1/2">
<UserGroupIcon className="flex-shrink-0 h-4 w-4" /> <FlagIcon className="flex-shrink-0 h-4 w-4" />
<p>Blocker issues</p> <p>Blocking</p>
</div> </div>
<div className="sm:basis-1/2 space-y-1"> <div className="sm:basis-1/2 space-y-1">
<div className="flex gap-1 flex-wrap"> <div className="flex gap-1 flex-wrap">
@ -71,7 +66,7 @@ const SelectBlocker: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
? watch("blockers_list").map((issue) => ( ? watch("blockers_list").map((issue) => (
<span <span
key={issue} key={issue}
className="group flex items-center gap-1 border rounded-2xl text-xs px-1 py-0.5 hover:bg-red-50 hover:border-red-500 cursor-pointer" className="group flex items-center gap-1 border rounded-2xl text-xs px-1.5 py-0.5 text-yellow-500 hover:bg-yellow-50 border-yellow-500 cursor-pointer"
onClick={() => { onClick={() => {
const updatedBlockers = watch("blockers_list").filter((i) => i !== issue); const updatedBlockers = watch("blockers_list").filter((i) => i !== issue);
submitChanges({ submitChanges({
@ -145,7 +140,10 @@ const SelectBlocker: React.FC<Props> = ({ submitChanges, issuesList, watch }) =>
)} )}
<ul className="text-sm text-gray-700"> <ul className="text-sm text-gray-700">
{issuesList.map((issue) => { {issuesList.map((issue) => {
if (!watch("blockers_list").includes(issue.id)) { if (
!watch("blockers_list").includes(issue.id) &&
!watch("blocked_list").includes(issue.id)
) {
return ( return (
<Combobox.Option <Combobox.Option
key={issue.id} key={issue.id}

View File

@ -12,6 +12,7 @@ import { IIssue } from "types";
import { classNames } from "constants/common"; import { classNames } from "constants/common";
import { PRIORITIES } from "constants/"; import { PRIORITIES } from "constants/";
import CustomSelect from "ui/custom-select"; import CustomSelect from "ui/custom-select";
import { getPriorityIcon } from "constants/global";
type Props = { type Props = {
control: Control<IIssue, any>; control: Control<IIssue, any>;
@ -33,7 +34,18 @@ const SelectPriority: React.FC<Props> = ({ control, submitChanges, watch }) => {
render={({ field: { value } }) => ( render={({ field: { value } }) => (
<CustomSelect <CustomSelect
label={ label={
<span className={classNames(value ? "" : "text-gray-900", "text-left capitalize")}> <span
className={classNames(
value ? "" : "text-gray-900",
"text-left capitalize flex items-center gap-2"
)}
>
{getPriorityIcon(
watch("priority") && watch("priority") !== ""
? watch("priority") ?? ""
: "None",
"text-sm"
)}
{watch("priority") && watch("priority") !== "" ? watch("priority") : "None"} {watch("priority") && watch("priority") !== "" ? watch("priority") : "None"}
</span> </span>
} }
@ -44,7 +56,10 @@ const SelectPriority: React.FC<Props> = ({ control, submitChanges, watch }) => {
> >
{PRIORITIES.map((option) => ( {PRIORITIES.map((option) => (
<CustomSelect.Option key={option} value={option} className="capitalize"> <CustomSelect.Option key={option} value={option} className="capitalize">
<>
{getPriorityIcon(option, "text-sm")}
{option} {option}
</>
</CustomSelect.Option> </CustomSelect.Option>
))} ))}
</CustomSelect> </CustomSelect>

View File

@ -8,7 +8,7 @@ import useSWR from "swr";
// headless ui // headless ui
import { Disclosure, Listbox, Menu, Transition } from "@headlessui/react"; import { Disclosure, Listbox, Menu, Transition } from "@headlessui/react";
// ui // ui
import { Spinner } from "ui"; import { CustomMenu, Spinner } from "ui";
// icons // icons
import { import {
ChevronDownIcon, ChevronDownIcon,
@ -483,18 +483,8 @@ const ListView: React.FC<Props> = ({
)} )}
</Listbox> </Listbox>
)} )}
<Menu as="div" className="relative"> <CustomMenu ellipsis>
<Menu.Button <CustomMenu.MenuItem
as="button"
className={`h-7 w-7 p-1 grid place-items-center rounded hover:bg-gray-100 duration-300 outline-none`}
>
<EllipsisHorizontalIcon className="h-4 w-4" />
</Menu.Button>
<Menu.Items className="absolute origin-top-right right-0.5 mt-1 p-1 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none z-10">
<Menu.Item>
<button
type="button"
className="text-left p-2 text-gray-900 hover:bg-theme hover:text-white rounded-md text-xs whitespace-nowrap w-full"
onClick={() => { onClick={() => {
setSelectedIssue({ setSelectedIssue({
...issue, ...issue,
@ -503,23 +493,15 @@ const ListView: React.FC<Props> = ({
}} }}
> >
Edit Edit
</button> </CustomMenu.MenuItem>
</Menu.Item> <CustomMenu.MenuItem
<Menu.Item>
<div className="hover:bg-gray-100 border-b last:border-0">
<button
type="button"
className="text-left p-2 text-gray-900 hover:bg-theme hover:text-white rounded-md text-xs whitespace-nowrap w-full"
onClick={() => { onClick={() => {
handleDeleteIssue(issue.id); handleDeleteIssue(issue.id);
}} }}
> >
Delete permanently Delete permanently
</button> </CustomMenu.MenuItem>
</div> </CustomMenu>
</Menu.Item>
</Menu.Items>
</Menu>
</div> </div>
</div> </div>
); );

View File

@ -1,12 +1,18 @@
export const getPriorityIcon = (priority: string) => { export const getPriorityIcon = (priority: string, className: string) => {
switch (priority) { switch (priority) {
case "urgent": case "urgent":
return <span className="material-symbols-rounded">signal_cellular_alt</span>; return <span className={`material-symbols-rounded ${className}`}>error</span>;
case "high": case "high":
return <span className="material-symbols-rounded">signal_cellular_alt_2_bar</span>; return <span className={`material-symbols-rounded ${className}`}>signal_cellular_alt</span>;
case "medium": case "medium":
return <span className="material-symbols-rounded">signal_cellular_alt_1_bar</span>; return (
<span className={`material-symbols-rounded ${className}`}>signal_cellular_alt_2_bar</span>
);
case "low":
return (
<span className={`material-symbols-rounded ${className}`}>signal_cellular_alt_1_bar</span>
);
default: default:
return <span>N/A</span>; return null;
} }
}; };

View File

@ -92,7 +92,7 @@ class ProjectIssuesServices extends APIService {
projectId: string, projectId: string,
cycleId: string, cycleId: string,
data: { data: {
issue: string[]; issues: string[];
} }
) { ) {
return this.post(CYCLE_DETAIL(workspaceSlug, projectId, cycleId), data) return this.post(CYCLE_DETAIL(workspaceSlug, projectId, cycleId), data)

View File

@ -90,47 +90,7 @@ const OnBoard: NextPage = () => {
<div className="w-full md:w-2/3 lg:w-1/3 p-8 rounded-lg"> <div className="w-full md:w-2/3 lg:w-1/3 p-8 rounded-lg">
{invitations && workspaces ? ( {invitations && workspaces ? (
invitations.length > 0 ? ( invitations.length > 0 ? (
<div className="mt-3 sm:mt-5"> <div>
<div className="mt-2">
<h2 className="text-2xl font-medium mb-4">Join your workspaces</h2>
<div className="space-y-2 mb-12">
{invitations.map((item) => (
<div
className="relative flex items-center border px-4 py-2 rounded"
key={item.id}
>
<div className="ml-3 text-sm flex flex-col items-start w-full">
<h3 className="font-medium text-xl text-gray-700">
{item.workspace.name}
</h3>
<p className="text-sm">invited by {item.workspace.owner.first_name}</p>
</div>
<div className="flex gap-x-2 h-5 items-center">
<div className="h-full flex items-center gap-x-1">
<input
id={`${item.id}`}
aria-describedby="workspaces"
name={`${item.id}`}
checked={invitationsRespond.includes(item.id)}
value={item.workspace.name}
onChange={() => {
handleInvitation(
item,
invitationsRespond.includes(item.id) ? "withdraw" : "accepted"
);
}}
type="checkbox"
className="h-4 w-4 rounded border-gray-300 text-theme focus:ring-indigo-500"
/>
<label htmlFor={item.id} className="text-sm">
Accept
</label>
</div>
</div>
</div>
))}
</div>
</div>
<h2 className="text-lg font-medium text-gray-900">Workspace Invitations</h2> <h2 className="text-lg font-medium text-gray-900">Workspace Invitations</h2>
<p className="mt-1 text-sm text-gray-500"> <p className="mt-1 text-sm text-gray-500">
Select invites that you want to accept. Select invites that you want to accept.

View File

@ -176,7 +176,7 @@ const SingleCycle: React.FC = () => {
.then((res) => { .then((res) => {
issuesServices issuesServices
.addIssueToCycle(activeWorkspace.slug, activeProject.id, destination.droppableId, { .addIssueToCycle(activeWorkspace.slug, activeProject.id, destination.droppableId, {
issue: [result.draggableId.split(",")[1]], issues: [result.draggableId.split(",")[1]],
}) })
.then((res) => { .then((res) => {
console.log(res); console.log(res);

View File

@ -34,7 +34,7 @@ import ConfirmIssueDeletion from "components/project/issues/confirm-issue-deleti
import IssueDetailSidebar from "components/project/issues/issue-detail/issue-detail-sidebar"; import IssueDetailSidebar from "components/project/issues/issue-detail/issue-detail-sidebar";
import IssueActivitySection from "components/project/issues/issue-detail/activity"; import IssueActivitySection from "components/project/issues/issue-detail/activity";
// ui // ui
import { Spinner, TextArea, HeaderButton, Breadcrumbs, BreadcrumbItem } from "ui"; import { Spinner, TextArea, HeaderButton, Breadcrumbs, BreadcrumbItem, CustomMenu } from "ui";
// icons // icons
import { import {
ChevronLeftIcon, ChevronLeftIcon,
@ -215,6 +215,8 @@ const IssueDetail: NextPage = () => {
} }
}; };
console.log("Issue detail", issueDetail);
return ( return (
<AppLayout <AppLayout
noPadding={true} noPadding={true}
@ -531,12 +533,12 @@ const IssueDetail: NextPage = () => {
leaveFrom="transform opacity-100 scale-100" leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95" leaveTo="transform opacity-0 scale-95"
> >
<Menu.Items className="absolute origin-top-right left-0 mt-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none z-10"> <Menu.Items className="absolute origin-top-right left-0 mt-1 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none z-10">
<div className="p-1"> <div className="py-1">
<Menu.Item as="div"> <Menu.Item as="div">
<button <button
type="button" type="button"
className="text-left p-2 text-gray-900 hover:bg-theme hover:text-white rounded-md text-xs whitespace-nowrap w-full" className="text-left p-2 text-gray-900 hover:bg-indigo-50 text-xs whitespace-nowrap w-full"
onClick={() => { onClick={() => {
setIsOpen(true); setIsOpen(true);
setPreloadedData({ setPreloadedData({
@ -551,7 +553,7 @@ const IssueDetail: NextPage = () => {
<Menu.Item as="div"> <Menu.Item as="div">
<button <button
type="button" type="button"
className="p-2 text-left text-gray-900 hover:bg-theme hover:text-white rounded-md text-xs whitespace-nowrap" className="p-2 text-left text-gray-900 hover:bg-indigo-50 text-xs whitespace-nowrap"
onClick={() => { onClick={() => {
setIsAddAsSubIssueOpen(true); setIsAddAsSubIssueOpen(true);
setPreloadedData({ setPreloadedData({

View File

@ -208,7 +208,7 @@ const ProjectIssues: NextPage = () => {
leaveFrom="opacity-100 translate-y-0" leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1" leaveTo="opacity-0 translate-y-1"
> >
<Popover.Panel className="absolute mr-5 right-1/2 z-10 mt-1 w-screen max-w-xs translate-x-1/2 transform p-3 bg-white rounded-lg shadow-lg overflow-hidden"> <Popover.Panel className="absolute mr-5 right-1/2 z-20 mt-1 w-screen max-w-xs translate-x-1/2 transform p-3 bg-white rounded-lg shadow-lg overflow-hidden">
<div className="relative flex flex-col gap-1 gap-y-4"> <div className="relative flex flex-col gap-1 gap-y-4">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<h4 className="text-sm text-gray-600">Group by</h4> <h4 className="text-sm text-gray-600">Group by</h4>