Skip to content

Commit

Permalink
chore: implemented drag and drop between dates for project issues, cy…
Browse files Browse the repository at this point in the history
…cle, module, and project views for calendar layout (#2535)
  • Loading branch information
gurusainath authored Oct 25, 2023
1 parent cea39c7 commit a6d741e
Show file tree
Hide file tree
Showing 16 changed files with 492 additions and 63 deletions.
61 changes: 36 additions & 25 deletions web/components/issues/issue-layouts/calendar/day-tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,46 @@ export const CalendarDayTile: React.FC<Props> = observer((props) => {
const issuesList = issues ? (issues as IIssueGroupedStructure)[renderDateFormat(date.date)] : null;

return (
<Droppable droppableId={renderDateFormat(date.date)}>
{(provided, snapshot) => (
<>
<div className="w-full h-full relative flex flex-col bg-custom-background-90">
{/* header */}
<div
className={`flex-grow p-2 space-y-1 w-full flex flex-col overflow-hidden ${
snapshot.isDraggingOver || date.date.getDay() === 0 || date.date.getDay() === 6
className={`text-xs text-right flex-shrink-0 py-1 px-2 ${
calendarLayout === "month" // if month layout, highlight current month days
? date.is_current_month
? "font-medium"
: "text-custom-text-300"
: "font-medium" // if week layout, highlight all days
} ${
date.date.getDay() === 0 || date.date.getDay() === 6
? "bg-custom-background-90"
: "bg-custom-background-100"
} ${calendarLayout === "month" ? "min-h-[9rem]" : ""}`}
{...provided.droppableProps}
ref={provided.innerRef}
}`}
>
<>
<div
className={`text-xs text-right ${
calendarLayout === "month" // if month layout, highlight current month days
? date.is_current_month
? "font-medium"
: "text-custom-text-300"
: "font-medium" // if week layout, highlight all days
}`}
>
{date.date.getDate() === 1 && MONTHS_LIST[date.date.getMonth() + 1].shortTitle + " "}
{date.date.getDate()}
</div>
<CalendarIssueBlocks issues={issuesList} quickActions={quickActions} />
{provided.placeholder}
</>
{date.date.getDate() === 1 && MONTHS_LIST[date.date.getMonth() + 1].shortTitle + " "}
{date.date.getDate()}
</div>
)}
</Droppable>

{/* content */}
<div className="w-full h-full">
<Droppable droppableId={renderDateFormat(date.date)} isDropDisabled={false}>
{(provided, snapshot) => (
<div
className={`h-full w-full overflow-y-auto select-none ${
snapshot.isDraggingOver || date.date.getDay() === 0 || date.date.getDay() === 6
? "bg-custom-background-90"
: "bg-custom-background-100"
} ${calendarLayout === "month" ? "min-h-[9rem]" : ""}`}
{...provided.droppableProps}
ref={provided.innerRef}
>
<CalendarIssueBlocks issues={issuesList} quickActions={quickActions} />
{provided.placeholder}
</div>
)}
</Droppable>
</div>
</div>
</>
);
});
58 changes: 31 additions & 27 deletions web/components/issues/issue-layouts/calendar/issue-blocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,46 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
const { workspaceSlug } = router.query;

return (
<div className="space-y-2 h-full w-full overflow-y-auto p-0.5">
<>
{issues?.map((issue, index) => (
<Draggable key={issue.id} draggableId={issue.id} index={index}>
{(provided, snapshot) => (
<Link href={`/${workspaceSlug?.toString()}/projects/${issue.project}/issues/${issue.id}`}>
<a
className={`group/calendar-block h-8 w-full shadow-custom-shadow-2xs rounded py-1.5 px-1 flex items-center gap-1.5 border-[0.5px] border-custom-border-100 ${
snapshot.isDragging
? "shadow-custom-shadow-rg bg-custom-background-90"
: "bg-custom-background-100 hover:bg-custom-background-90"
}`}
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<span
className="h-full w-0.5 rounded flex-shrink-0"
style={{
backgroundColor: issue.state_detail.color,
}}
/>
<div className="text-xs text-custom-text-300 flex-shrink-0">
{issue.project_detail.identifier}-{issue.sequence_id}
</div>
<h6 className="text-xs flex-grow truncate">{issue.name}</h6>
<div className="hidden group-hover/calendar-block:block">{quickActions(issue)}</div>
{/* <IssueQuickActions
<div
className="p-1 px-2"
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<Link href={`/${workspaceSlug?.toString()}/projects/${issue.project}/issues/${issue.id}`}>
<a
className={`group/calendar-block h-8 w-full shadow-custom-shadow-2xs rounded py-1.5 px-1 flex items-center gap-1.5 border-[0.5px] border-custom-border-100 ${
snapshot.isDragging
? "shadow-custom-shadow-rg bg-custom-background-90"
: "bg-custom-background-100 hover:bg-custom-background-90"
}`}
>
<span
className="h-full w-0.5 rounded flex-shrink-0"
style={{
backgroundColor: issue.state_detail.color,
}}
/>
<div className="text-xs text-custom-text-300 flex-shrink-0">
{issue.project_detail.identifier}-{issue.sequence_id}
</div>
<h6 className="text-xs flex-grow truncate">{issue.name}</h6>
<div className="hidden group-hover/calendar-block:block">{quickActions(issue)}</div>
{/* <IssueQuickActions
issue={issue}
handleDelete={async () => handleIssues(issue.target_date ?? "", issue, "delete")}
handleUpdate={async (data) => handleIssues(issue.target_date ?? "", data, "update")}
/> */}
</a>
</Link>
</a>
</Link>
</div>
)}
</Draggable>
))}
</div>
</>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import { IIssueGroupedStructure } from "store/issue";
import { IIssue } from "types";

export const CycleCalendarLayout: React.FC = observer(() => {
const { cycleIssue: cycleIssueStore, issueFilter: issueFilterStore, issueDetail: issueDetailStore } = useMobxStore();
const {
cycleIssue: cycleIssueStore,
issueFilter: issueFilterStore,
issueDetail: issueDetailStore,
cycleIssueCalendarView: cycleIssueCalendarViewStore,
} = useMobxStore();

const router = useRouter();
const { workspaceSlug, cycleId } = router.query;

// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => {
if (!result) return;

Expand All @@ -26,7 +30,7 @@ export const CycleCalendarLayout: React.FC = observer(() => {
// return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return;

// issueKanBanViewStore?.handleDragDrop(result.source, result.destination);
cycleIssueCalendarViewStore?.handleDragDrop(result.source, result.destination);
};

const issues = cycleIssueStore.getIssues;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
moduleIssue: moduleIssueStore,
issueFilter: issueFilterStore,
issueDetail: issueDetailStore,
moduleIssueCalendarView: moduleIssueCalendarViewStore,
} = useMobxStore();

const router = useRouter();
const { workspaceSlug, moduleId } = router.query;

// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => {
if (!result) return;

Expand All @@ -30,7 +30,7 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
// return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return;

// issueKanBanViewStore?.handleDragDrop(result.source, result.destination);
moduleIssueCalendarViewStore?.handleDragDrop(result.source, result.destination);
};

const issues = moduleIssueStore.getIssues;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import { IIssueGroupedStructure } from "store/issue";
import { IIssue } from "types";

export const CalendarLayout: React.FC = observer(() => {
const { issue: issueStore, issueFilter: issueFilterStore, issueDetail: issueDetailStore } = useMobxStore();
const {
issue: issueStore,
issueFilter: issueFilterStore,
issueDetail: issueDetailStore,
issueCalendarView: issueCalendarViewStore,
} = useMobxStore();

const router = useRouter();
const { workspaceSlug } = router.query;

// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => {
if (!result) return;

Expand All @@ -26,7 +30,7 @@ export const CalendarLayout: React.FC = observer(() => {
// return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return;

// issueKanBanViewStore?.handleDragDrop(result.source, result.destination);
issueCalendarViewStore?.handleDragDrop(result.source, result.destination);
};

const issues = issueStore.getIssues;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
projectViewIssues: projectViewIssuesStore,
issueFilter: issueFilterStore,
issueDetail: issueDetailStore,
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
} = useMobxStore();

const router = useRouter();
const { workspaceSlug } = router.query;

// TODO: add drag and drop functionality
const onDragEnd = (result: DropResult) => {
if (!result) return;

Expand All @@ -30,7 +30,7 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
// return if dropped on the same date
if (result.destination.droppableId === result.source.droppableId) return;

// issueKanBanViewStore?.handleDragDrop(result.source, result.destination);
projectViewIssueCalendarViewStore?.handleDragDrop(result.source, result.destination);
};

const issues = projectViewIssuesStore.getIssues;
Expand Down
89 changes: 89 additions & 0 deletions web/store/cycle/cycle_issue_calendar_view.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { action, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { IIssueType } from "./cycle_issue.store";

export interface ICycleIssueCalendarViewStore {
// actions
handleDragDrop: (source: any, destination: any) => void;
}

export class CycleIssueCalendarViewStore implements ICycleIssueCalendarViewStore {
// root store
rootStore;

constructor(_rootStore: RootStore) {
makeObservable(this, {
// actions
handleDragDrop: action,
});

this.rootStore = _rootStore;
}

handleDragDrop = async (source: any, destination: any) => {
const workspaceSlug = this.rootStore?.workspace?.workspaceSlug;
const projectId = this.rootStore?.project?.projectId;
const cycleId = this.rootStore?.cycle?.cycleId;
const issueType: IIssueType | null = this.rootStore?.cycleIssue?.getIssueType;
const issueLayout = this.rootStore?.issueFilter?.userDisplayFilters?.layout || null;
const currentIssues: any = this.rootStore.cycleIssue.getIssues;

if (workspaceSlug && projectId && cycleId && issueType && issueLayout === "calendar" && currentIssues) {
// update issue payload
let updateIssue: any = {
workspaceSlug: workspaceSlug,
projectId: projectId,
};

const droppableSourceColumnId = source.droppableId;
const droppableDestinationColumnId = destination.droppableId;

if (droppableSourceColumnId === droppableDestinationColumnId) return;

if (droppableSourceColumnId != droppableDestinationColumnId) {
// horizontal
const _sourceIssues = currentIssues[droppableSourceColumnId];
let _destinationIssues = currentIssues[droppableDestinationColumnId] || [];

const [removed] = _sourceIssues.splice(source.index, 1);

if (_destinationIssues && _destinationIssues.length > 0)
_destinationIssues.splice(destination.index, 0, {
...removed,
target_date: droppableDestinationColumnId,
});
else _destinationIssues = [..._destinationIssues, { ...removed, target_date: droppableDestinationColumnId }];

updateIssue = { ...updateIssue, issueId: removed?.id, target_date: droppableDestinationColumnId };

currentIssues[droppableSourceColumnId] = _sourceIssues;
currentIssues[droppableDestinationColumnId] = _destinationIssues;
}

const reorderedIssues = {
...this.rootStore?.cycleIssue.issues,
[cycleId]: {
...this.rootStore?.cycleIssue.issues?.[cycleId],
[issueType]: {
...this.rootStore?.cycleIssue.issues?.[cycleId]?.[issueType],
[issueType]: currentIssues,
},
},
};

runInAction(() => {
this.rootStore.cycleIssue.issues = { ...reorderedIssues };
});

this.rootStore.issueDetail?.updateIssue(
updateIssue.workspaceSlug,
updateIssue.projectId,
updateIssue.issueId,
updateIssue
);
}

return;
};
}
1 change: 1 addition & 0 deletions web/store/cycle/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./cycle_issue_filters.store";
export * from "./cycle_issue_kanban_view.store";
export * from "./cycle_issue_calendar_view.store";
export * from "./cycle_issue.store";
export * from "./cycles.store";
1 change: 1 addition & 0 deletions web/store/issue/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from "./issue_detail.store";
export * from "./issue_draft.store";
export * from "./issue_filters.store";
export * from "./issue_kanban_view.store";
export * from "./issue_calendar_view.store";
export * from "./issue.store";
Loading

0 comments on commit a6d741e

Please sign in to comment.