Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: manual ordering of issues #305

Merged
merged 1 commit into from
Feb 20, 2023
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
20 changes: 18 additions & 2 deletions apps/app/components/core/board-view/single-board.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type Props = {
addIssueToState: () => void;
handleDeleteIssue: (issue: IIssue) => void;
openIssuesListModal?: (() => void) | null;
orderBy: NestedKeyOf<IIssue> | "manual" | null;
orderBy: NestedKeyOf<IIssue> | null;
handleTrashBox: (isDragging: boolean) => void;
removeIssue: ((bridgeId: string) => void) | null;
userAuth: UserAuth;
Expand Down Expand Up @@ -92,6 +92,22 @@ export const SingleBoard: React.FC<Props> = ({
ref={provided.innerRef}
{...provided.droppableProps}
>
{orderBy !== "sort_order" && (
<>
<div
className={`absolute ${
snapshot.isDraggingOver ? "block" : "hidden"
} top-0 left-0 h-full w-full bg-indigo-200 opacity-50 pointer-events-none z-[99999998]`}
/>
<div
className={`absolute ${
snapshot.isDraggingOver ? "block" : "hidden"
} top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 text-xs whitespace-nowrap bg-white p-2 rounded pointer-events-none z-[99999999]`}
>
This board is order by {orderBy}
</div>
</>
)}
{groupedByIssues[groupTitle].map((issue, index: number) => (
<Draggable
key={issue.id}
Expand Down Expand Up @@ -124,7 +140,7 @@ export const SingleBoard: React.FC<Props> = ({
))}
<span
style={{
display: orderBy === "manual" ? "inline" : "none",
display: orderBy === "sort_order" ? "inline" : "none",
}}
>
{provided.placeholder}
Expand Down
14 changes: 4 additions & 10 deletions apps/app/components/core/board-view/single-issue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type Props = {
editIssue: () => void;
removeIssue?: (() => void) | null;
handleDeleteIssue: (issue: IIssue) => void;
orderBy: NestedKeyOf<IIssue> | "manual" | null;
orderBy: NestedKeyOf<IIssue> | null;
handleTrashBox: (isDragging: boolean) => void;
userAuth: UserAuth;
};
Expand Down Expand Up @@ -150,7 +150,7 @@ export const SingleBoardIssue: React.FC<Props> = ({
style: DraggingStyle | NotDraggingStyle | undefined,
snapshot: DraggableStateSnapshot
) {
if (orderBy === "manual") return style;
if (orderBy === "sort_order") return style;
if (!snapshot.isDragging) return {};
if (!snapshot.isDropAnimating) {
return style;
Expand Down Expand Up @@ -179,12 +179,13 @@ export const SingleBoardIssue: React.FC<Props> = ({
});
});
};
const isNotAllowed = userAuth.isGuest || userAuth.isViewer;

useEffect(() => {
if (snapshot.isDragging) handleTrashBox(snapshot.isDragging);
}, [snapshot, handleTrashBox]);

const isNotAllowed = userAuth.isGuest || userAuth.isViewer;

return (
<div
className={`rounded border bg-white shadow-sm ${
Expand All @@ -198,13 +199,6 @@ export const SingleBoardIssue: React.FC<Props> = ({
<div className="group/card relative select-none p-2">
{!isNotAllowed && (
<div className="absolute top-1.5 right-1.5 z-10 opacity-0 group-hover/card:opacity-100">
{/* <button
type="button"
className="grid h-7 w-7 place-items-center rounded bg-white p-1 text-red-500 outline-none duration-300 hover:bg-red-50"
onClick={() => handleDeleteIssue(issue)}
>
<TrashIcon className="h-4 w-4" />
</button> */}
{type && !isNotAllowed && (
<CustomMenu width="auto" ellipsis>
<CustomMenu.MenuItem onClick={handleCopyText}>Copy issue link</CustomMenu.MenuItem>
Expand Down
5 changes: 4 additions & 1 deletion apps/app/components/core/issues-view-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@ export const IssuesFilterView: React.FC<Props> = ({ issues }) => {
option.key === "priority" ? null : (
<CustomMenu.MenuItem
key={option.key}
onClick={() => setOrderBy(option.key)}
onClick={() => {
console.log(option.key);
setOrderBy(option.key);
}}
>
{option.name}
</CustomMenu.MenuItem>
Expand Down
31 changes: 30 additions & 1 deletion apps/app/components/core/issues-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ export const IssuesView: React.FC<Props> = ({
const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;

const { issueView, groupedByIssues, groupByProperty: selectedGroup } = useIssueView(issues);
const {
issueView,
groupedByIssues,
groupByProperty: selectedGroup,
orderBy,
} = useIssueView(issues);

const { data: stateGroups } = useSWR(
workspaceSlug && projectId ? STATE_LIST(projectId as string) : null,
Expand Down Expand Up @@ -101,10 +106,25 @@ export const IssuesView: React.FC<Props> = ({
const { source, destination } = result;

const draggedItem = groupedByIssues[source.droppableId][source.index];
let newSortOrder = draggedItem.sort_order;

if (destination.droppableId === "trashBox") {
handleDeleteIssue(draggedItem);
} else {
if (orderBy === "sort_order") {
const destinationGroupArray = groupedByIssues[destination.droppableId];

if (destination.index === 0) newSortOrder = destinationGroupArray[0].sort_order - 10000;
else if (destination.index === destinationGroupArray.length)
newSortOrder =
destinationGroupArray[destinationGroupArray.length - 1].sort_order + 10000;
else
newSortOrder =
(destinationGroupArray[destination.index - 1].sort_order +
destinationGroupArray[destination.index].sort_order) /
2;
}

if (source.droppableId !== destination.droppableId) {
const sourceGroup = source.droppableId; // source group id
const destinationGroup = destination.droppableId; // destination group id
Expand All @@ -127,6 +147,7 @@ export const IssuesView: React.FC<Props> = ({
issue_detail: {
...draggedItem,
priority: destinationGroup,
sort_order: newSortOrder,
},
};
}
Expand All @@ -149,6 +170,7 @@ export const IssuesView: React.FC<Props> = ({
issue_detail: {
...draggedItem,
priority: destinationGroup,
sort_order: newSortOrder,
},
};
}
Expand All @@ -169,6 +191,7 @@ export const IssuesView: React.FC<Props> = ({
return {
...draggedItem,
priority: destinationGroup,
sort_order: newSortOrder,
};

return issue;
Expand All @@ -183,6 +206,7 @@ export const IssuesView: React.FC<Props> = ({
issuesService
.patchIssue(workspaceSlug as string, projectId as string, draggedItem.id, {
priority: destinationGroup,
sort_order: newSortOrder,
})
.then((res) => {
if (cycleId) mutate(CYCLE_ISSUES(cycleId as string));
Expand Down Expand Up @@ -212,6 +236,7 @@ export const IssuesView: React.FC<Props> = ({
...draggedItem,
state_detail: destinationState,
state: destinationStateId,
sort_order: newSortOrder,
},
};
}
Expand All @@ -235,6 +260,7 @@ export const IssuesView: React.FC<Props> = ({
...draggedItem,
state_detail: destinationState,
state: destinationStateId,
sort_order: newSortOrder,
},
};
}
Expand All @@ -256,6 +282,7 @@ export const IssuesView: React.FC<Props> = ({
...draggedItem,
state_detail: destinationState,
state: destinationStateId,
sort_order: newSortOrder,
};

return issue;
Expand All @@ -270,6 +297,7 @@ export const IssuesView: React.FC<Props> = ({
issuesService
.patchIssue(workspaceSlug as string, projectId as string, draggedItem.id, {
state: destinationStateId,
sort_order: newSortOrder,
})
.then((res) => {
if (cycleId) mutate(CYCLE_ISSUES(cycleId as string));
Expand All @@ -288,6 +316,7 @@ export const IssuesView: React.FC<Props> = ({
groupedByIssues,
projectId,
selectedGroup,
orderBy,
states,
handleDeleteIssue,
]
Expand Down
20 changes: 16 additions & 4 deletions apps/app/components/cycles/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,18 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
.then((res) => {
mutate(CYCLE_LIST(projectId as string));
handleClose();

setToastAlert({
type: "success",
title: "Success!",
message: "Cycle created successfully.",
});
})
.catch((err) => {
setToastAlert({
type: "error",
title: "Error",
message: "Error in creating cycle. Please try again!",
title: "Error!",
message: "Error in creating cycle. Please try again.",
});
});
};
Expand All @@ -55,12 +61,18 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
.then((res) => {
mutate(CYCLE_LIST(projectId as string));
handleClose();

setToastAlert({
type: "success",
title: "Success!",
message: "Cycle updated successfully.",
});
})
.catch((err) => {
setToastAlert({
type: "error",
title: "Error",
message: "Error in updating cycle. Please try again!",
title: "Error!",
message: "Error in updating cycle. Please try again.",
});
});
};
Expand Down
14 changes: 6 additions & 8 deletions apps/app/constants/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ export const GROUP_BY_OPTIONS: Array<{ name: string; key: NestedKeyOf<IIssue> |
{ name: "None", key: null },
];

export const ORDER_BY_OPTIONS: Array<{ name: string; key: NestedKeyOf<IIssue> | "manual" | null }> =
[
// { name: "Manual", key: "manual" },
{ name: "Last created", key: "created_at" },
{ name: "Last updated", key: "updated_at" },
{ name: "Priority", key: "priority" },
// { name: "None", key: null },
];
export const ORDER_BY_OPTIONS: Array<{ name: string; key: NestedKeyOf<IIssue> | null }> = [
{ name: "Manual", key: "sort_order" },
{ name: "Last created", key: "created_at" },
{ name: "Last updated", key: "updated_at" },
{ name: "Priority", key: "priority" },
];

export const FILTER_ISSUE_OPTIONS: Array<{
name: string;
Expand Down
10 changes: 5 additions & 5 deletions apps/app/contexts/issue-view.context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type IssueViewProps = {
issueView: "list" | "kanban" | null;
groupByProperty: NestedKeyOf<IIssue> | null;
filterIssue: "activeIssue" | "backlogIssue" | null;
orderBy: NestedKeyOf<IIssue> | "manual" | null;
orderBy: NestedKeyOf<IIssue> | null;
};

type ReducerActionType = {
Expand All @@ -34,12 +34,12 @@ type ReducerActionType = {
};

type ContextType = {
orderBy: NestedKeyOf<IIssue> | "manual" | null;
orderBy: NestedKeyOf<IIssue> | null;
issueView: "list" | "kanban" | null;
groupByProperty: NestedKeyOf<IIssue> | null;
filterIssue: "activeIssue" | "backlogIssue" | null;
setGroupByProperty: (property: NestedKeyOf<IIssue> | null) => void;
setOrderBy: (property: NestedKeyOf<IIssue> | "manual" | null) => void;
setOrderBy: (property: NestedKeyOf<IIssue> | null) => void;
setFilterIssue: (property: "activeIssue" | "backlogIssue" | null) => void;
resetFilterToDefault: () => void;
setNewFilterDefaultView: () => void;
Expand All @@ -51,7 +51,7 @@ type StateType = {
issueView: "list" | "kanban" | null;
groupByProperty: NestedKeyOf<IIssue> | null;
filterIssue: "activeIssue" | "backlogIssue" | null;
orderBy: NestedKeyOf<IIssue> | "manual" | null;
orderBy: NestedKeyOf<IIssue> | null;
};
type ReducerFunctionType = (state: StateType, action: ReducerActionType) => StateType;

Expand Down Expand Up @@ -220,7 +220,7 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
);

const setOrderBy = useCallback(
(property: NestedKeyOf<IIssue> | "manual" | null) => {
(property: NestedKeyOf<IIssue> | null) => {
dispatch({
type: "SET_ORDER_BY_PROPERTY",
payload: {
Expand Down
2 changes: 1 addition & 1 deletion apps/app/hooks/use-issue-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const useIssueView = (projectIssues: IIssue[]) => {
groupedByIssues = Object.fromEntries(
Object.entries(groupedByIssues).map(([key, value]) => [
key,
orderArrayBy(value, orderBy, "descending"),
orderArrayBy(value, orderBy, orderBy === "sort_order" ? "ascending" : "descending"),
])
);
}
Expand Down
1 change: 1 addition & 0 deletions apps/app/types/issues.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export interface IIssue {
project: string;
project_detail: IProject;
sequence_id: number;
sort_order: number;
sprints: string | null;
start_date: string | null;
state: string;
Expand Down