fix: issue layouts bugs and ui fixes (#3012)
* fix: initial issue creation issue in the list layout * fix kanban drag n drop and updating properties * reduce z index of spreadsheet bottom row to not overlap with other elements * fix state update by using state id instead of state detail's id * fix add default use state for description * add create issue button for project views to be at par with production * save draft issues from modal * chore: added save view button in all layouts applied filters * use useEffect instead of swr for fetching issue details for peek overview * fix: resolved kanban dnd --------- Co-authored-by: rahulramesha <rahulramesham@gmail.com>
This commit is contained in:
parent
55ce748aa1
commit
e585255c4c
16 changed files with 213 additions and 148 deletions
|
|
@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
|
|||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { AppliedFiltersList } from "components/issues";
|
||||
import { AppliedFiltersList, SaveFilterView } from "components/issues";
|
||||
// types
|
||||
import { IIssueFilterOptions } from "types";
|
||||
import { EFilterType } from "store/issues/types";
|
||||
|
||||
export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||
|
||||
const {
|
||||
projectArchivedIssuesFilter: { issueFilters, updateFilters },
|
||||
|
|
@ -69,7 +69,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
|
|||
if (Object.keys(appliedFilters).length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="p-4 flex items-center justify-between">
|
||||
<AppliedFiltersList
|
||||
appliedFilters={appliedFilters}
|
||||
handleClearAllFilters={handleClearAllFilters}
|
||||
|
|
@ -78,6 +78,8 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
|
|||
members={projectMembers?.map((m) => m.member)}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
|
||||
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { AppliedFiltersList } from "components/issues";
|
||||
import { AppliedFiltersList, SaveFilterView } from "components/issues";
|
||||
// types
|
||||
import { IIssueFilterOptions } from "types";
|
||||
import { EFilterType } from "store/issues/types";
|
||||
|
|
@ -75,7 +76,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
if (Object.keys(appliedFilters).length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="p-4 flex items-center justify-between">
|
||||
<AppliedFiltersList
|
||||
appliedFilters={appliedFilters}
|
||||
handleClearAllFilters={handleClearAllFilters}
|
||||
|
|
@ -84,6 +85,8 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
members={projectMembers?.map((m) => m.member)}
|
||||
states={projectStateStore.states?.[cycleId ?? ""]}
|
||||
/>
|
||||
|
||||
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ import { observer } from "mobx-react-lite";
|
|||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { AppliedFiltersList } from "components/issues";
|
||||
import { AppliedFiltersList, SaveFilterView } from "components/issues";
|
||||
// types
|
||||
import { IIssueFilterOptions } from "types";
|
||||
import { EFilterType } from "store/issues/types";
|
||||
|
||||
export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
const { workspaceSlug, projectId } = router.query as { workspaceSlug: string; projectId: string };
|
||||
|
||||
const {
|
||||
projectDraftIssuesFilter: { issueFilters, updateFilters },
|
||||
|
|
@ -64,7 +64,7 @@ export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => {
|
|||
if (Object.keys(appliedFilters).length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="p-4 flex items-center justify-between">
|
||||
<AppliedFiltersList
|
||||
appliedFilters={appliedFilters}
|
||||
handleClearAllFilters={handleClearAllFilters}
|
||||
|
|
@ -73,6 +73,8 @@ export const DraftIssueAppliedFiltersRoot: React.FC = observer(() => {
|
|||
members={projectMembers?.map((m) => m.member)}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
|
||||
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react-lite";
|
|||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { AppliedFiltersList } from "components/issues";
|
||||
import { AppliedFiltersList, SaveFilterView } from "components/issues";
|
||||
// types
|
||||
import { IIssueFilterOptions } from "types";
|
||||
import { EFilterType } from "store/issues/types";
|
||||
|
|
@ -76,7 +76,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
if (Object.keys(appliedFilters).length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="p-4 flex items-center justify-between">
|
||||
<AppliedFiltersList
|
||||
appliedFilters={appliedFilters}
|
||||
handleClearAllFilters={handleClearAllFilters}
|
||||
|
|
@ -85,6 +85,8 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
members={projectMembers?.map((m) => m.member)}
|
||||
states={projectStateStore.states?.[moduleId ?? ""]}
|
||||
/>
|
||||
|
||||
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,14 +4,18 @@ import { observer } from "mobx-react-lite";
|
|||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { AppliedFiltersList } from "components/issues";
|
||||
import { AppliedFiltersList, SaveFilterView } from "components/issues";
|
||||
|
||||
// types
|
||||
import { IIssueFilterOptions } from "types";
|
||||
import { EFilterType } from "store/issues/types";
|
||||
|
||||
export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
const { workspaceSlug, projectId } = router.query as {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
const {
|
||||
projectLabel: { projectLabels },
|
||||
|
|
@ -60,7 +64,7 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
|
|||
if (Object.keys(appliedFilters).length === 0) return null;
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="p-4 flex items-center justify-between">
|
||||
<AppliedFiltersList
|
||||
appliedFilters={appliedFilters}
|
||||
handleClearAllFilters={handleClearAllFilters}
|
||||
|
|
@ -69,6 +73,8 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
|
|||
members={projectMembers?.map((m) => m.member)}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
|
||||
<SaveFilterView workspaceSlug={workspaceSlug} projectId={projectId} filterParams={appliedFilters} />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||
} = useMobxStore();
|
||||
|
||||
const viewDetails = viewId ? projectViewsStore.viewDetails[viewId.toString()] : undefined;
|
||||
const storedFilters = viewId ? projectViewFiltersStore.storedFilters[viewId.toString()] : undefined;
|
||||
|
||||
const userFilters = issueFilters?.filters;
|
||||
// filters whose value not null or empty array
|
||||
|
|
@ -89,7 +88,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||
projectViewsStore.updateView(workspaceSlug.toString(), projectId.toString(), viewId.toString(), {
|
||||
query_data: {
|
||||
...viewDetails.query_data,
|
||||
...(storedFilters ?? {}),
|
||||
...(appliedFilters ?? {}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -104,13 +103,16 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||
members={projectMembers?.map((m) => m.member)}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
{storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data ?? {}) && (
|
||||
<div className="flex items-center justify-center flex-shrink-0">
|
||||
<Button variant="primary" size="sm" onClick={handleUpdateView}>
|
||||
Update view
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{appliedFilters &&
|
||||
viewDetails?.query_data &&
|
||||
areFiltersDifferent(appliedFilters, viewDetails?.query_data ?? {}) && (
|
||||
<div className="flex items-center justify-center flex-shrink-0">
|
||||
<Button variant="primary" size="sm" onClick={handleUpdateView}>
|
||||
Update view
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,3 +15,6 @@ export * from "./spreadsheet";
|
|||
|
||||
// properties
|
||||
export * from "./properties";
|
||||
|
||||
// save view
|
||||
export * from "./save-filter-view";
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
import { memo, useRef, useState } from "react";
|
||||
import { memo } from "react";
|
||||
import { Draggable } from "@hello-pangea/dnd";
|
||||
import isEqual from "lodash/isEqual";
|
||||
// components
|
||||
import { KanBanProperties } from "./properties";
|
||||
// ui
|
||||
import { Tooltip } from "@plane/ui";
|
||||
// hooks
|
||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||
// types
|
||||
import { IIssueDisplayProperties, IIssue } from "types";
|
||||
import { EIssueActions } from "../types";
|
||||
import { useRouter } from "next/router";
|
||||
import { MoreHorizontal } from "lucide-react";
|
||||
|
||||
interface IssueBlockProps {
|
||||
sub_group_id: string;
|
||||
|
|
@ -20,37 +18,28 @@ interface IssueBlockProps {
|
|||
isDragDisabled: boolean;
|
||||
showEmptyGroup: boolean;
|
||||
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
|
||||
quickActions: (
|
||||
sub_group_by: string | null,
|
||||
group_by: string | null,
|
||||
issue: IIssue,
|
||||
customActionButton?: React.ReactElement
|
||||
) => React.ReactNode;
|
||||
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
|
||||
displayProperties: IIssueDisplayProperties | null;
|
||||
isReadOnly: boolean;
|
||||
}
|
||||
|
||||
export const KanBanIssueMemoBlock: React.FC<IssueBlockProps> = (props) => {
|
||||
const {
|
||||
sub_group_id,
|
||||
columnId,
|
||||
index,
|
||||
issue,
|
||||
isDragDisabled,
|
||||
showEmptyGroup,
|
||||
handleIssues,
|
||||
quickActions,
|
||||
displayProperties,
|
||||
isReadOnly,
|
||||
} = props;
|
||||
// router
|
||||
interface IssueDetailsBlockProps {
|
||||
sub_group_id: string;
|
||||
columnId: string;
|
||||
issue: IIssue;
|
||||
showEmptyGroup: boolean;
|
||||
handleIssues: (sub_group_by: string | null, group_by: string | null, issue: IIssue, action: EIssueActions) => void;
|
||||
quickActions: (sub_group_by: string | null, group_by: string | null, issue: IIssue) => React.ReactNode;
|
||||
displayProperties: IIssueDisplayProperties | null;
|
||||
isReadOnly: boolean;
|
||||
}
|
||||
|
||||
const KanbanIssueDetailsBlock: React.FC<IssueDetailsBlockProps> = (props) => {
|
||||
const { sub_group_id, columnId, issue, showEmptyGroup, handleIssues, quickActions, displayProperties, isReadOnly } =
|
||||
props;
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// states
|
||||
const [isMenuActive, setIsMenuActive] = useState(false);
|
||||
|
||||
const menuActionRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const updateIssue = (sub_group_by: string | null, group_by: string | null, issueToUpdate: IIssue) => {
|
||||
if (issueToUpdate) handleIssues(sub_group_by, group_by, issueToUpdate, EIssueActions.UPDATE);
|
||||
};
|
||||
|
|
@ -64,24 +53,70 @@ export const KanBanIssueMemoBlock: React.FC<IssueBlockProps> = (props) => {
|
|||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{displayProperties && displayProperties?.key && (
|
||||
<div className="relative">
|
||||
<div className="text-xs line-clamp-1 text-custom-text-300">
|
||||
{issue.project_detail.identifier}-{issue.sequence_id}
|
||||
</div>
|
||||
<div className="absolute -top-1 right-0 hidden group-hover/kanban-block:block">
|
||||
{quickActions(
|
||||
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
|
||||
!columnId && columnId === "null" ? null : columnId,
|
||||
issue
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
|
||||
<div className="line-clamp-2 text-sm font-medium text-custom-text-100" onClick={handleIssuePeekOverview}>
|
||||
{issue.name}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div>
|
||||
<KanBanProperties
|
||||
sub_group_id={sub_group_id}
|
||||
columnId={columnId}
|
||||
issue={issue}
|
||||
handleIssues={updateIssue}
|
||||
displayProperties={displayProperties}
|
||||
showEmptyGroup={showEmptyGroup}
|
||||
isReadOnly={isReadOnly}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const validateMemo = (prevProps: IssueDetailsBlockProps, nextProps: IssueDetailsBlockProps) => {
|
||||
if (prevProps.issue !== nextProps.issue) return false;
|
||||
if (!isEqual(prevProps.displayProperties, nextProps.displayProperties)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const KanbanIssueMemoBlock = memo(KanbanIssueDetailsBlock, validateMemo);
|
||||
|
||||
export const KanbanIssueBlock: React.FC<IssueBlockProps> = (props) => {
|
||||
const {
|
||||
sub_group_id,
|
||||
columnId,
|
||||
index,
|
||||
issue,
|
||||
isDragDisabled,
|
||||
showEmptyGroup,
|
||||
handleIssues,
|
||||
quickActions,
|
||||
displayProperties,
|
||||
isReadOnly,
|
||||
} = props;
|
||||
|
||||
let draggableId = issue.id;
|
||||
if (columnId) draggableId = `${draggableId}__${columnId}`;
|
||||
if (sub_group_id) draggableId = `${draggableId}__${sub_group_id}`;
|
||||
|
||||
useOutsideClickDetector(menuActionRef, () => setIsMenuActive(false));
|
||||
|
||||
const customActionButton = (
|
||||
<div
|
||||
ref={menuActionRef}
|
||||
className={`w-full cursor-pointer text-custom-sidebar-text-400 rounded p-1 hover:bg-custom-background-80 ${
|
||||
isMenuActive ? "bg-custom-background-80 text-custom-text-100" : "text-custom-text-200"
|
||||
}`}
|
||||
onClick={() => setIsMenuActive(!isMenuActive)}
|
||||
>
|
||||
<MoreHorizontal className="h-3.5 w-3.5" />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Draggable draggableId={draggableId} index={index}>
|
||||
|
|
@ -100,44 +135,16 @@ export const KanBanIssueMemoBlock: React.FC<IssueBlockProps> = (props) => {
|
|||
isDragDisabled ? "" : "hover:cursor-grab"
|
||||
} ${snapshot.isDragging ? `border-custom-primary-100` : `border-transparent`}`}
|
||||
>
|
||||
{displayProperties && displayProperties?.key && (
|
||||
<div className="relative">
|
||||
<div className="text-xs line-clamp-1 text-custom-text-300">
|
||||
{issue.project_detail.identifier}-{issue.sequence_id}
|
||||
</div>
|
||||
<div
|
||||
className={`absolute -top-1 right-0 hidden group-hover/kanban-block:block ${
|
||||
isMenuActive ? "!block" : ""
|
||||
}`}
|
||||
>
|
||||
{quickActions(
|
||||
!sub_group_id && sub_group_id === "null" ? null : sub_group_id,
|
||||
!columnId && columnId === "null" ? null : columnId,
|
||||
issue,
|
||||
customActionButton
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<Tooltip tooltipHeading="Title" tooltipContent={issue.name}>
|
||||
<div
|
||||
className="line-clamp-2 text-sm font-medium text-custom-text-100"
|
||||
onClick={handleIssuePeekOverview}
|
||||
>
|
||||
{issue.name}
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div>
|
||||
<KanBanProperties
|
||||
sub_group_id={sub_group_id}
|
||||
columnId={columnId}
|
||||
issue={issue}
|
||||
handleIssues={updateIssue}
|
||||
displayProperties={displayProperties}
|
||||
showEmptyGroup={showEmptyGroup}
|
||||
isReadOnly={isReadOnly}
|
||||
/>
|
||||
</div>
|
||||
<KanbanIssueMemoBlock
|
||||
sub_group_id={sub_group_id}
|
||||
columnId={columnId}
|
||||
issue={issue}
|
||||
showEmptyGroup={showEmptyGroup}
|
||||
handleIssues={handleIssues}
|
||||
quickActions={quickActions}
|
||||
displayProperties={displayProperties}
|
||||
isReadOnly={isReadOnly}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -145,10 +152,3 @@ export const KanBanIssueMemoBlock: React.FC<IssueBlockProps> = (props) => {
|
|||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const validateMemo = (prevProps: IssueBlockProps, nextProps: IssueBlockProps) => {
|
||||
if (prevProps.issue != nextProps.issue) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
export const KanbanIssueBlock = memo(KanBanIssueMemoBlock, validateMemo);
|
||||
|
|
|
|||
|
|
@ -22,17 +22,20 @@ export const IssueBlocksList: FC<Props> = (props) => {
|
|||
return (
|
||||
<div className="w-full h-full relative divide-y-[0.5px] divide-custom-border-200">
|
||||
{issueIds && issueIds.length > 0 ? (
|
||||
issueIds.map((issueId: string) => (
|
||||
<IssueBlock
|
||||
key={issues[issueId]?.id}
|
||||
columnId={columnId}
|
||||
issue={issues[issueId]}
|
||||
handleIssues={handleIssues}
|
||||
quickActions={quickActions}
|
||||
isReadonly={isReadonly}
|
||||
displayProperties={displayProperties}
|
||||
/>
|
||||
))
|
||||
issueIds.map(
|
||||
(issueId: string) =>
|
||||
issues[issueId] && (
|
||||
<IssueBlock
|
||||
key={issues[issueId].id}
|
||||
columnId={columnId}
|
||||
issue={issues[issueId]}
|
||||
handleIssues={handleIssues}
|
||||
quickActions={quickActions}
|
||||
isReadonly={isReadonly}
|
||||
displayProperties={displayProperties}
|
||||
/>
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<div className="bg-custom-background-100 text-custom-text-400 text-sm p-3">No issues</div>
|
||||
)}
|
||||
|
|
|
|||
33
web/components/issues/issue-layouts/save-filter-view.tsx
Normal file
33
web/components/issues/issue-layouts/save-filter-view.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { FC, useState } from "react";
|
||||
import { Plus } from "lucide-react";
|
||||
import { Button } from "@plane/ui";
|
||||
// components
|
||||
import { CreateUpdateProjectViewModal } from "components/views";
|
||||
|
||||
interface ISaveFilterView {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
filterParams: any;
|
||||
}
|
||||
|
||||
export const SaveFilterView: FC<ISaveFilterView> = (props) => {
|
||||
const { workspaceSlug, projectId, filterParams } = props;
|
||||
|
||||
const [viewModal, setViewModal] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<CreateUpdateProjectViewModal
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
preLoadedData={{ query_data: { ...filterParams } }}
|
||||
isOpen={viewModal}
|
||||
onClose={() => setViewModal(false)}
|
||||
/>
|
||||
|
||||
<Button size="sm" prependIcon={<Plus />} onClick={() => setViewModal(true)}>
|
||||
Save View
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -26,7 +26,7 @@ export const SpreadsheetStateColumn: React.FC<Props> = (props) => {
|
|||
<>
|
||||
<IssuePropertyState
|
||||
projectId={issue.project_detail?.id ?? null}
|
||||
value={issue.state_detail.id}
|
||||
value={issue.state}
|
||||
defaultOptions={issue?.state_detail ? [issue.state_detail] : []}
|
||||
onChange={(data) => onChange({ state: data.id, state_detail: data })}
|
||||
className="h-full w-full"
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ export const SpreadsheetView: React.FC<Props> = observer((props) => {
|
|||
</div>
|
||||
|
||||
<div className="border-t border-custom-border-100">
|
||||
<div className="mb-3 z-50 sticky bottom-0 left-0">
|
||||
<div className="mb-3 z-5 sticky bottom-0 left-0">
|
||||
{enableQuickCreateIssue && (
|
||||
<SpreadsheetQuickAddIssueForm formKey="name" quickAddCallback={quickAddCallback} viewId={viewId} />
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue