style: revamp of the issue details sidebar (#2014)

This commit is contained in:
Aaryan Khandelwal 2023-08-29 20:15:12 +05:30 committed by GitHub
parent d8bbdc14ac
commit 168e79d6df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 219 additions and 234 deletions

View File

@ -48,10 +48,10 @@ export const SidebarAssigneeSelect: React.FC<Props> = ({ value, onChange, disabl
{value && value.length > 0 && Array.isArray(value) ? ( {value && value.length > 0 && Array.isArray(value) ? (
<div className="-my-0.5 flex items-center gap-2"> <div className="-my-0.5 flex items-center gap-2">
<AssigneesList userIds={value} length={3} showLength={false} /> <AssigneesList userIds={value} length={3} showLength={false} />
<span className="text-custom-text-100 text-sm">{value.length} Assignees</span> <span className="text-custom-text-100 text-xs">{value.length} Assignees</span>
</div> </div>
) : ( ) : (
<button type="button" className="bg-custom-background-80 px-2.5 py-0.5 text-sm rounded"> <button type="button" className="bg-custom-background-80 px-2.5 py-0.5 text-xs rounded">
No assignees No assignees
</button> </button>
)} )}

View File

@ -18,7 +18,6 @@ type Props = {
issueId?: string; issueId?: string;
submitChanges: (formData: Partial<IIssue>) => void; submitChanges: (formData: Partial<IIssue>) => void;
watch: UseFormWatch<IIssue>; watch: UseFormWatch<IIssue>;
userAuth: UserAuth;
disabled?: boolean; disabled?: boolean;
}; };
@ -26,7 +25,6 @@ export const SidebarBlockedSelect: React.FC<Props> = ({
issueId, issueId,
submitChanges, submitChanges,
watch, watch,
userAuth,
disabled = false, disabled = false,
}) => { }) => {
const [isBlockedModalOpen, setIsBlockedModalOpen] = useState(false); const [isBlockedModalOpen, setIsBlockedModalOpen] = useState(false);
@ -73,8 +71,6 @@ export const SidebarBlockedSelect: React.FC<Props> = ({
handleClose(); handleClose();
}; };
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disabled;
return ( return (
<> <>
<ExistingIssuesListModal <ExistingIssuesListModal
@ -128,11 +124,11 @@ export const SidebarBlockedSelect: React.FC<Props> = ({
</div> </div>
<button <button
type="button" type="button"
className={`flex w-full text-custom-text-200 ${ className={`bg-custom-background-80 text-xs rounded px-2.5 py-0.5 ${
isNotAllowed ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80" disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80"
} items-center justify-between gap-1 rounded-md border border-custom-border-200 px-2 py-1 text-xs shadow-sm duration-300 focus:outline-none`} }`}
onClick={() => setIsBlockedModalOpen(true)} onClick={() => setIsBlockedModalOpen(true)}
disabled={isNotAllowed} disabled={disabled}
> >
Select issues Select issues
</button> </button>

View File

@ -18,7 +18,6 @@ type Props = {
issueId?: string; issueId?: string;
submitChanges: (formData: Partial<IIssue>) => void; submitChanges: (formData: Partial<IIssue>) => void;
watch: UseFormWatch<IIssue>; watch: UseFormWatch<IIssue>;
userAuth: UserAuth;
disabled?: boolean; disabled?: boolean;
}; };
@ -26,7 +25,6 @@ export const SidebarBlockerSelect: React.FC<Props> = ({
issueId, issueId,
submitChanges, submitChanges,
watch, watch,
userAuth,
disabled = false, disabled = false,
}) => { }) => {
const [isBlockerModalOpen, setIsBlockerModalOpen] = useState(false); const [isBlockerModalOpen, setIsBlockerModalOpen] = useState(false);
@ -73,8 +71,6 @@ export const SidebarBlockerSelect: React.FC<Props> = ({
handleClose(); handleClose();
}; };
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disabled;
return ( return (
<> <>
<ExistingIssuesListModal <ExistingIssuesListModal
@ -130,11 +126,11 @@ export const SidebarBlockerSelect: React.FC<Props> = ({
</div> </div>
<button <button
type="button" type="button"
className={`flex w-full text-custom-text-200 ${ className={`bg-custom-background-80 text-xs rounded px-2.5 py-0.5 ${
isNotAllowed ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80" disabled ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80"
} items-center justify-between gap-1 rounded-md border border-custom-border-200 px-2 py-1 text-xs shadow-sm duration-300 focus:outline-none`} }`}
onClick={() => setIsBlockerModalOpen(true)} onClick={() => setIsBlockerModalOpen(true)}
disabled={isNotAllowed} disabled={disabled}
> >
Select issues Select issues
</button> </button>

View File

@ -11,24 +11,20 @@ import cyclesService from "services/cycles.service";
import { Spinner, CustomSelect, Tooltip } from "components/ui"; import { Spinner, CustomSelect, Tooltip } from "components/ui";
// helper // helper
import { truncateText } from "helpers/string.helper"; import { truncateText } from "helpers/string.helper";
// icons
import { ContrastIcon } from "components/icons";
// types // types
import { ICycle, IIssue, UserAuth } from "types"; import { ICycle, IIssue } from "types";
// fetch-keys // fetch-keys
import { CYCLE_ISSUES, INCOMPLETE_CYCLES_LIST, ISSUE_DETAILS } from "constants/fetch-keys"; import { CYCLE_ISSUES, INCOMPLETE_CYCLES_LIST, ISSUE_DETAILS } from "constants/fetch-keys";
type Props = { type Props = {
issueDetail: IIssue | undefined; issueDetail: IIssue | undefined;
handleCycleChange: (cycle: ICycle) => void; handleCycleChange: (cycle: ICycle) => void;
userAuth: UserAuth;
disabled?: boolean; disabled?: boolean;
}; };
export const SidebarCycleSelect: React.FC<Props> = ({ export const SidebarCycleSelect: React.FC<Props> = ({
issueDetail, issueDetail,
handleCycleChange, handleCycleChange,
userAuth,
disabled = false, disabled = false,
}) => { }) => {
const router = useRouter(); const router = useRouter();
@ -63,26 +59,25 @@ export const SidebarCycleSelect: React.FC<Props> = ({
const issueCycle = issueDetail?.issue_cycle; const issueCycle = issueDetail?.issue_cycle;
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disabled;
return ( return (
<div className="flex flex-wrap items-center py-2">
<div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:basis-1/2">
<ContrastIcon className="h-4 w-4 flex-shrink-0" />
<p>Cycle</p>
</div>
<div className="space-y-1 sm:basis-1/2">
<CustomSelect <CustomSelect
label={ customButton={
<Tooltip <Tooltip
position="left" position="left"
tooltipContent={`${issueCycle ? issueCycle.cycle_detail.name : "No cycle"}`} tooltipContent={`${issueCycle ? issueCycle.cycle_detail.name : "No cycle"}`}
> >
<span className="w-full max-w-[125px] truncate text-left sm:block"> <button
<span className={`${issueCycle ? "text-custom-text-100" : "text-custom-text-200"}`}> type="button"
{issueCycle ? truncateText(issueCycle.cycle_detail.name, 15) : "No cycle"} className={`bg-custom-background-80 text-xs rounded px-2.5 py-0.5 w-full flex ${
</span> disabled ? "cursor-not-allowed" : ""
}`}
>
<span
className={`truncate ${issueCycle ? "text-custom-text-100" : "text-custom-text-200"}`}
>
{issueCycle ? issueCycle.cycle_detail.name : "No cycle"}
</span> </span>
</button>
</Tooltip> </Tooltip>
} }
value={issueCycle ? issueCycle.cycle_detail.id : null} value={issueCycle ? issueCycle.cycle_detail.id : null}
@ -94,7 +89,7 @@ export const SidebarCycleSelect: React.FC<Props> = ({
width="w-full" width="w-full"
position="right" position="right"
maxHeight="rg" maxHeight="rg"
disabled={isNotAllowed} disabled={disabled}
> >
{incompleteCycles ? ( {incompleteCycles ? (
incompleteCycles.length > 0 ? ( incompleteCycles.length > 0 ? (
@ -115,7 +110,5 @@ export const SidebarCycleSelect: React.FC<Props> = ({
<Spinner /> <Spinner />
)} )}
</CustomSelect> </CustomSelect>
</div>
</div>
); );
}; };

View File

@ -14,9 +14,7 @@ type Props = {
}; };
export const SidebarEstimateSelect: React.FC<Props> = ({ value, onChange, disabled = false }) => { export const SidebarEstimateSelect: React.FC<Props> = ({ value, onChange, disabled = false }) => {
const { isEstimateActive, estimatePoints } = useEstimateOption(); const { estimatePoints } = useEstimateOption();
if (!isEstimateActive) return null;
return ( return (
<CustomSelect <CustomSelect

View File

@ -10,24 +10,20 @@ import modulesService from "services/modules.service";
import { Spinner, CustomSelect, Tooltip } from "components/ui"; import { Spinner, CustomSelect, Tooltip } from "components/ui";
// helper // helper
import { truncateText } from "helpers/string.helper"; import { truncateText } from "helpers/string.helper";
// icons
import { RectangleGroupIcon } from "@heroicons/react/24/outline";
// types // types
import { IIssue, IModule, UserAuth } from "types"; import { IIssue, IModule } from "types";
// fetch-keys // fetch-keys
import { ISSUE_DETAILS, MODULE_ISSUES, MODULE_LIST } from "constants/fetch-keys"; import { ISSUE_DETAILS, MODULE_ISSUES, MODULE_LIST } from "constants/fetch-keys";
type Props = { type Props = {
issueDetail: IIssue | undefined; issueDetail: IIssue | undefined;
handleModuleChange: (module: IModule) => void; handleModuleChange: (module: IModule) => void;
userAuth: UserAuth;
disabled?: boolean; disabled?: boolean;
}; };
export const SidebarModuleSelect: React.FC<Props> = ({ export const SidebarModuleSelect: React.FC<Props> = ({
issueDetail, issueDetail,
handleModuleChange, handleModuleChange,
userAuth,
disabled = false, disabled = false,
}) => { }) => {
const router = useRouter(); const router = useRouter();
@ -57,33 +53,29 @@ export const SidebarModuleSelect: React.FC<Props> = ({
const issueModule = issueDetail?.issue_module; const issueModule = issueDetail?.issue_module;
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disabled;
return ( return (
<div className="flex flex-wrap items-center py-2">
<div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:basis-1/2">
<RectangleGroupIcon className="h-4 w-4 flex-shrink-0" />
<p>Module</p>
</div>
<div className="space-y-1 sm:basis-1/2">
<CustomSelect <CustomSelect
label={ customButton={
<Tooltip <Tooltip
position="left" position="left"
tooltipContent={`${ tooltipContent={`${
modules?.find((m) => m.id === issueModule?.module)?.name ?? "No module" modules?.find((m) => m.id === issueModule?.module)?.name ?? "No module"
}`} }`}
> >
<span className="w-full max-w-[125px] truncate text-left sm:block"> <button
<span type="button"
className={`${issueModule ? "text-custom-text-100" : "text-custom-text-200"}`} className={`bg-custom-background-80 text-xs rounded px-2.5 py-0.5 w-full flex ${
disabled ? "cursor-not-allowed" : ""
}`}
> >
{truncateText( <span
`${modules?.find((m) => m.id === issueModule?.module)?.name ?? "No module"}`, className={`truncate ${
15 issueModule ? "text-custom-text-100" : "text-custom-text-200"
)} }`}
</span> >
{modules?.find((m) => m.id === issueModule?.module)?.name ?? "No module"}
</span> </span>
</button>
</Tooltip> </Tooltip>
} }
value={issueModule ? issueModule.module_detail?.id : null} value={issueModule ? issueModule.module_detail?.id : null}
@ -95,7 +87,7 @@ export const SidebarModuleSelect: React.FC<Props> = ({
width="w-full" width="w-full"
position="right" position="right"
maxHeight="rg" maxHeight="rg"
disabled={isNotAllowed} disabled={disabled}
> >
{modules ? ( {modules ? (
modules.length > 0 ? ( modules.length > 0 ? (
@ -116,7 +108,5 @@ export const SidebarModuleSelect: React.FC<Props> = ({
<Spinner /> <Spinner />
)} )}
</CustomSelect> </CustomSelect>
</div>
</div>
); );
}; };

View File

@ -2,8 +2,6 @@ import React, { useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
// icons
import { UserIcon } from "@heroicons/react/24/outline";
// components // components
import { ParentIssuesListModal } from "components/issues"; import { ParentIssuesListModal } from "components/issues";
// types // types
@ -12,14 +10,12 @@ import { IIssue, ISearchIssueResponse, UserAuth } from "types";
type Props = { type Props = {
onChange: (value: string) => void; onChange: (value: string) => void;
issueDetails: IIssue | undefined; issueDetails: IIssue | undefined;
userAuth: UserAuth;
disabled?: boolean; disabled?: boolean;
}; };
export const SidebarParentSelect: React.FC<Props> = ({ export const SidebarParentSelect: React.FC<Props> = ({
onChange, onChange,
issueDetails, issueDetails,
userAuth,
disabled = false, disabled = false,
}) => { }) => {
const [isParentModalOpen, setIsParentModalOpen] = useState(false); const [isParentModalOpen, setIsParentModalOpen] = useState(false);
@ -28,15 +24,8 @@ export const SidebarParentSelect: React.FC<Props> = ({
const router = useRouter(); const router = useRouter();
const { projectId, issueId } = router.query; const { projectId, issueId } = router.query;
const isNotAllowed = userAuth.isGuest || userAuth.isViewer || disabled;
return ( return (
<div className="flex flex-wrap items-center py-2"> <>
<div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:basis-1/2">
<UserIcon className="h-4 w-4 flex-shrink-0" />
<p>Parent</p>
</div>
<div className="sm:basis-1/2">
<ParentIssuesListModal <ParentIssuesListModal
isOpen={isParentModalOpen} isOpen={isParentModalOpen}
handleClose={() => setIsParentModalOpen(false)} handleClose={() => setIsParentModalOpen(false)}
@ -49,11 +38,11 @@ export const SidebarParentSelect: React.FC<Props> = ({
/> />
<button <button
type="button" type="button"
className={`flex w-full ${ className={`bg-custom-background-80 text-xs rounded px-2.5 py-0.5 ${
isNotAllowed ? "cursor-not-allowed" : "cursor-pointer hover:bg-custom-background-80" disabled ? "cursor-not-allowed" : "cursor-pointer "
} items-center justify-between gap-1 rounded-md border border-custom-border-200 px-2 py-1 text-xs shadow-sm duration-300 focus:outline-none`} }`}
onClick={() => setIsParentModalOpen(true)} onClick={() => setIsParentModalOpen(true)}
disabled={isNotAllowed} disabled={disabled}
> >
{selectedParentIssue && issueDetails?.parent ? ( {selectedParentIssue && issueDetails?.parent ? (
`${selectedParentIssue.project__identifier}-${selectedParentIssue.sequence_id}` `${selectedParentIssue.project__identifier}-${selectedParentIssue.sequence_id}`
@ -63,7 +52,6 @@ export const SidebarParentSelect: React.FC<Props> = ({
<span className="text-custom-text-200">Select issue</span> <span className="text-custom-text-200">Select issue</span>
)} )}
</button> </button>
</div> </>
</div>
); );
}; };

View File

@ -18,7 +18,7 @@ export const SidebarPrioritySelect: React.FC<Props> = ({ value, onChange, disabl
customButton={ customButton={
<button <button
type="button" type="button"
className={`flex items-center gap-1.5 text-left text-sm capitalize rounded px-2.5 py-0.5 ${ className={`flex items-center gap-1.5 text-left text-xs capitalize rounded px-2.5 py-0.5 ${
value === "urgent" value === "urgent"
? "border-red-500/20 bg-red-500/20 text-red-500" ? "border-red-500/20 bg-red-500/20 text-red-500"
: value === "high" : value === "high"

View File

@ -39,7 +39,7 @@ export const SidebarStateSelect: React.FC<Props> = ({ value, onChange, disabled
return ( return (
<CustomSelect <CustomSelect
customButton={ customButton={
<button type="button" className="bg-custom-background-80 text-sm rounded px-2.5 py-0.5"> <button type="button" className="bg-custom-background-80 text-xs rounded px-2.5 py-0.5">
{selectedState ? ( {selectedState ? (
<div className="flex items-center gap-1.5 text-left text-custom-text-100"> <div className="flex items-center gap-1.5 text-left text-custom-text-100">
{getStateGroupIcon( {getStateGroupIcon(

View File

@ -10,6 +10,7 @@ import { Controller, UseFormWatch } from "react-hook-form";
import useToast from "hooks/use-toast"; import useToast from "hooks/use-toast";
import useUserAuth from "hooks/use-user-auth"; import useUserAuth from "hooks/use-user-auth";
import useUserIssueNotificationSubscription from "hooks/use-issue-notification-subscription"; import useUserIssueNotificationSubscription from "hooks/use-issue-notification-subscription";
import useEstimateOption from "hooks/use-estimate-option";
// services // services
import issuesService from "services/issues.service"; import issuesService from "services/issues.service";
import modulesService from "services/modules.service"; import modulesService from "services/modules.service";
@ -42,6 +43,8 @@ import {
ChartBarIcon, ChartBarIcon,
UserGroupIcon, UserGroupIcon,
PlayIcon, PlayIcon,
UserIcon,
RectangleGroupIcon,
} from "@heroicons/react/24/outline"; } from "@heroicons/react/24/outline";
// helpers // helpers
import { copyTextToClipboard } from "helpers/string.helper"; import { copyTextToClipboard } from "helpers/string.helper";
@ -49,6 +52,7 @@ import { copyTextToClipboard } from "helpers/string.helper";
import type { ICycle, IIssue, IIssueLink, linkDetails, IModule } from "types"; import type { ICycle, IIssue, IIssueLink, linkDetails, IModule } from "types";
// fetch-keys // fetch-keys
import { ISSUE_DETAILS } from "constants/fetch-keys"; import { ISSUE_DETAILS } from "constants/fetch-keys";
import { ContrastIcon } from "components/icons";
type Props = { type Props = {
control: any; control: any;
@ -93,6 +97,8 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
const { user } = useUserAuth(); const { user } = useUserAuth();
const { isEstimateActive } = useEstimateOption();
const { loading, handleSubscribe, handleUnsubscribe, subscribed } = const { loading, handleSubscribe, handleUnsubscribe, subscribed } =
useUserIssueNotificationSubscription(workspaceSlug, projectId, issueId); useUserIssueNotificationSubscription(workspaceSlug, projectId, issueId);
@ -403,7 +409,8 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
</div> </div>
</div> </div>
)} )}
{(fieldsToShow.includes("all") || fieldsToShow.includes("estimate")) && ( {(fieldsToShow.includes("all") || fieldsToShow.includes("estimate")) &&
isEstimateActive && (
<div className="flex flex-wrap items-center py-2"> <div className="flex flex-wrap items-center py-2">
<div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:basis-1/2"> <div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:basis-1/2">
<PlayIcon className="h-4 w-4 flex-shrink-0 -rotate-90" /> <PlayIcon className="h-4 w-4 flex-shrink-0 -rotate-90" />
@ -431,6 +438,12 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
{showSecondSection && ( {showSecondSection && (
<div className="py-1"> <div className="py-1">
{(fieldsToShow.includes("all") || fieldsToShow.includes("parent")) && ( {(fieldsToShow.includes("all") || fieldsToShow.includes("parent")) && (
<div className="flex flex-wrap items-center py-2">
<div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:basis-1/2">
<UserIcon className="h-4 w-4 flex-shrink-0" />
<p>Parent</p>
</div>
<div className="sm:basis-1/2">
<Controller <Controller
control={control} control={control}
name="parent" name="parent"
@ -441,19 +454,19 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
onChange(val); onChange(val);
}} }}
issueDetails={issueDetail} issueDetails={issueDetail}
userAuth={memberRole} disabled={memberRole.isGuest || memberRole.isViewer || uneditable}
disabled={uneditable}
/> />
)} )}
/> />
</div>
</div>
)} )}
{(fieldsToShow.includes("all") || fieldsToShow.includes("blocker")) && ( {(fieldsToShow.includes("all") || fieldsToShow.includes("blocker")) && (
<SidebarBlockerSelect <SidebarBlockerSelect
issueId={issueId as string} issueId={issueId as string}
submitChanges={submitChanges} submitChanges={submitChanges}
watch={watchIssue} watch={watchIssue}
userAuth={memberRole} disabled={memberRole.isGuest || memberRole.isViewer || uneditable}
disabled={uneditable}
/> />
)} )}
{(fieldsToShow.includes("all") || fieldsToShow.includes("blocked")) && ( {(fieldsToShow.includes("all") || fieldsToShow.includes("blocked")) && (
@ -461,8 +474,7 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
issueId={issueId as string} issueId={issueId as string}
submitChanges={submitChanges} submitChanges={submitChanges}
watch={watchIssue} watch={watchIssue}
userAuth={memberRole} disabled={memberRole.isGuest || memberRole.isViewer || uneditable}
disabled={uneditable}
/> />
)} )}
{(fieldsToShow.includes("all") || fieldsToShow.includes("startDate")) && ( {(fieldsToShow.includes("all") || fieldsToShow.includes("startDate")) && (
@ -484,8 +496,7 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
start_date: val, start_date: val,
}) })
} }
className="bg-custom-background-100" className="bg-custom-background-80 border-none"
wrapperClassName="w-full"
maxDate={maxDate ?? undefined} maxDate={maxDate ?? undefined}
disabled={isNotAllowed || uneditable} disabled={isNotAllowed || uneditable}
/> />
@ -513,8 +524,7 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
target_date: val, target_date: val,
}) })
} }
className="bg-custom-background-100" className="bg-custom-background-80 border-none"
wrapperClassName="w-full"
minDate={minDate ?? undefined} minDate={minDate ?? undefined}
disabled={isNotAllowed || uneditable} disabled={isNotAllowed || uneditable}
/> />
@ -528,20 +538,34 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
{showThirdSection && ( {showThirdSection && (
<div className="py-1"> <div className="py-1">
{(fieldsToShow.includes("all") || fieldsToShow.includes("cycle")) && ( {(fieldsToShow.includes("all") || fieldsToShow.includes("cycle")) && (
<div className="flex flex-wrap items-center py-2">
<div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:w-1/2">
<ContrastIcon className="h-4 w-4 flex-shrink-0" />
<p>Cycle</p>
</div>
<div className="space-y-1 sm:w-1/2">
<SidebarCycleSelect <SidebarCycleSelect
issueDetail={issueDetail} issueDetail={issueDetail}
handleCycleChange={handleCycleChange} handleCycleChange={handleCycleChange}
userAuth={memberRole} disabled={memberRole.isGuest || memberRole.isViewer || uneditable}
disabled={uneditable}
/> />
</div>
</div>
)} )}
{(fieldsToShow.includes("all") || fieldsToShow.includes("module")) && ( {(fieldsToShow.includes("all") || fieldsToShow.includes("module")) && (
<div className="flex flex-wrap items-center py-2">
<div className="flex items-center gap-x-2 text-sm text-custom-text-200 sm:w-1/2">
<RectangleGroupIcon className="h-4 w-4 flex-shrink-0" />
<p>Module</p>
</div>
<div className="space-y-1 sm:w-1/2">
<SidebarModuleSelect <SidebarModuleSelect
issueDetail={issueDetail} issueDetail={issueDetail}
handleModuleChange={handleModuleChange} handleModuleChange={handleModuleChange}
userAuth={memberRole} disabled={memberRole.isGuest || memberRole.isViewer || uneditable}
disabled={uneditable}
/> />
</div>
</div>
)} )}
</div> </div>
)} )}