mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: ui improvement and bug fixes (#1883)
This commit is contained in:
parent
e593a8d4bd
commit
d74ec7bda9
@ -88,6 +88,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
const [contextMenu, setContextMenu] = useState(false);
|
const [contextMenu, setContextMenu] = useState(false);
|
||||||
const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 });
|
const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 });
|
||||||
const [isMenuActive, setIsMenuActive] = useState(false);
|
const [isMenuActive, setIsMenuActive] = useState(false);
|
||||||
|
const [isDropdownActive, setIsDropdownActive] = useState(false);
|
||||||
|
|
||||||
const actionSectionRef = useRef<HTMLDivElement | null>(null);
|
const actionSectionRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
@ -245,7 +246,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
setContextMenuPosition({ x: e.pageX, y: e.pageY });
|
setContextMenuPosition({ x: e.pageX, y: e.pageY });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="group/card relative select-none p-3.5">
|
<div className="flex flex-col justify-between gap-1.5 group/card relative select-none px-3.5 py-3 h-[118px]">
|
||||||
{!isNotAllowed && (
|
{!isNotAllowed && (
|
||||||
<div
|
<div
|
||||||
ref={actionSectionRef}
|
ref={actionSectionRef}
|
||||||
@ -295,16 +296,20 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Link href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}>
|
<Link href={`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`}>
|
||||||
<a>
|
<a className="flex flex-col gap-1.5">
|
||||||
{properties.key && (
|
{properties.key && (
|
||||||
<div className="mb-2.5 text-xs font-medium text-custom-text-200">
|
<div className="text-xs font-medium text-custom-text-200">
|
||||||
{issue.project_detail.identifier}-{issue.sequence_id}
|
{issue.project_detail.identifier}-{issue.sequence_id}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<h5 className="text-sm break-words line-clamp-2">{issue.name}</h5>
|
<h5 className="text-sm break-words line-clamp-2">{issue.name}</h5>
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="mt-2.5 flex overflow-x-scroll items-center gap-2 text-xs">
|
<div
|
||||||
|
className={`flex items-center gap-2 text-xs ${
|
||||||
|
isDropdownActive ? "" : "overflow-x-scroll"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{properties.priority && (
|
{properties.priority && (
|
||||||
<ViewPrioritySelect
|
<ViewPrioritySelect
|
||||||
issue={issue}
|
issue={issue}
|
||||||
@ -327,6 +332,8 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
<ViewStartDateSelect
|
<ViewStartDateSelect
|
||||||
issue={issue}
|
issue={issue}
|
||||||
partialUpdateIssue={partialUpdateIssue}
|
partialUpdateIssue={partialUpdateIssue}
|
||||||
|
handleOnOpen={() => setIsDropdownActive(true)}
|
||||||
|
handleOnClose={() => setIsDropdownActive(false)}
|
||||||
user={user}
|
user={user}
|
||||||
isNotAllowed={isNotAllowed}
|
isNotAllowed={isNotAllowed}
|
||||||
/>
|
/>
|
||||||
@ -335,6 +342,8 @@ export const SingleBoardIssue: React.FC<Props> = ({
|
|||||||
<ViewDueDateSelect
|
<ViewDueDateSelect
|
||||||
issue={issue}
|
issue={issue}
|
||||||
partialUpdateIssue={partialUpdateIssue}
|
partialUpdateIssue={partialUpdateIssue}
|
||||||
|
handleOnOpen={() => setIsDropdownActive(true)}
|
||||||
|
handleOnClose={() => setIsDropdownActive(false)}
|
||||||
user={user}
|
user={user}
|
||||||
isNotAllowed={isNotAllowed}
|
isNotAllowed={isNotAllowed}
|
||||||
/>
|
/>
|
||||||
|
@ -101,7 +101,7 @@ export const AddComment: React.FC<Props> = ({ issueId, user, disabled = false })
|
|||||||
? watch("comment_html")
|
? watch("comment_html")
|
||||||
: value
|
: value
|
||||||
}
|
}
|
||||||
customClassName="p-3 min-h-[50px]"
|
customClassName="p-3 min-h-[50px] shadow-sm"
|
||||||
debouncedUpdatesEnabled={false}
|
debouncedUpdatesEnabled={false}
|
||||||
onChange={(comment_json: Object, comment_html: string) => {
|
onChange={(comment_json: Object, comment_html: string) => {
|
||||||
onChange(comment_html);
|
onChange(comment_html);
|
||||||
|
@ -106,7 +106,7 @@ export const CommentCard: React.FC<Props> = ({ comment, onSubmit, handleCommentD
|
|||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
value={watch("comment_html")}
|
value={watch("comment_html")}
|
||||||
debouncedUpdatesEnabled={false}
|
debouncedUpdatesEnabled={false}
|
||||||
customClassName="min-h-[50px] p-3"
|
customClassName="min-h-[50px] p-3 shadow-sm"
|
||||||
onChange={(comment_json: Object, comment_html: string) => {
|
onChange={(comment_json: Object, comment_html: string) => {
|
||||||
setValue("comment_json", comment_json);
|
setValue("comment_json", comment_json);
|
||||||
setValue("comment_html", comment_html);
|
setValue("comment_html", comment_html);
|
||||||
|
@ -141,7 +141,7 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({
|
|||||||
}
|
}
|
||||||
debouncedUpdatesEnabled={true}
|
debouncedUpdatesEnabled={true}
|
||||||
setIsSubmitting={setIsSubmitting}
|
setIsSubmitting={setIsSubmitting}
|
||||||
customClassName="min-h-[150px]"
|
customClassName="min-h-[150px] shadow-sm"
|
||||||
editorContentCustomClassNames="pb-9"
|
editorContentCustomClassNames="pb-9"
|
||||||
onChange={(description: Object, description_html: string) => {
|
onChange={(description: Object, description_html: string) => {
|
||||||
setIsSubmitting("submitting");
|
setIsSubmitting("submitting");
|
||||||
|
@ -5,9 +5,7 @@ import useSWR from "swr";
|
|||||||
// services
|
// services
|
||||||
import projectServices from "services/project.service";
|
import projectServices from "services/project.service";
|
||||||
// ui
|
// ui
|
||||||
import { AssigneesList, Avatar, CustomSearchSelect } from "components/ui";
|
import { AssigneesList, Avatar, CustomSearchSelect, Icon } from "components/ui";
|
||||||
// icons
|
|
||||||
import { UserGroupIcon } from "@heroicons/react/24/outline";
|
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { PROJECT_MEMBERS } from "constants/fetch-keys";
|
import { PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||||
|
|
||||||
@ -44,15 +42,15 @@ export const IssueAssigneeSelect: React.FC<Props> = ({ projectId, value = [], on
|
|||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
options={options}
|
options={options}
|
||||||
label={
|
customButton={
|
||||||
<div className="flex items-center gap-2 text-custom-text-200">
|
<div className="flex items-center gap-2 cursor-pointer text-xs text-custom-text-200">
|
||||||
{value && value.length > 0 && Array.isArray(value) ? (
|
{value && value.length > 0 && Array.isArray(value) ? (
|
||||||
<div className="flex items-center justify-center gap-2">
|
<div className="-my-0.5 flex items-center justify-center gap-2">
|
||||||
<AssigneesList userIds={value} length={3} showLength={true} />
|
<AssigneesList userIds={value} length={3} showLength={true} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center justify-center gap-2">
|
<div className="flex items-center justify-center gap-2 px-1.5 py-1 rounded shadow-sm border border-custom-border-300">
|
||||||
<UserGroupIcon className="h-4 w-4 text-custom-text-200" />
|
<Icon iconName="person" className="!text-base !leading-4" />
|
||||||
<span className="text-custom-text-200">Assignee</span>
|
<span className="text-custom-text-200">Assignee</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -59,9 +59,9 @@ export const IssueLabelSelect: React.FC<Props> = ({ setIsOpen, value, onChange,
|
|||||||
>
|
>
|
||||||
{({ open }: any) => (
|
{({ open }: any) => (
|
||||||
<>
|
<>
|
||||||
<Combobox.Button className="flex cursor-pointer items-center rounded-md border border-custom-border-200 text-xs shadow-sm duration-200 hover:bg-custom-background-80">
|
<Combobox.Button className="flex cursor-pointer items-center text-xs">
|
||||||
{value && value.length > 0 ? (
|
{value && value.length > 0 ? (
|
||||||
<span className="flex items-center justify-center gap-2 px-3 py-1 text-xs">
|
<span className="flex items-center justify-center gap-2 px-2 py-1 text-xs">
|
||||||
<IssueLabelsList
|
<IssueLabelsList
|
||||||
labels={value.map((v) => issueLabels?.find((l) => l.id === v)?.color) ?? []}
|
labels={value.map((v) => issueLabels?.find((l) => l.id === v)?.color) ?? []}
|
||||||
length={3}
|
length={3}
|
||||||
@ -69,7 +69,7 @@ export const IssueLabelSelect: React.FC<Props> = ({ setIsOpen, value, onChange,
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="flex items-center justify-center gap-2 px-2.5 py-1 text-xs">
|
<span className="flex items-center justify-center gap-2 px-2.5 py-1 text-xs rounded-md border border-custom-border-200 shadow-sm duration-200 hover:bg-custom-background-80">
|
||||||
<TagIcon className="h-3.5 w-3.5 text-custom-text-200" />
|
<TagIcon className="h-3.5 w-3.5 text-custom-text-200" />
|
||||||
<span className=" text-custom-text-200">Label</span>
|
<span className=" text-custom-text-200">Label</span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -396,7 +396,8 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
|
|||||||
start_date: val,
|
start_date: val,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="bg-custom-background-90 w-full"
|
className="bg-custom-background-100"
|
||||||
|
wrapperClassName="w-full"
|
||||||
maxDate={maxDate ?? undefined}
|
maxDate={maxDate ?? undefined}
|
||||||
disabled={isNotAllowed || uneditable}
|
disabled={isNotAllowed || uneditable}
|
||||||
/>
|
/>
|
||||||
@ -424,7 +425,8 @@ export const IssueDetailsSidebar: React.FC<Props> = ({
|
|||||||
target_date: val,
|
target_date: val,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
className="bg-custom-background-90 w-full"
|
className="bg-custom-background-100"
|
||||||
|
wrapperClassName="w-full"
|
||||||
minDate={minDate ?? undefined}
|
minDate={minDate ?? undefined}
|
||||||
disabled={isNotAllowed || uneditable}
|
disabled={isNotAllowed || uneditable}
|
||||||
/>
|
/>
|
||||||
|
@ -13,6 +13,8 @@ import useIssuesView from "hooks/use-issues-view";
|
|||||||
type Props = {
|
type Props = {
|
||||||
issue: IIssue;
|
issue: IIssue;
|
||||||
partialUpdateIssue: (formData: Partial<IIssue>, issue: IIssue) => void;
|
partialUpdateIssue: (formData: Partial<IIssue>, issue: IIssue) => void;
|
||||||
|
handleOnOpen?: () => void;
|
||||||
|
handleOnClose?: () => void;
|
||||||
tooltipPosition?: "top" | "bottom";
|
tooltipPosition?: "top" | "bottom";
|
||||||
noBorder?: boolean;
|
noBorder?: boolean;
|
||||||
user: ICurrentUserResponse | undefined;
|
user: ICurrentUserResponse | undefined;
|
||||||
@ -22,6 +24,8 @@ type Props = {
|
|||||||
export const ViewDueDateSelect: React.FC<Props> = ({
|
export const ViewDueDateSelect: React.FC<Props> = ({
|
||||||
issue,
|
issue,
|
||||||
partialUpdateIssue,
|
partialUpdateIssue,
|
||||||
|
handleOnOpen,
|
||||||
|
handleOnClose,
|
||||||
tooltipPosition = "top",
|
tooltipPosition = "top",
|
||||||
noBorder = false,
|
noBorder = false,
|
||||||
user,
|
user,
|
||||||
@ -80,6 +84,8 @@ export const ViewDueDateSelect: React.FC<Props> = ({
|
|||||||
}`}
|
}`}
|
||||||
minDate={minDate ?? undefined}
|
minDate={minDate ?? undefined}
|
||||||
noBorder={noBorder}
|
noBorder={noBorder}
|
||||||
|
handleOnOpen={handleOnOpen}
|
||||||
|
handleOnClose={handleOnClose}
|
||||||
disabled={isNotAllowed}
|
disabled={isNotAllowed}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,8 @@ import useIssuesView from "hooks/use-issues-view";
|
|||||||
type Props = {
|
type Props = {
|
||||||
issue: IIssue;
|
issue: IIssue;
|
||||||
partialUpdateIssue: (formData: Partial<IIssue>, issue: IIssue) => void;
|
partialUpdateIssue: (formData: Partial<IIssue>, issue: IIssue) => void;
|
||||||
|
handleOnOpen?: () => void;
|
||||||
|
handleOnClose?: () => void;
|
||||||
tooltipPosition?: "top" | "bottom";
|
tooltipPosition?: "top" | "bottom";
|
||||||
noBorder?: boolean;
|
noBorder?: boolean;
|
||||||
user: ICurrentUserResponse | undefined;
|
user: ICurrentUserResponse | undefined;
|
||||||
@ -22,6 +24,8 @@ type Props = {
|
|||||||
export const ViewStartDateSelect: React.FC<Props> = ({
|
export const ViewStartDateSelect: React.FC<Props> = ({
|
||||||
issue,
|
issue,
|
||||||
partialUpdateIssue,
|
partialUpdateIssue,
|
||||||
|
handleOnOpen,
|
||||||
|
handleOnClose,
|
||||||
tooltipPosition = "top",
|
tooltipPosition = "top",
|
||||||
noBorder = false,
|
noBorder = false,
|
||||||
user,
|
user,
|
||||||
@ -72,6 +76,8 @@ export const ViewStartDateSelect: React.FC<Props> = ({
|
|||||||
}`}
|
}`}
|
||||||
maxDate={maxDate ?? undefined}
|
maxDate={maxDate ?? undefined}
|
||||||
noBorder={noBorder}
|
noBorder={noBorder}
|
||||||
|
handleOnOpen={handleOnOpen}
|
||||||
|
handleOnClose={handleOnClose}
|
||||||
disabled={isNotAllowed}
|
disabled={isNotAllowed}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -112,7 +112,7 @@ const Tiptap = (props: ITiptapRichTextEditor) => {
|
|||||||
}, 500);
|
}, 500);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
const editorClassNames = `relative w-full max-w-screen-lg sm:rounded-lg sm:shadow-lg mt-2 p-3 relative focus:outline-none rounded-md
|
const editorClassNames = `relative w-full max-w-screen-lg mt-2 p-3 relative focus:outline-none rounded-lg
|
||||||
${noBorder ? "" : "border border-custom-border-200"} ${
|
${noBorder ? "" : "border border-custom-border-200"} ${
|
||||||
borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0"
|
borderOnFocus ? "focus:border border-custom-border-300" : "focus:border-0"
|
||||||
} ${customClassName}`;
|
} ${customClassName}`;
|
||||||
|
@ -8,10 +8,13 @@ type Props = {
|
|||||||
renderAs?: "input" | "button";
|
renderAs?: "input" | "button";
|
||||||
value: Date | string | null | undefined;
|
value: Date | string | null | undefined;
|
||||||
onChange: (val: string | null) => void;
|
onChange: (val: string | null) => void;
|
||||||
|
handleOnOpen?: () => void;
|
||||||
|
handleOnClose?: () => void;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
displayShortForm?: boolean;
|
displayShortForm?: boolean;
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
noBorder?: boolean;
|
noBorder?: boolean;
|
||||||
|
wrapperClassName?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
isClearable?: boolean;
|
isClearable?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
@ -23,10 +26,13 @@ export const CustomDatePicker: React.FC<Props> = ({
|
|||||||
renderAs = "button",
|
renderAs = "button",
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
|
handleOnOpen,
|
||||||
|
handleOnClose,
|
||||||
placeholder = "Select date",
|
placeholder = "Select date",
|
||||||
displayShortForm = false,
|
displayShortForm = false,
|
||||||
error = false,
|
error = false,
|
||||||
noBorder = false,
|
noBorder = false,
|
||||||
|
wrapperClassName = "",
|
||||||
className = "",
|
className = "",
|
||||||
isClearable = true,
|
isClearable = true,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
@ -40,6 +46,9 @@ export const CustomDatePicker: React.FC<Props> = ({
|
|||||||
if (!val) onChange(null);
|
if (!val) onChange(null);
|
||||||
else onChange(renderDateFormat(val));
|
else onChange(renderDateFormat(val));
|
||||||
}}
|
}}
|
||||||
|
onCalendarOpen={handleOnOpen}
|
||||||
|
onCalendarClose={handleOnClose}
|
||||||
|
wrapperClassName={wrapperClassName}
|
||||||
className={`${
|
className={`${
|
||||||
renderAs === "input"
|
renderAs === "input"
|
||||||
? "block px-2 py-2 text-sm focus:outline-none"
|
? "block px-2 py-2 text-sm focus:outline-none"
|
||||||
|
Loading…
Reference in New Issue
Block a user