Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion web/components/core/views/all-views.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import useSWR from "swr";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { CalendarLayout, GanttLayout, KanBanLayout } from "components/issues";
import { CalendarLayout, GanttLayout, KanBanLayout, SpreadsheetLayout } from "components/issues";

export const AllViews: React.FC = observer(() => {
const router = useRouter();
Expand Down Expand Up @@ -41,6 +41,8 @@ export const AllViews: React.FC = observer(() => {
<CalendarLayout />
) : activeLayout === "gantt_chart" ? (
<GanttLayout />
) : activeLayout === "spreadsheet" ? (
<SpreadsheetLayout />
) : null}
</div>
);
Expand Down
88 changes: 14 additions & 74 deletions web/components/core/views/spreadsheet-view/single-issue.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,27 @@
import React, { useCallback, useState } from "react";

import { useRouter } from "next/router";

import { mutate } from "swr";

// components
import { ViewDueDateSelect, ViewEstimateSelect, ViewStartDateSelect } from "components/issues";
import { LabelSelect, MembersSelect, PrioritySelect } from "components/project";
import { StateSelect } from "components/states";
import { Popover2 } from "@blueprintjs/popover2";

// icons
import { Icon } from "components/ui";
import { EllipsisHorizontalIcon, LinkIcon, PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
// hooks
import useSpreadsheetIssuesView from "hooks/use-spreadsheet-issues-view";
import useToast from "hooks/use-toast";
// services
import issuesService from "services/issue.service";
import trackEventServices from "services/track_event.service";
// constant
import {
CYCLE_DETAILS,
CYCLE_ISSUES_WITH_PARAMS,
MODULE_DETAILS,
MODULE_ISSUES_WITH_PARAMS,
PROJECT_ISSUES_LIST_WITH_PARAMS,
SUB_ISSUES,
VIEW_ISSUES,
} from "constants/fetch-keys";
// types
import { ICurrentUserResponse, IIssue, IState, ISubIssueResponse, Properties, TIssuePriorities, UserAuth } from "types";
// helper
// hooks
import useToast from "hooks/use-toast";
// components
import { ViewDueDateSelect, ViewEstimateSelect, ViewStartDateSelect } from "components/issues";
import { LabelSelect, MembersSelect, PrioritySelect } from "components/project";
import { StateSelect } from "components/states";
// helpers
import { copyTextToClipboard } from "helpers/string.helper";
import { renderLongDetailDateFormat } from "helpers/date-time.helper";
// types
import { ICurrentUserResponse, IIssue, IState, Properties, TIssuePriorities, UserAuth } from "types";
// constant
import { CYCLE_DETAILS, MODULE_DETAILS, SUB_ISSUES } from "constants/fetch-keys";

type Props = {
issue: IIssue;
Expand Down Expand Up @@ -67,69 +56,20 @@ export const SingleSpreadsheetIssue: React.FC<Props> = ({

const router = useRouter();

const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;

const { params } = useSpreadsheetIssuesView();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;

const { setToastAlert } = useToast();

const partialUpdateIssue = useCallback(
(formData: Partial<IIssue>, issue: IIssue) => {
if (!workspaceSlug || !projectId) return;

const fetchKey = cycleId
? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params)
: moduleId
? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params)
: viewId
? VIEW_ISSUES(viewId.toString(), params)
: PROJECT_ISSUES_LIST_WITH_PARAMS(projectId.toString(), params);

if (issue.parent)
mutate<ISubIssueResponse>(
SUB_ISSUES(issue.parent.toString()),
(prevData) => {
if (!prevData) return prevData;

return {
...prevData,
sub_issues: (prevData.sub_issues ?? []).map((i) => {
if (i.id === issue.id) {
return {
...i,
...formData,
};
}
return i;
}),
};
},
false
);
else
mutate<IIssue[]>(
fetchKey,
(prevData) =>
(prevData ?? []).map((p) => {
if (p.id === issue.id) {
return {
...p,
...formData,
};
}
return p;
}),
false
);

issuesService
.patchIssue(workspaceSlug as string, projectId as string, issue.id as string, formData, user)
.then(() => {
if (issue.parent) {
mutate(SUB_ISSUES(issue.parent as string));
} else {
mutate(fetchKey);

if (cycleId) mutate(CYCLE_DETAILS(cycleId as string));
if (moduleId) mutate(MODULE_DETAILS(moduleId as string));
}
Expand All @@ -138,7 +78,7 @@ export const SingleSpreadsheetIssue: React.FC<Props> = ({
console.log(error);
});
},
[workspaceSlug, projectId, cycleId, moduleId, viewId, params, user]
[workspaceSlug, projectId, cycleId, moduleId, user]
);

const openPeekOverview = () => {
Expand Down
74 changes: 23 additions & 51 deletions web/components/core/views/spreadsheet-view/spreadsheet-columns.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,46 @@
import React from "react";
// hooks
import useSpreadsheetIssuesView from "hooks/use-spreadsheet-issues-view";
import useLocalStorage from "hooks/use-local-storage";
// component
import { CustomMenu, Icon } from "components/ui";
// icon
import { CheckIcon, ChevronDownIcon } from "@heroicons/react/24/outline";
// types
import { TIssueOrderByOptions } from "types";
import { IIssueDisplayFilterOptions, TIssueOrderByOptions } from "types";

type Props = {
columnData: any;
displayFilters: IIssueDisplayFilterOptions;
gridTemplateColumns: string;
handleDisplayFiltersUpdate: (updatedDisplayFilter: Partial<IIssueDisplayFilterOptions>) => void;
};

export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateColumns }) => {
export const SpreadsheetColumns: React.FC<Props> = (props) => {
const { columnData, displayFilters, gridTemplateColumns, handleDisplayFiltersUpdate } = props;

const { storedValue: selectedMenuItem, setValue: setSelectedMenuItem } = useLocalStorage(
"spreadsheetViewSorting",
""
);
const { storedValue: activeSortingProperty, setValue: setActiveSortingProperty } =
useLocalStorage("spreadsheetViewActiveSortingProperty", "");

const { displayFilters, setDisplayFilters } = useSpreadsheetIssuesView();
const { storedValue: activeSortingProperty, setValue: setActiveSortingProperty } = useLocalStorage(
"spreadsheetViewActiveSortingProperty",
""
);

const handleOrderBy = (order: TIssueOrderByOptions, itemKey: string) => {
setDisplayFilters({ order_by: order });
handleDisplayFiltersUpdate({ order_by: order });
setSelectedMenuItem(`${order}_${itemKey}`);
setActiveSortingProperty(order === "-created_at" ? "" : itemKey);
};

return (
<div
className={`grid auto-rows-[minmax(36px,1fr)] w-full min-w-max`}
style={{ gridTemplateColumns }}
>
<div className={`grid auto-rows-[minmax(36px,1fr)] w-full min-w-max`} style={{ gridTemplateColumns }}>
{columnData.map((col: any) => {
if (col.isActive) {
return (
<div
className={`bg-custom-background-90 w-full ${
col.propertyName === "title"
? "sticky left-0 z-20 bg-custom-background-90 pl-24"
: ""
col.propertyName === "title" ? "sticky left-0 z-20 bg-custom-background-90 pl-24" : ""
}`}
>
{col.propertyName === "title" ? (
Expand Down Expand Up @@ -108,10 +106,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
{col.propertyName === "assignee" || col.propertyName === "labels" ? (
<>
<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="east" className="absolute left-0 rotate-90 text-xs leading-3" />
<Icon iconName="sort" className="absolute right-0 text-sm" />
</span>
<span>A</span>
Expand All @@ -123,10 +118,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
col.propertyName === "updated_on" ? (
<>
<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="east" className="absolute left-0 rotate-90 text-xs leading-3" />
<Icon iconName="sort" className="absolute right-0 text-sm" />
</span>
<span>New</span>
Expand All @@ -136,10 +128,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
) : (
<>
<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="east" className="absolute left-0 rotate-90 text-xs leading-3" />
<Icon iconName="sort" className="absolute right-0 text-sm" />
</span>
<span>First</span>
Expand All @@ -151,18 +140,14 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo

<CheckIcon
className={`h-3.5 w-3.5 opacity-0 group-hover:opacity-100 ${
selectedMenuItem === `${col.ascendingOrder}_${col.propertyName}`
? "opacity-100"
: ""
selectedMenuItem === `${col.ascendingOrder}_${col.propertyName}` ? "opacity-100" : ""
}`}
/>
</div>
</CustomMenu.MenuItem>
<CustomMenu.MenuItem
className={`mt-0.5 ${
selectedMenuItem === `${col.descendingOrder}_${col.propertyName}`
? "bg-custom-background-80"
: ""
selectedMenuItem === `${col.descendingOrder}_${col.propertyName}` ? "bg-custom-background-80" : ""
}`}
key={col.property}
onClick={() => {
Expand All @@ -180,10 +165,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
{col.propertyName === "assignee" || col.propertyName === "labels" ? (
<>
<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="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"
Expand All @@ -196,10 +178,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
) : col.propertyName === "due_date" ? (
<>
<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="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"
Expand All @@ -212,10 +191,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
) : (
<>
<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="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"
Expand All @@ -230,9 +206,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo

<CheckIcon
className={`h-3.5 w-3.5 opacity-0 group-hover:opacity-100 ${
selectedMenuItem === `${col.descendingOrder}_${col.propertyName}`
? "opacity-100"
: ""
selectedMenuItem === `${col.descendingOrder}_${col.propertyName}` ? "opacity-100" : ""
}`}
/>
</div>
Expand All @@ -243,9 +217,7 @@ export const SpreadsheetColumns: React.FC<Props> = ({ columnData, gridTemplateCo
selectedMenuItem.includes(col.propertyName) && (
<CustomMenu.MenuItem
className={`mt-0.5${
selectedMenuItem === `-created_at_${col.propertyName}`
? "bg-custom-background-80"
: ""
selectedMenuItem === `-created_at_${col.propertyName}` ? "bg-custom-background-80" : ""
}`}
key={col.property}
onClick={() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React from "react";

// components
import { SingleSpreadsheetIssue } from "components/core";
Expand Down
Loading