chore: cycle & module sidebar improvement (#3251)

* chore: no lead option added in module lead select dropdown

* chore: module lead select dropdown code refactor

* chore: cycle sidebar improvement

* chore: module sidebar improvement

* style: cycle and module sidebar improvement

* style: app sidebar improvement
This commit is contained in:
Anmol Singh Bhatia 2023-12-27 15:16:13 +05:30 committed by GitHub
parent 440cfc0f20
commit 05eb728c40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 153 additions and 53 deletions

View File

@ -17,7 +17,16 @@ import { CycleDeleteModal } from "components/cycles/delete-modal";
import { CustomRangeDatePicker } from "components/ui"; import { CustomRangeDatePicker } from "components/ui";
import { Avatar, CustomMenu, Loader, LayersIcon } from "@plane/ui"; import { Avatar, CustomMenu, Loader, LayersIcon } from "@plane/ui";
// icons // icons
import { ChevronDown, LinkIcon, Trash2, UserCircle2, AlertCircle, ChevronRight, MoveRight } from "lucide-react"; import {
ChevronDown,
LinkIcon,
Trash2,
UserCircle2,
AlertCircle,
ChevronRight,
CalendarCheck2,
CalendarClock,
} from "lucide-react";
// helpers // helpers
import { copyUrlToClipboard } from "helpers/string.helper"; import { copyUrlToClipboard } from "helpers/string.helper";
import { import {
@ -357,8 +366,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
</div> </div>
</div> </div>
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3 pt-2">
<h4 className="w-full break-words text-xl font-semibold text-custom-text-100">{cycleDetails.name}</h4>
<div className="flex items-center gap-5"> <div className="flex items-center gap-5">
{currentCycle && ( {currentCycle && (
<span <span
@ -373,15 +381,39 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
: `${currentCycle.label}`} : `${currentCycle.label}`}
</span> </span>
)} )}
<div className="relative flex h-full w-52 items-center gap-2.5"> </div>
<Popover className="flex h-full items-center justify-center rounded-lg"> <h4 className="w-full break-words text-xl font-semibold text-custom-text-100">{cycleDetails.name}</h4>
</div>
{cycleDetails.description && (
<span className="w-full whitespace-normal break-words py-2.5 text-sm leading-5 text-custom-text-200">
{cycleDetails.description}
</span>
)}
<div className="flex flex-col gap-5 pb-6 pt-2.5">
<div className="flex items-center justify-start gap-1">
<div className="flex w-1/2 items-center justify-start gap-2 text-custom-text-300">
<CalendarClock className="h-4 w-4" />
<span className="text-base">Start Date</span>
</div>
<div className="relative flex w-1/2 items-center rounded-sm">
<Popover className="flex h-full w-full items-center justify-center rounded-lg">
<Popover.Button <Popover.Button
className={`text-sm font-medium text-custom-text-300 ${ className={`text-sm font-medium text-custom-text-300 w-full rounded-sm cursor-pointer hover:bg-custom-background-80 ${
isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed" isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed"
}`} }`}
disabled={isCompleted || !isEditingAllowed} disabled={isCompleted || !isEditingAllowed}
> >
{areYearsEqual ? renderShortDate(startDate, "_ _") : renderShortMonthDate(startDate, "_ _")} <span
className={`group flex w-full items-center justify-between gap-2 py-1 px-1.5 text-sm ${
watch("start_date") ? "" : "text-custom-text-400"
}`}
>
{areYearsEqual
? renderShortDate(startDate, "No date selected")
: renderShortMonthDate(startDate, "No date selected")}
</span>
</Popover.Button> </Popover.Button>
<Transition <Transition
@ -393,7 +425,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
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 -right-5 top-10 z-20 transform overflow-hidden"> <Popover.Panel className="absolute right-0 top-10 z-20 transform overflow-hidden">
<CustomRangeDatePicker <CustomRangeDatePicker
value={watch("start_date") ? watch("start_date") : cycleDetails?.start_date} value={watch("start_date") ? watch("start_date") : cycleDetails?.start_date}
onChange={(val) => { onChange={(val) => {
@ -410,16 +442,32 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
</Popover.Panel> </Popover.Panel>
</Transition> </Transition>
</Popover> </Popover>
<MoveRight className="h-4 w-4 text-custom-text-300" /> </div>
<Popover className="flex h-full items-center justify-center rounded-lg"> </div>
<div className="flex items-center justify-start gap-1">
<div className="flex w-1/2 items-center justify-start gap-2 text-custom-text-300">
<CalendarCheck2 className="h-4 w-4" />
<span className="text-base">Target Date</span>
</div>
<div className="relative flex w-1/2 items-center rounded-sm">
<Popover className="flex h-full w-full items-center justify-center rounded-lg">
<> <>
<Popover.Button <Popover.Button
className={`text-sm font-medium text-custom-text-300 ${ className={`text-sm font-medium text-custom-text-300 w-full rounded-sm cursor-pointer hover:bg-custom-background-80 ${
isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed" isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed"
}`} }`}
disabled={isCompleted || !isEditingAllowed} disabled={isCompleted || !isEditingAllowed}
> >
{areYearsEqual ? renderShortDate(endDate, "_ _") : renderShortMonthDate(endDate, "_ _")} <span
className={`group flex w-full items-center justify-between gap-2 py-1 px-1.5 text-sm ${
watch("end_date") ? "" : "text-custom-text-400"
}`}
>
{areYearsEqual
? renderShortDate(endDate, "No date selected")
: renderShortMonthDate(endDate, "No date selected")}
</span>
</Popover.Button> </Popover.Button>
<Transition <Transition
@ -431,7 +479,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
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 -right-5 top-10 z-20 transform overflow-hidden"> <Popover.Panel className="absolute right-0 top-10 z-20 transform overflow-hidden">
<CustomRangeDatePicker <CustomRangeDatePicker
value={watch("end_date") ? watch("end_date") : cycleDetails?.end_date} value={watch("end_date") ? watch("end_date") : cycleDetails?.end_date}
onChange={(val) => { onChange={(val) => {
@ -451,15 +499,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
</Popover> </Popover>
</div> </div>
</div> </div>
</div>
{cycleDetails.description && (
<span className="w-full whitespace-normal break-words py-2.5 text-sm leading-5 text-custom-text-200">
{cycleDetails.description}
</span>
)}
<div className="flex flex-col gap-5 pb-6 pt-2.5">
<div className="flex items-center justify-start gap-1"> <div className="flex items-center justify-start gap-1">
<div className="flex w-1/2 items-center justify-start gap-2 text-custom-text-300"> <div className="flex w-1/2 items-center justify-start gap-2 text-custom-text-300">
<UserCircle2 className="h-4 w-4" /> <UserCircle2 className="h-4 w-4" />

View File

@ -7,7 +7,7 @@ import { ProjectMemberService } from "services/project";
import { Avatar, CustomSearchSelect } from "@plane/ui"; import { Avatar, CustomSearchSelect } from "@plane/ui";
// icons // icons
import { Combobox } from "@headlessui/react"; import { Combobox } from "@headlessui/react";
import { UserCircle } from "lucide-react"; import { UserCircle, UserCircle2 } from "lucide-react";
// fetch-keys // fetch-keys
import { PROJECT_MEMBERS } from "constants/fetch-keys"; import { PROJECT_MEMBERS } from "constants/fetch-keys";
@ -65,9 +65,10 @@ export const ModuleLeadSelect: React.FC<Props> = ({ value, onChange }) => {
value="" value=""
className="flex cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5 text-custom-text-200" className="flex cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5 text-custom-text-200"
> >
<span className="flex items-center justify-start gap-1 text-custom-text-200"> <div className="flex items-center gap-2">
<span>No Lead</span> <UserCircle2 className="h-4 w-4" />
</span> No lead
</div>
</Combobox.Option> </Combobox.Option>
} }
onChange={onChange} onChange={onChange}

View File

@ -31,6 +31,17 @@ export const SidebarLeadSelect: FC<Props> = (props) => {
: null : null
); );
const noLeadOption = {
value: "",
query: "No lead",
content: (
<div className="flex items-center gap-2">
<UserCircle2 className="h-4 w-4" />
No lead
</div>
),
};
const options = members?.map((member) => ({ const options = members?.map((member) => ({
value: member.member.id, value: member.member.id,
query: member.member.display_name, query: member.member.display_name,
@ -42,6 +53,8 @@ export const SidebarLeadSelect: FC<Props> = (props) => {
), ),
})); }));
const leadOption = (options || []).concat(noLeadOption);
const selectedOption = members?.find((m) => m.member.id === value)?.member; const selectedOption = members?.find((m) => m.member.id === value)?.member;
return ( return (
@ -69,7 +82,7 @@ export const SidebarLeadSelect: FC<Props> = (props) => {
</div> </div>
) )
} }
options={options} options={leadOption}
maxHeight="md" maxHeight="md"
onChange={onChange} onChange={onChange}
/> />

View File

@ -15,7 +15,17 @@ import ProgressChart from "components/core/sidebar/progress-chart";
import { CustomRangeDatePicker } from "components/ui"; import { CustomRangeDatePicker } from "components/ui";
import { CustomMenu, Loader, LayersIcon, CustomSelect, ModuleStatusIcon } from "@plane/ui"; import { CustomMenu, Loader, LayersIcon, CustomSelect, ModuleStatusIcon } from "@plane/ui";
// icon // icon
import { AlertCircle, ChevronDown, ChevronRight, Info, LinkIcon, MoveRight, Plus, Trash2 } from "lucide-react"; import {
AlertCircle,
CalendarCheck2,
CalendarClock,
ChevronDown,
ChevronRight,
Info,
LinkIcon,
Plus,
Trash2,
} from "lucide-react";
// helpers // helpers
import { import {
isDateGreaterThanToday, isDateGreaterThanToday,
@ -227,7 +237,13 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
else newValues.push(value); else newValues.push(value);
} }
updateFilters(workspaceSlug.toString(), projectId.toString(), EFilterType.FILTERS, { [key]: newValues }, moduleId); updateFilters(
workspaceSlug.toString(),
projectId.toString(),
EFilterType.FILTERS,
{ [key]: newValues },
moduleId
);
}, },
[workspaceSlug, projectId, moduleId, issueFilters, updateFilters] [workspaceSlug, projectId, moduleId, issueFilters, updateFilters]
); );
@ -328,8 +344,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
</div> </div>
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
<h4 className="w-full break-words text-xl font-semibold text-custom-text-100">{moduleDetails.name}</h4> <div className="flex items-center gap-5 pt-2">
<div className="flex items-center gap-5">
<Controller <Controller
control={control} control={control}
name="status" name="status"
@ -365,16 +380,40 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
</CustomSelect> </CustomSelect>
)} )}
/> />
</div>
<h4 className="w-full break-words text-xl font-semibold text-custom-text-100">{moduleDetails.name}</h4>
</div>
<div className="relative flex h-full w-52 items-center gap-2.5"> {moduleDetails.description && (
<Popover className="flex h-full items-center justify-center rounded-lg"> <span className="w-full whitespace-normal break-words py-2.5 text-sm leading-5 text-custom-text-200">
{moduleDetails.description}
</span>
)}
<div className="flex flex-col gap-5 pb-6 pt-2.5">
<div className="flex items-center justify-start gap-1">
<div className="flex w-1/2 items-center justify-start gap-2 text-custom-text-300">
<CalendarClock className="h-4 w-4" />
<span className="text-base">Start Date</span>
</div>
<div className="relative flex w-1/2 items-center rounded-sm">
<Popover className="flex h-full w-full items-center justify-center rounded-lg">
<Popover.Button <Popover.Button
className={`text-sm font-medium text-custom-text-300 ${ className={`text-sm font-medium text-custom-text-300 w-full rounded-sm cursor-pointer hover:bg-custom-background-80 ${
isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed" isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed"
}`} }`}
disabled={!isEditingAllowed} disabled={!isEditingAllowed}
> >
{areYearsEqual ? renderShortDate(startDate, "_ _") : renderShortMonthDate(startDate, "_ _")} <span
className={`group flex w-full items-center justify-between gap-2 py-1 px-1.5 text-sm ${
watch("start_date") ? "" : "text-custom-text-400"
}`}
>
{areYearsEqual
? renderShortDate(startDate, "No date selected")
: renderShortMonthDate(startDate, "No date selected")}
</span>
</Popover.Button> </Popover.Button>
<Transition <Transition
@ -386,7 +425,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
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 -right-5 top-10 z-20 transform overflow-hidden"> <Popover.Panel className="absolute right-0 top-10 z-20 transform overflow-hidden">
<CustomRangeDatePicker <CustomRangeDatePicker
value={watch("start_date") ? watch("start_date") : moduleDetails?.start_date} value={watch("start_date") ? watch("start_date") : moduleDetails?.start_date}
onChange={(val) => { onChange={(val) => {
@ -402,16 +441,32 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
</Popover.Panel> </Popover.Panel>
</Transition> </Transition>
</Popover> </Popover>
<MoveRight className="h-4 w-4 text-custom-text-300" /> </div>
<Popover className="flex h-full items-center justify-center rounded-lg"> </div>
<div className="flex items-center justify-start gap-1">
<div className="flex w-1/2 items-center justify-start gap-2 text-custom-text-300">
<CalendarCheck2 className="h-4 w-4" />
<span className="text-base">Target Date</span>
</div>
<div className="relative flex w-1/2 items-center rounded-sm">
<Popover className="flex h-full w-full items-center justify-center rounded-lg">
<> <>
<Popover.Button <Popover.Button
className={`text-sm font-medium text-custom-text-300 ${ className={`text-sm font-medium text-custom-text-300 w-full rounded-sm cursor-pointer hover:bg-custom-background-80 ${
isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed" isEditingAllowed ? "cursor-pointer" : "cursor-not-allowed"
}`} }`}
disabled={!isEditingAllowed} disabled={!isEditingAllowed}
> >
{areYearsEqual ? renderShortDate(endDate, "_ _") : renderShortMonthDate(endDate, "_ _")} <span
className={`group flex w-full items-center justify-between gap-2 py-1 px-1.5 text-sm ${
watch("target_date") ? "" : "text-custom-text-400"
}`}
>
{areYearsEqual
? renderShortDate(endDate, "No date selected")
: renderShortMonthDate(endDate, "No date selected")}
</span>
</Popover.Button> </Popover.Button>
<Transition <Transition
@ -423,7 +478,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
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 -right-5 top-10 z-20 transform overflow-hidden"> <Popover.Panel className="absolute right-0 top-10 z-20 transform overflow-hidden">
<CustomRangeDatePicker <CustomRangeDatePicker
value={watch("target_date") ? watch("target_date") : moduleDetails?.target_date} value={watch("target_date") ? watch("target_date") : moduleDetails?.target_date}
onChange={(val) => { onChange={(val) => {
@ -442,15 +497,6 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
</Popover> </Popover>
</div> </div>
</div> </div>
</div>
{moduleDetails.description && (
<span className="w-full whitespace-normal break-words py-2.5 text-sm leading-5 text-custom-text-200">
{moduleDetails.description}
</span>
)}
<div className="flex flex-col gap-5 pb-6 pt-2.5">
<Controller <Controller
control={control} control={control}
name="lead" name="lead"

View File

@ -138,9 +138,9 @@ export const ProjectSidebarList: FC = observer(() => {
> >
Favorites Favorites
{open ? ( {open ? (
<ChevronDown className="h-3 w-3 opacity-0 group-hover:opacity-100" /> <ChevronDown className="h-3.5 w-3.5" />
) : ( ) : (
<ChevronRight className="h-3 w-3 opacity-0 group-hover:opacity-100" /> <ChevronRight className="h-3.5 w-3.5" />
)} )}
</Disclosure.Button> </Disclosure.Button>
{isAuthorizedUser && ( {isAuthorizedUser && (
@ -215,9 +215,9 @@ export const ProjectSidebarList: FC = observer(() => {
> >
Projects Projects
{open ? ( {open ? (
<ChevronDown className="h-3 w-3 opacity-0 group-hover:opacity-100" /> <ChevronDown className="h-3.5 w-3.5" />
) : ( ) : (
<ChevronRight className="h-3 w-3 opacity-0 group-hover:opacity-100" /> <ChevronRight className="h-3.5 w-3.5" />
)} )}
</Disclosure.Button> </Disclosure.Button>
{isAuthorizedUser && ( {isAuthorizedUser && (