forked from github/plane
improve error overlay while dragging over a group (#4551)
This commit is contained in:
parent
794183b640
commit
ca73a11868
@ -5,7 +5,7 @@ import { cn } from "@/helpers/common.helper";
|
||||
|
||||
type Props = {
|
||||
dragColumnOrientation: "justify-start" | "justify-center" | "justify-end";
|
||||
canDropOverIssue: boolean;
|
||||
canOverlayBeVisible: boolean;
|
||||
isDropDisabled: boolean;
|
||||
dropErrorMessage?: string;
|
||||
orderBy: TIssueOrderByOptions | undefined;
|
||||
@ -13,10 +13,16 @@ type Props = {
|
||||
};
|
||||
|
||||
export const GroupDragOverlay = (props: Props) => {
|
||||
const { dragColumnOrientation, canDropOverIssue, isDropDisabled, dropErrorMessage, orderBy, isDraggingOverColumn } =
|
||||
props;
|
||||
const {
|
||||
dragColumnOrientation,
|
||||
canOverlayBeVisible,
|
||||
isDropDisabled,
|
||||
dropErrorMessage,
|
||||
orderBy,
|
||||
isDraggingOverColumn,
|
||||
} = props;
|
||||
|
||||
const shouldOverlay = isDraggingOverColumn && (!canDropOverIssue || isDropDisabled);
|
||||
const shouldOverlayBeVisible = isDraggingOverColumn && canOverlayBeVisible;
|
||||
const readableOrderBy = ISSUE_ORDER_BY_OPTIONS.find((orderByObj) => orderByObj.key === orderBy)?.title;
|
||||
|
||||
return (
|
||||
@ -24,16 +30,16 @@ export const GroupDragOverlay = (props: Props) => {
|
||||
className={cn(
|
||||
`absolute top-0 left-0 h-full w-full items-center text-sm font-medium text-custom-text-300 rounded bg-custom-background-overlay ${dragColumnOrientation}`,
|
||||
{
|
||||
"flex flex-col border-[1px] border-custom-border-300 z-[2]": shouldOverlay,
|
||||
"flex flex-col border-[1px] border-custom-border-300 z-[2]": shouldOverlayBeVisible,
|
||||
},
|
||||
{ hidden: !shouldOverlay }
|
||||
{ hidden: !shouldOverlayBeVisible }
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"p-3 mt-8 flex flex-col rounded items-center",
|
||||
"p-3 my-8 flex flex-col rounded items-center",
|
||||
{
|
||||
"text-custom-text-200": shouldOverlay,
|
||||
"text-custom-text-200": shouldOverlayBeVisible,
|
||||
},
|
||||
{
|
||||
"text-custom-text-error": isDropDisabled,
|
||||
|
@ -25,15 +25,16 @@ import { KanbanStoreType } from "./base-kanban-root";
|
||||
import { HeaderGroupByCard } from "./headers/group-by-card";
|
||||
import { KanbanGroup } from "./kanban-group";
|
||||
|
||||
export interface IGroupByKanBan {
|
||||
export interface IKanBan {
|
||||
issuesMap: IIssueMap;
|
||||
issueIds: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues;
|
||||
displayProperties: IIssueDisplayProperties | undefined;
|
||||
sub_group_by: TIssueGroupByOptions | undefined;
|
||||
group_by: TIssueGroupByOptions | undefined;
|
||||
orderBy: TIssueOrderByOptions | undefined;
|
||||
sub_group_id: string;
|
||||
isDragDisabled: boolean;
|
||||
isDropDisabled?: boolean;
|
||||
dropErrorMessage?: string | undefined;
|
||||
sub_group_id?: string;
|
||||
updateIssue: ((projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>) | undefined;
|
||||
quickActions: TRenderQuickActions;
|
||||
kanbanFilters: TIssueKanbanFilters;
|
||||
@ -56,7 +57,7 @@ export interface IGroupByKanBan {
|
||||
subGroupIssueHeaderCount?: (listId: string) => number;
|
||||
}
|
||||
|
||||
const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
const {
|
||||
issuesMap,
|
||||
issueIds,
|
||||
@ -64,7 +65,6 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
sub_group_by,
|
||||
group_by,
|
||||
sub_group_id = "null",
|
||||
isDragDisabled,
|
||||
updateIssue,
|
||||
quickActions,
|
||||
kanbanFilters,
|
||||
@ -81,6 +81,8 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
showEmptyGroup = true,
|
||||
subGroupIssueHeaderCount,
|
||||
orderBy,
|
||||
isDropDisabled,
|
||||
dropErrorMessage,
|
||||
} = props;
|
||||
|
||||
const member = useMember();
|
||||
@ -89,6 +91,9 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
const cycle = useCycle();
|
||||
const moduleInfo = useModule();
|
||||
const projectState = useProjectState();
|
||||
const issueKanBanView = useKanbanView();
|
||||
|
||||
const isDragDisabled = !issueKanBanView?.getCanUserDragDrop(group_by, sub_group_by);
|
||||
|
||||
const list = getGroupByColumns(
|
||||
group_by as GroupByColumnTypes,
|
||||
@ -175,8 +180,8 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
orderBy={orderBy}
|
||||
sub_group_id={sub_group_id}
|
||||
isDragDisabled={isDragDisabled}
|
||||
isDropDisabled={!!subList.isDropDisabled}
|
||||
dropErrorMessage={subList.dropErrorMessage}
|
||||
isDropDisabled={!!subList.isDropDisabled || !!isDropDisabled}
|
||||
dropErrorMessage={subList.dropErrorMessage ?? dropErrorMessage}
|
||||
updateIssue={updateIssue}
|
||||
quickActions={quickActions}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
@ -194,90 +199,3 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export interface IKanBan {
|
||||
issuesMap: IIssueMap;
|
||||
issueIds: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues;
|
||||
displayProperties: IIssueDisplayProperties | undefined;
|
||||
sub_group_by: TIssueGroupByOptions | undefined;
|
||||
group_by: TIssueGroupByOptions | undefined;
|
||||
orderBy: TIssueOrderByOptions | undefined;
|
||||
sub_group_id?: string;
|
||||
updateIssue: ((projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>) | undefined;
|
||||
quickActions: TRenderQuickActions;
|
||||
kanbanFilters: TIssueKanbanFilters;
|
||||
handleKanbanFilters: (toggle: "group_by" | "sub_group_by", value: string) => void;
|
||||
showEmptyGroup: boolean;
|
||||
enableQuickIssueCreate?: boolean;
|
||||
quickAddCallback?: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
data: TIssue,
|
||||
viewId?: string
|
||||
) => Promise<TIssue | undefined>;
|
||||
viewId?: string;
|
||||
disableIssueCreation?: boolean;
|
||||
storeType: KanbanStoreType;
|
||||
addIssuesToView?: (issueIds: string[]) => Promise<TIssue>;
|
||||
canEditProperties: (projectId: string | undefined) => boolean;
|
||||
scrollableContainerRef?: MutableRefObject<HTMLDivElement | null>;
|
||||
handleOnDrop: (source: GroupDropLocation, destination: GroupDropLocation) => Promise<void>;
|
||||
subGroupIssueHeaderCount?: (listId: string) => number;
|
||||
}
|
||||
|
||||
export const KanBan: React.FC<IKanBan> = observer((props) => {
|
||||
const {
|
||||
issuesMap,
|
||||
issueIds,
|
||||
displayProperties,
|
||||
sub_group_by,
|
||||
group_by,
|
||||
sub_group_id = "null",
|
||||
updateIssue,
|
||||
quickActions,
|
||||
kanbanFilters,
|
||||
handleKanbanFilters,
|
||||
enableQuickIssueCreate,
|
||||
quickAddCallback,
|
||||
viewId,
|
||||
disableIssueCreation,
|
||||
storeType,
|
||||
addIssuesToView,
|
||||
canEditProperties,
|
||||
scrollableContainerRef,
|
||||
handleOnDrop,
|
||||
showEmptyGroup,
|
||||
subGroupIssueHeaderCount,
|
||||
orderBy,
|
||||
} = props;
|
||||
|
||||
const issueKanBanView = useKanbanView();
|
||||
|
||||
return (
|
||||
<GroupByKanBan
|
||||
issuesMap={issuesMap}
|
||||
issueIds={issueIds}
|
||||
displayProperties={displayProperties}
|
||||
group_by={group_by}
|
||||
sub_group_by={sub_group_by}
|
||||
orderBy={orderBy}
|
||||
sub_group_id={sub_group_id}
|
||||
isDragDisabled={!issueKanBanView?.getCanUserDragDrop(group_by, sub_group_by)}
|
||||
updateIssue={updateIssue}
|
||||
quickActions={quickActions}
|
||||
kanbanFilters={kanbanFilters}
|
||||
handleKanbanFilters={handleKanbanFilters}
|
||||
enableQuickIssueCreate={enableQuickIssueCreate}
|
||||
quickAddCallback={quickAddCallback}
|
||||
viewId={viewId}
|
||||
disableIssueCreation={disableIssueCreation}
|
||||
storeType={storeType}
|
||||
addIssuesToView={addIssuesToView}
|
||||
canEditProperties={canEditProperties}
|
||||
scrollableContainerRef={scrollableContainerRef}
|
||||
handleOnDrop={handleOnDrop}
|
||||
showEmptyGroup={showEmptyGroup}
|
||||
subGroupIssueHeaderCount={subGroupIssueHeaderCount}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
@ -187,8 +187,8 @@ export const KanbanGroup = observer((props: IKanbanGroup) => {
|
||||
return preloadedData;
|
||||
};
|
||||
|
||||
const canDropOverIssue = orderBy === "sort_order";
|
||||
const shouldOverlay = isDraggingOverColumn && (!canDropOverIssue || isDropDisabled);
|
||||
const canOverlayBeVisible = orderBy !== "sort_order" || isDropDisabled;
|
||||
const shouldOverlayBeVisible = isDraggingOverColumn && canOverlayBeVisible;
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -196,13 +196,13 @@ export const KanbanGroup = observer((props: IKanbanGroup) => {
|
||||
className={cn(
|
||||
"relative h-full transition-all min-h-[120px]",
|
||||
{ "bg-custom-background-80 rounded": isDraggingOverColumn },
|
||||
{ "vertical-scrollbar scrollbar-md": !sub_group_by && !shouldOverlay }
|
||||
{ "vertical-scrollbar scrollbar-md": !sub_group_by && !shouldOverlayBeVisible }
|
||||
)}
|
||||
ref={columnRef}
|
||||
>
|
||||
<GroupDragOverlay
|
||||
dragColumnOrientation={sub_group_by ? "justify-start": "justify-center" }
|
||||
canDropOverIssue={canDropOverIssue}
|
||||
canOverlayBeVisible={canOverlayBeVisible}
|
||||
isDropDisabled={isDropDisabled}
|
||||
dropErrorMessage={dropErrorMessage}
|
||||
orderBy={orderBy}
|
||||
@ -219,7 +219,7 @@ export const KanbanGroup = observer((props: IKanbanGroup) => {
|
||||
quickActions={quickActions}
|
||||
canEditProperties={canEditProperties}
|
||||
scrollableContainerRef={sub_group_by ? scrollableContainerRef : columnRef}
|
||||
canDropOverIssue={canDropOverIssue}
|
||||
canDropOverIssue={!canOverlayBeVisible}
|
||||
/>
|
||||
|
||||
{enableQuickIssueCreate && !disableIssueCreation && (
|
||||
|
@ -219,6 +219,8 @@ const SubGroupSwimlane: React.FC<ISubGroupSwimlane> = observer((props) => {
|
||||
scrollableContainerRef={scrollableContainerRef}
|
||||
handleOnDrop={handleOnDrop}
|
||||
orderBy={orderBy}
|
||||
isDropDisabled={_list.isDropDisabled}
|
||||
dropErrorMessage={_list.dropErrorMessage}
|
||||
subGroupIssueHeaderCount={(groupByListId: string) =>
|
||||
getSubGroupHeaderIssuesCount(issueIds as TSubGroupedIssues, groupByListId)
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ export const ListGroup = observer((props: Props) => {
|
||||
|
||||
const is_list = group_by === null ? true : false;
|
||||
const isDragAllowed = !!group_by && DRAG_ALLOWED_GROUPS.includes(group_by);
|
||||
const canDropOverIssue = orderBy === "sort_order";
|
||||
const canOverlayBeVisible = orderBy !== "sort_order" || !!group.isDropDisabled;
|
||||
|
||||
const issueCount: number = is_list ? issueIds?.length ?? 0 : issueIds?.[group.id]?.length ?? 0;
|
||||
|
||||
@ -187,6 +187,7 @@ export const ListGroup = observer((props: Props) => {
|
||||
ref={groupRef}
|
||||
className={cn(`relative flex flex-shrink-0 flex-col border-[1px] border-transparent`, {
|
||||
"border-custom-primary-100": isDraggingOverColumn,
|
||||
"border-custom-error-200": isDraggingOverColumn && !!group.isDropDisabled,
|
||||
})}
|
||||
>
|
||||
<div className="sticky top-0 z-[3] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 px-3 pl-5 py-1">
|
||||
@ -205,7 +206,7 @@ export const ListGroup = observer((props: Props) => {
|
||||
<div className="relative">
|
||||
<GroupDragOverlay
|
||||
dragColumnOrientation={dragColumnOrientation}
|
||||
canDropOverIssue={canDropOverIssue}
|
||||
canOverlayBeVisible={canOverlayBeVisible}
|
||||
isDropDisabled={!!group.isDropDisabled}
|
||||
dropErrorMessage={group.dropErrorMessage}
|
||||
orderBy={orderBy}
|
||||
@ -222,7 +223,7 @@ export const ListGroup = observer((props: Props) => {
|
||||
canEditProperties={canEditProperties}
|
||||
containerRef={containerRef}
|
||||
isDragAllowed={isDragAllowed}
|
||||
canDropOverIssue={canDropOverIssue}
|
||||
canDropOverIssue={!canOverlayBeVisible}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user