feat: spreadsheet view improvements (#1379)

* feat: quick menu for spreadsheet view added ,style: spreadsheet view column updated ,fix: z-index issue

* feat: sorting indicator, style: spreadsheet column
This commit is contained in:
Anmol Singh Bhatia 2023-06-23 21:33:24 +05:30 committed by GitHub
parent ca7d3309d3
commit 160cc014a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 125 additions and 82 deletions

View File

@ -128,15 +128,15 @@ export const SingleSpreadsheetIssue: React.FC<Props> = ({
className="relative group grid auto-rows-[minmax(44px,1fr)] hover:rounded-sm hover:bg-brand-surface-2 border-b border-brand-base w-full min-w-max" className="relative group grid auto-rows-[minmax(44px,1fr)] hover:rounded-sm hover:bg-brand-surface-2 border-b border-brand-base w-full min-w-max"
style={{ gridTemplateColumns }} style={{ gridTemplateColumns }}
> >
<div className="flex gap-1.5 items-center px-4 sticky left-0 z-10 text-brand-secondary bg-brand-base group-hover:text-brand-base group-hover:bg-brand-surface-2 border-brand-base w-full"> <div className="flex gap-1.5 items-center px-4 sticky left-0 z-[1] text-brand-secondary bg-brand-base group-hover:text-brand-base group-hover:bg-brand-surface-2 border-brand-base w-full">
<span className="flex gap-1 items-center" style={issue.parent ? { paddingLeft } : {}}> <span className="flex gap-1 items-center" style={issue.parent ? { paddingLeft } : {}}>
{properties.key && ( <div className="flex items-center cursor-pointer text-xs text-center hover:text-brand-base w-14 opacity-100 group-hover:opacity-0">
<> {properties.key && (
<div className="flex items-center cursor-pointer text-xs text-center hover:text-brand-base w-14 "> <span>
{issue.project_detail?.identifier}-{issue.sequence_id} {issue.project_detail?.identifier}-{issue.sequence_id}
</div> </span>
</> )}
)} </div>
<div className="h-5 w-5"> <div className="h-5 w-5">
{issue.sub_issues_count > 0 && ( {issue.sub_issues_count > 0 && (
@ -237,9 +237,14 @@ export const SingleSpreadsheetIssue: React.FC<Props> = ({
/> />
</div> </div>
)} )}
<div className="absolute top-2.5 right-2.5 z-30 cursor-pointer opacity-0 group-hover:opacity-100"> <div
className="absolute top-2.5 z-10 cursor-pointer opacity-0 group-hover:opacity-100"
style={{
left: `${nestingLevel * 68 + 24}px`,
}}
>
{!isNotAllowed && ( {!isNotAllowed && (
<CustomMenu width="auto" ellipsis> <CustomMenu width="auto" position="left" ellipsis>
<CustomMenu.MenuItem onClick={handleEditIssue}> <CustomMenu.MenuItem onClick={handleEditIssue}>
<div className="flex items-center justify-start gap-2"> <div className="flex items-center justify-start gap-2">
<PencilIcon className="h-4 w-4" /> <PencilIcon className="h-4 w-4" />

View File

@ -19,13 +19,17 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
"spreadsheetViewSorting", "spreadsheetViewSorting",
"" ""
); );
const { storedValue: activeSortingProperty, setValue: setActiveSortingProperty } =
useLocalStorage("spreadsheetViewActiveSortingProperty", "");
const { orderBy, setOrderBy } = useSpreadsheetIssuesView(); const { orderBy, setOrderBy } = useSpreadsheetIssuesView();
const handleOrderBy = (order: TIssueOrderByOptions, itemKey: string) => { const handleOrderBy = (order: TIssueOrderByOptions, itemKey: string) => {
setOrderBy(order); setOrderBy(order);
setSelectedMenuItem(`${order}_${itemKey}`); setSelectedMenuItem(`${order}_${itemKey}`);
setActiveSortingProperty(order === "-created_at" ? "" : itemKey);
}; };
return ( return (
<div <div
className={`grid auto-rows-[minmax(36px,1fr)] w-full min-w-max`} className={`grid auto-rows-[minmax(36px,1fr)] w-full min-w-max`}
@ -35,39 +39,34 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
if (col.isActive) { if (col.isActive) {
return ( return (
<div <div
className={`bg-brand-surface-2 ${ className={`bg-brand-surface-1 w-full ${
col.propertyName === "title" ? "sticky left-0 z-20 bg-brand-surface-2 pl-24" : "" col.propertyName === "title" ? "sticky left-0 z-[2] bg-brand-surface-1 pl-24" : ""
}`} }`}
> >
{col.propertyName === "title" || col.propertyName === "priority" ? ( {col.propertyName === "title" ? (
<div <div
className={`flex items-center justify-start gap-1.5 cursor-default text-sm text-brand-secondary text-current py-2.5 px-2`} className={`flex items-center justify-start gap-1.5 cursor-default text-sm text-brand-secondary text-current w-full py-2.5 px-2`}
> >
{col.icon ? (
<col.icon
className={`text-brand-secondary ${
col.propertyName === "estimate" ? "-rotate-90" : ""
}`}
aria-hidden="true"
height="14"
width="14"
/>
) : col.propertyName === "priority" ? (
<span className="text-sm material-symbols-rounded text-brand-secondary">
signal_cellular_alt
</span>
) : (
""
)}
{col.colName} {col.colName}
</div> </div>
) : ( ) : (
<CustomMenu <CustomMenu
className="!w-full"
customButton={ customButton={
<div <div
className={`group flex items-center justify-start gap-1.5 cursor-pointer text-sm text-brand-secondary text-current hover:text-brand-base py-2.5 px-2`} className={`relative group flex items-center justify-start gap-1.5 cursor-pointer text-sm text-brand-secondary text-current hover:text-brand-base w-full py-3 px-2 ${
activeSortingProperty === col.propertyName ? "bg-brand-surface-2" : ""
}`}
> >
{activeSortingProperty === col.propertyName && (
<div className="absolute top-1 right-1.5">
<Icon
iconName="filter_list"
className="flex items-center justify-center h-3.5 w-3.5 rounded-full bg-brand-accent text-xs text-white"
/>
</div>
)}
{col.icon ? ( {col.icon ? (
<col.icon <col.icon
className={`text-brand-secondary group-hover:text-brand-base ${ className={`text-brand-secondary group-hover:text-brand-base ${
@ -110,25 +109,42 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
: "text-brand-secondary hover:text-brand-base" : "text-brand-secondary hover:text-brand-base"
}`} }`}
> >
<div className="flex gap-1.5 items-center"> <div className="flex gap-2 items-center">
{col.propertyName === "assignee" || col.propertyName === "labels" ? ( {col.propertyName === "assignee" || col.propertyName === "labels" ? (
<> <>
<span>A-Z</span> <span className="relative flex items-center h-6 w-6">
<span>Ascending</span> <Icon
iconName="east"
className="absolute left-0 rotate-90 text-xs leading-3"
/>
<Icon iconName="sort" className="absolute right-0 text-sm" />
</span>
<span>A</span>
<Icon iconName="east" className="text-sm" />
<span>Z</span>
</> </>
) : col.propertyName === "due_date" ? ( ) : col.propertyName === "due_date" ? (
<> <>
<span>1-9</span> <span className="relative flex items-center h-6 w-6">
<span>Ascending</span> <Icon
</> iconName="east"
) : col.propertyName === "estimate" ? ( className="absolute left-0 rotate-90 text-xs leading-3"
<> />
<span>0</span> <Icon iconName="sort" className="absolute right-0 text-sm" />
</span>
<span>New</span>
<Icon iconName="east" className="text-sm" /> <Icon iconName="east" className="text-sm" />
<span>10</span> <span>Old</span>
</> </>
) : ( ) : (
<> <>
<span className="relative flex items-center h-6 w-6">
<Icon
iconName="east"
className="absolute left-0 rotate-90 text-xs leading-3"
/>
<Icon iconName="sort" className="absolute right-0 text-sm" />
</span>
<span>First</span> <span>First</span>
<Icon iconName="east" className="text-sm" /> <Icon iconName="east" className="text-sm" />
<span>Last</span> <span>Last</span>
@ -146,7 +162,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
</div> </div>
</CustomMenu.MenuItem> </CustomMenu.MenuItem>
<CustomMenu.MenuItem <CustomMenu.MenuItem
className={`${ className={`mt-0.5 ${
selectedMenuItem === `${col.descendingOrder}_${col.propertyName}` selectedMenuItem === `${col.descendingOrder}_${col.propertyName}`
? "bg-brand-surface-2" ? "bg-brand-surface-2"
: "" : ""
@ -163,25 +179,51 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
: "text-brand-secondary hover:text-brand-base" : "text-brand-secondary hover:text-brand-base"
}`} }`}
> >
<div className="flex gap-1.5 items-center"> <div className="flex gap-2 items-center">
{col.propertyName === "assignee" || col.propertyName === "labels" ? ( {col.propertyName === "assignee" || col.propertyName === "labels" ? (
<> <>
<span>Z-A</span> <span className="relative flex items-center h-6 w-6">
<span>Descending</span> <Icon
iconName="east"
className="absolute left-0 -rotate-90 text-xs leading-3"
/>
<Icon
iconName="sort"
className="absolute rotate-180 transform scale-x-[-1] right-0 text-sm"
/>
</span>
<span>Z</span>
<Icon iconName="east" className="text-sm" />
<span>A</span>
</> </>
) : col.propertyName === "due_date" ? ( ) : col.propertyName === "due_date" ? (
<> <>
<span>9-1</span> <span className="relative flex items-center h-6 w-6">
<span>Descending</span> <Icon
</> iconName="east"
) : col.propertyName === "estimate" ? ( className="absolute left-0 -rotate-90 text-xs leading-3"
<> />
<span>10</span> <Icon
iconName="sort"
className="absolute rotate-180 transform scale-x-[-1] right-0 text-sm"
/>
</span>
<span>Old</span>
<Icon iconName="east" className="text-sm" /> <Icon iconName="east" className="text-sm" />
<span>0</span> <span>New</span>
</> </>
) : ( ) : (
<> <>
<span className="relative flex items-center h-6 w-6">
<Icon
iconName="east"
className="absolute left-0 -rotate-90 text-xs leading-3"
/>
<Icon
iconName="sort"
className="absolute rotate-180 transform scale-x-[-1] right-0 text-sm"
/>
</span>
<span>Last</span> <span>Last</span>
<Icon iconName="east" className="text-sm" /> <Icon iconName="east" className="text-sm" />
<span>First</span> <span>First</span>
@ -198,38 +240,32 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
/> />
</div> </div>
</CustomMenu.MenuItem> </CustomMenu.MenuItem>
<CustomMenu.MenuItem {selectedMenuItem &&
className={`${ selectedMenuItem !== "" &&
selectedMenuItem === `-created_at_${col.propertyName}` orderBy !== "-created_at" &&
? "bg-brand-surface-2" selectedMenuItem.includes(col.propertyName) && (
: "" <CustomMenu.MenuItem
}`} className={`mt-0.5${
key={col.property}
onClick={() => {
handleOrderBy("-created_at", col.propertyName);
}}
>
<div
className={`group flex gap-1.5 px-1 items-center justify-between ${
selectedMenuItem === `-created_at_${col.propertyName}`
? "text-brand-base"
: "text-brand-secondary hover:text-brand-base"
}`}
>
<div className="flex gap-1.5 items-center">
<Icon iconName="block" className="text-sm" />
<span>None</span>
</div>
<CheckIcon
className={`h-3.5 w-3.5 opacity-0 group-hover:opacity-100 ${
selectedMenuItem === `-created_at_${col.propertyName}` selectedMenuItem === `-created_at_${col.propertyName}`
? "opacity-100" ? "bg-brand-surface-2"
: "" : ""
}`} }`}
/> key={col.property}
</div> onClick={() => {
</CustomMenu.MenuItem> handleOrderBy("-created_at", col.propertyName);
}}
>
<div className={`group flex gap-1.5 px-1 items-center justify-between `}>
<div className="flex gap-1.5 items-center">
<span className="relative flex items-center justify-center h-6 w-6">
<Icon iconName="ink_eraser" className="text-sm" />
</span>
<span>Clear sorting</span>
</div>
</div>
</CustomMenu.MenuItem>
)}
</CustomMenu> </CustomMenu>
)} )}
</div> </div>

View File

@ -56,7 +56,7 @@ export const SpreadsheetView: React.FC<Props> = ({
return ( return (
<div className="h-full rounded-lg text-brand-secondary overflow-x-auto whitespace-nowrap bg-brand-base"> <div className="h-full rounded-lg text-brand-secondary overflow-x-auto whitespace-nowrap bg-brand-base">
<div className="sticky z-20 top-0 border-b border-brand-base bg-brand-surface-2 w-full min-w-max"> <div className="sticky z-[2] top-0 border-b border-brand-base bg-brand-surface-1 w-full min-w-max">
<SpreadsheetColumns columnData={columnData} gridTemplateColumns={gridTemplateColumns} /> <SpreadsheetColumns columnData={columnData} gridTemplateColumns={gridTemplateColumns} />
</div> </div>
{spreadsheetIssues ? ( {spreadsheetIssues ? (

View File

@ -24,6 +24,8 @@ export const SPREADSHEET_COLUMN = [
propertyName: "priority", propertyName: "priority",
colName: "Priority", colName: "Priority",
colSize: "128px", colSize: "128px",
ascendingOrder: "priority",
descendingOrder: "-priority",
}, },
{ {
propertyName: "assignee", propertyName: "assignee",