forked from github/plane
style: list layout (#2566)
This commit is contained in:
parent
08ca016f65
commit
59c52023fb
@ -1,3 +1,4 @@
|
|||||||
|
// FIXME: fix this!!!
|
||||||
import { Placement } from "@blueprintjs/popover2";
|
import { Placement } from "@blueprintjs/popover2";
|
||||||
|
|
||||||
export interface IDropdownProps {
|
export interface IDropdownProps {
|
||||||
|
@ -147,7 +147,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
|||||||
onChange={(layout) => handleLayoutChange(layout)}
|
onChange={(layout) => handleLayoutChange(layout)}
|
||||||
selectedLayout={activeLayout}
|
selectedLayout={activeLayout}
|
||||||
/>
|
/>
|
||||||
<FiltersDropdown title="Filters">
|
<FiltersDropdown title="Filters" placement="bottom-end">
|
||||||
<FilterSelection
|
<FilterSelection
|
||||||
filters={cycleIssueFilterStore.cycleFilters}
|
filters={cycleIssueFilterStore.cycleFilters}
|
||||||
handleFiltersUpdate={handleFiltersUpdate}
|
handleFiltersUpdate={handleFiltersUpdate}
|
||||||
@ -159,7 +159,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
|||||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
<FiltersDropdown title="Display">
|
<FiltersDropdown title="Display" placement="bottom-end">
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
displayFilters={issueFilterStore.userDisplayFilters}
|
displayFilters={issueFilterStore.userDisplayFilters}
|
||||||
displayProperties={issueFilterStore.userDisplayProperties}
|
displayProperties={issueFilterStore.userDisplayProperties}
|
||||||
|
@ -128,7 +128,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
{activeLayout === "spreadsheet" && (
|
{activeLayout === "spreadsheet" && (
|
||||||
<>
|
<>
|
||||||
{!STATIC_VIEW_TYPES.some((word) => router.pathname.includes(word)) && (
|
{!STATIC_VIEW_TYPES.some((word) => router.pathname.includes(word)) && (
|
||||||
<FiltersDropdown title="Filters">
|
<FiltersDropdown title="Filters" placement="bottom-end">
|
||||||
<FilterSelection
|
<FilterSelection
|
||||||
filters={storedFilters ?? {}}
|
filters={storedFilters ?? {}}
|
||||||
handleFiltersUpdate={handleFiltersUpdate}
|
handleFiltersUpdate={handleFiltersUpdate}
|
||||||
@ -140,7 +140,7 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
|
|||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FiltersDropdown title="Display">
|
<FiltersDropdown title="Display" placement="bottom-end">
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
displayFilters={workspaceFilterStore.workspaceDisplayFilters}
|
displayFilters={workspaceFilterStore.workspaceDisplayFilters}
|
||||||
displayProperties={workspaceFilterStore.workspaceDisplayProperties}
|
displayProperties={workspaceFilterStore.workspaceDisplayProperties}
|
||||||
|
@ -150,7 +150,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
|||||||
onChange={(layout) => handleLayoutChange(layout)}
|
onChange={(layout) => handleLayoutChange(layout)}
|
||||||
selectedLayout={activeLayout}
|
selectedLayout={activeLayout}
|
||||||
/>
|
/>
|
||||||
<FiltersDropdown title="Filters">
|
<FiltersDropdown title="Filters" placement="bottom-end">
|
||||||
<FilterSelection
|
<FilterSelection
|
||||||
filters={moduleFilterStore.moduleFilters}
|
filters={moduleFilterStore.moduleFilters}
|
||||||
handleFiltersUpdate={handleFiltersUpdate}
|
handleFiltersUpdate={handleFiltersUpdate}
|
||||||
@ -162,7 +162,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
|||||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
<FiltersDropdown title="Display">
|
<FiltersDropdown title="Display" placement="bottom-end">
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
displayFilters={issueFilterStore.userDisplayFilters}
|
displayFilters={issueFilterStore.userDisplayFilters}
|
||||||
displayProperties={issueFilterStore.userDisplayProperties}
|
displayProperties={issueFilterStore.userDisplayProperties}
|
||||||
|
@ -146,7 +146,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
|||||||
onChange={(layout) => handleLayoutChange(layout)}
|
onChange={(layout) => handleLayoutChange(layout)}
|
||||||
selectedLayout={activeLayout}
|
selectedLayout={activeLayout}
|
||||||
/>
|
/>
|
||||||
<FiltersDropdown title="Filters">
|
<FiltersDropdown title="Filters" placement="bottom-end">
|
||||||
<FilterSelection
|
<FilterSelection
|
||||||
filters={issueFilterStore.userFilters}
|
filters={issueFilterStore.userFilters}
|
||||||
handleFiltersUpdate={handleFiltersUpdate}
|
handleFiltersUpdate={handleFiltersUpdate}
|
||||||
@ -158,7 +158,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
|||||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
<FiltersDropdown title="Display">
|
<FiltersDropdown title="Display" placement="bottom-end">
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
displayFilters={issueFilterStore.userDisplayFilters}
|
displayFilters={issueFilterStore.userDisplayFilters}
|
||||||
displayProperties={issueFilterStore.userDisplayProperties}
|
displayProperties={issueFilterStore.userDisplayProperties}
|
||||||
|
@ -135,7 +135,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
|||||||
onChange={(layout) => handleLayoutChange(layout)}
|
onChange={(layout) => handleLayoutChange(layout)}
|
||||||
selectedLayout={activeLayout}
|
selectedLayout={activeLayout}
|
||||||
/>
|
/>
|
||||||
<FiltersDropdown title="Filters">
|
<FiltersDropdown title="Filters" placement="bottom-end">
|
||||||
<FilterSelection
|
<FilterSelection
|
||||||
filters={storedFilters ?? {}}
|
filters={storedFilters ?? {}}
|
||||||
handleFiltersUpdate={handleFiltersUpdate}
|
handleFiltersUpdate={handleFiltersUpdate}
|
||||||
@ -147,7 +147,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
|||||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
<FiltersDropdown title="Display">
|
<FiltersDropdown title="Display" placement="bottom-end">
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
displayFilters={issueFilterStore.userDisplayFilters}
|
displayFilters={issueFilterStore.userDisplayFilters}
|
||||||
displayProperties={issueFilterStore.userDisplayProperties}
|
displayProperties={issueFilterStore.userDisplayProperties}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Fragment, useState } from "react";
|
import React, { Fragment, useState } from "react";
|
||||||
import { usePopper } from "react-popper";
|
import { usePopper } from "react-popper";
|
||||||
import { Popover, Transition } from "@headlessui/react";
|
import { Popover, Transition } from "@headlessui/react";
|
||||||
|
import { Placement } from "@popperjs/core";
|
||||||
// ui
|
// ui
|
||||||
import { Button } from "@plane/ui";
|
import { Button } from "@plane/ui";
|
||||||
// icons
|
// icons
|
||||||
@ -10,16 +10,17 @@ import { ChevronUp } from "lucide-react";
|
|||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
placement?: Placement;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FiltersDropdown: React.FC<Props> = (props) => {
|
export const FiltersDropdown: React.FC<Props> = (props) => {
|
||||||
const { children, title = "Dropdown" } = props;
|
const { children, title = "Dropdown", placement } = props;
|
||||||
|
|
||||||
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
|
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
|
||||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||||
placement: "auto",
|
placement: placement ?? "auto",
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -27,7 +27,7 @@ export const IssueBlock: React.FC<IssueBlockProps> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="text-sm p-3 relative shadow-custom-shadow-2xs bg-custom-background-100 flex items-center gap-3 border-b border-custom-border-200 hover:bg-custom-background-80">
|
<div className="text-sm p-3 relative bg-custom-background-100 flex items-center gap-3">
|
||||||
{display_properties && display_properties?.key && (
|
{display_properties && display_properties?.key && (
|
||||||
<div className="flex-shrink-0 text-xs text-custom-text-300">
|
<div className="flex-shrink-0 text-xs text-custom-text-300">
|
||||||
{issue?.project_detail?.identifier}-{issue.sequence_id}
|
{issue?.project_detail?.identifier}-{issue.sequence_id}
|
||||||
|
@ -21,9 +21,8 @@ export const IssueBlocksList: FC<Props> = (props) => {
|
|||||||
props;
|
props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="w-full h-full relative divide-y-[0.5px] divide-custom-border-200">
|
||||||
{issues &&
|
{issues && issues.length > 0 ? (
|
||||||
issues?.length > 0 &&
|
|
||||||
issues.map((issue) => (
|
issues.map((issue) => (
|
||||||
<IssueBlock
|
<IssueBlock
|
||||||
key={issue.id}
|
key={issue.id}
|
||||||
@ -37,7 +36,10 @@ export const IssueBlocksList: FC<Props> = (props) => {
|
|||||||
members={members}
|
members={members}
|
||||||
estimates={estimates}
|
estimates={estimates}
|
||||||
/>
|
/>
|
||||||
))}
|
))
|
||||||
</>
|
) : (
|
||||||
|
<div className="bg-custom-background-100 text-custom-text-400 text-sm p-3">No issues</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -53,7 +53,7 @@ const GroupByList: React.FC<IGroupByList> = observer((props) => {
|
|||||||
list.length > 0 &&
|
list.length > 0 &&
|
||||||
list.map((_list: any) => (
|
list.map((_list: any) => (
|
||||||
<div key={getValueFromObject(_list, listKey) as string} className={`flex-shrink-0 flex flex-col`}>
|
<div key={getValueFromObject(_list, listKey) as string} className={`flex-shrink-0 flex flex-col`}>
|
||||||
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky top-0 z-[2] px-3 border-b border-custom-border-100">
|
<div className="flex-shrink-0 w-full py-1 sticky top-0 z-[2] px-3">
|
||||||
<ListGroupByHeaderRoot
|
<ListGroupByHeaderRoot
|
||||||
column_id={getValueFromObject(_list, listKey) as string}
|
column_id={getValueFromObject(_list, listKey) as string}
|
||||||
column_value={_list}
|
column_value={_list}
|
||||||
@ -63,7 +63,6 @@ const GroupByList: React.FC<IGroupByList> = observer((props) => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={`w-full h-full relative transition-all`}>
|
|
||||||
{issues && (
|
{issues && (
|
||||||
<IssueBlocksList
|
<IssueBlocksList
|
||||||
columnId={getValueFromObject(_list, listKey) as string}
|
columnId={getValueFromObject(_list, listKey) as string}
|
||||||
@ -77,7 +76,6 @@ const GroupByList: React.FC<IGroupByList> = observer((props) => {
|
|||||||
estimates={estimates}
|
estimates={estimates}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
{enableQuickIssueCreate && (
|
{enableQuickIssueCreate && (
|
||||||
<ListInlineCreateIssueForm
|
<ListInlineCreateIssueForm
|
||||||
groupId={getValueFromObject(_list, listKey) as string}
|
groupId={getValueFromObject(_list, listKey) as string}
|
||||||
|
@ -161,7 +161,7 @@ export const ListInlineCreateIssueForm: React.FC<Props> = observer((props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="bg-custom-background-100">
|
||||||
<Transition
|
<Transition
|
||||||
show={isOpen}
|
show={isOpen}
|
||||||
enter="transition ease-in-out duration-200 transform"
|
enter="transition ease-in-out duration-200 transform"
|
||||||
@ -189,10 +189,10 @@ export const ListInlineCreateIssueForm: React.FC<Props> = observer((props) => {
|
|||||||
{!isOpen && (
|
{!isOpen && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="flex items-center gap-x-[6px] text-custom-primary-100 px-2 py-1 rounded-md"
|
className="flex items-center gap-x-[6px] text-custom-primary-100 px-3 py-1 rounded-md"
|
||||||
onClick={() => setIsOpen(true)}
|
onClick={() => setIsOpen(true)}
|
||||||
>
|
>
|
||||||
<PlusIcon className="h-4 w-4" />
|
<PlusIcon className="h-3 w-3" />
|
||||||
<span className="text-sm font-medium text-custom-primary-100">New Issue</span>
|
<span className="text-sm font-medium text-custom-primary-100">New Issue</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -62,7 +62,7 @@ export const CycleIssueQuickActions: React.FC<Props> = (props) => {
|
|||||||
if (issueToEdit) handleUpdate({ ...issueToEdit, ...data });
|
if (issueToEdit) handleUpdate({ ...issueToEdit, ...data });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CustomMenu ellipsis>
|
<CustomMenu placement="bottom-start" ellipsis>
|
||||||
<CustomMenu.MenuItem
|
<CustomMenu.MenuItem
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -62,7 +62,7 @@ export const ModuleIssueQuickActions: React.FC<Props> = (props) => {
|
|||||||
if (issueToEdit) handleUpdate({ ...issueToEdit, ...data });
|
if (issueToEdit) handleUpdate({ ...issueToEdit, ...data });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CustomMenu ellipsis>
|
<CustomMenu placement="bottom-start" ellipsis>
|
||||||
<CustomMenu.MenuItem
|
<CustomMenu.MenuItem
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -61,7 +61,7 @@ export const ProjectIssueQuickActions: React.FC<Props> = (props) => {
|
|||||||
if (issueToEdit) handleUpdate({ ...issueToEdit, ...data });
|
if (issueToEdit) handleUpdate({ ...issueToEdit, ...data });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CustomMenu ellipsis>
|
<CustomMenu placement="bottom-start" ellipsis>
|
||||||
<CustomMenu.MenuItem
|
<CustomMenu.MenuItem
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -41,7 +41,7 @@ export const ProfileIssuesFilter = observer(() => {
|
|||||||
selectedLayout={activeLayout}
|
selectedLayout={activeLayout}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FiltersDropdown title="Filters">
|
<FiltersDropdown title="Filters" placement="bottom-end">
|
||||||
<FilterSelection
|
<FilterSelection
|
||||||
filters={profileIssueFiltersStore.userFilters}
|
filters={profileIssueFiltersStore.userFilters}
|
||||||
handleFiltersUpdate={handleFilters}
|
handleFiltersUpdate={handleFilters}
|
||||||
@ -54,7 +54,7 @@ export const ProfileIssuesFilter = observer(() => {
|
|||||||
/>
|
/>
|
||||||
</FiltersDropdown>
|
</FiltersDropdown>
|
||||||
|
|
||||||
<FiltersDropdown title="Display">
|
<FiltersDropdown title="Display" placement="bottom-end">
|
||||||
<DisplayFiltersSelection
|
<DisplayFiltersSelection
|
||||||
displayFilters={profileIssueFiltersStore.userDisplayFilters}
|
displayFilters={profileIssueFiltersStore.userDisplayFilters}
|
||||||
displayProperties={profileIssueFiltersStore.userDisplayProperties}
|
displayProperties={profileIssueFiltersStore.userDisplayProperties}
|
||||||
|
Loading…
Reference in New Issue
Block a user