mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix calendar pagination
This commit is contained in:
parent
57133122ec
commit
9b4176aa17
@ -106,7 +106,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const issueIdList = groupedIssueIds ? groupedIssueIds[formattedDatePayload] : null;
|
const issueIdList = groupedIssueIds ? groupedIssueIds[formattedDatePayload] : [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -182,6 +182,9 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
|||||||
date={selectedDate}
|
date={selectedDate}
|
||||||
issues={issues}
|
issues={issues}
|
||||||
issueIdList={issueIdList}
|
issueIdList={issueIdList}
|
||||||
|
loadMoreIssues={loadMoreIssues}
|
||||||
|
getPaginationData={getPaginationData}
|
||||||
|
getGroupIssueCount={getGroupIssueCount}
|
||||||
quickActions={quickActions}
|
quickActions={quickActions}
|
||||||
enableQuickIssueCreate
|
enableQuickIssueCreate
|
||||||
disableIssueCreation={!enableIssueCreation || !isEditingAllowed}
|
disableIssueCreation={!enableIssueCreation || !isEditingAllowed}
|
||||||
|
@ -4,7 +4,7 @@ import { observer } from "mobx-react-lite";
|
|||||||
// types
|
// types
|
||||||
import { TGroupedIssues, TIssue, TIssueMap, TPaginationData } from "@plane/types";
|
import { TGroupedIssues, TIssue, TIssueMap, TPaginationData } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
import { CalendarIssueBlocks, ICalendarDate, CalendarQuickAddIssueForm } from "@/components/issues";
|
import { CalendarIssueBlocks, ICalendarDate } from "@/components/issues";
|
||||||
// helpers
|
// helpers
|
||||||
import { MONTHS_LIST } from "@/constants/calendar";
|
import { MONTHS_LIST } from "@/constants/calendar";
|
||||||
import { cn } from "@/helpers/common.helper";
|
import { cn } from "@/helpers/common.helper";
|
||||||
@ -63,11 +63,6 @@ export const CalendarDayTile: React.FC<Props> = observer((props) => {
|
|||||||
const formattedDatePayload = renderFormattedPayloadDate(date.date);
|
const formattedDatePayload = renderFormattedPayloadDate(date.date);
|
||||||
if (!formattedDatePayload) return null;
|
if (!formattedDatePayload) return null;
|
||||||
const issueIds = groupedIssueIds?.[formattedDatePayload];
|
const issueIds = groupedIssueIds?.[formattedDatePayload];
|
||||||
const dayIssueCount = getGroupIssueCount(formattedDatePayload);
|
|
||||||
const nextPageResults = getPaginationData(formattedDatePayload)?.nextPageResults;
|
|
||||||
|
|
||||||
const shouldLoadMore =
|
|
||||||
nextPageResults === undefined && dayIssueCount !== undefined ? issueIds?.length < dayIssueCount : !!nextPageResults;
|
|
||||||
|
|
||||||
const isToday = date.date.toDateString() === new Date().toDateString();
|
const isToday = date.date.toDateString() === new Date().toDateString();
|
||||||
const isSelectedDate = date.date.toDateString() == selectedDate.toDateString();
|
const isSelectedDate = date.date.toDateString() == selectedDate.toDateString();
|
||||||
@ -117,6 +112,9 @@ export const CalendarDayTile: React.FC<Props> = observer((props) => {
|
|||||||
issues={issues}
|
issues={issues}
|
||||||
issueIdList={issueIds ?? []}
|
issueIdList={issueIds ?? []}
|
||||||
quickActions={quickActions}
|
quickActions={quickActions}
|
||||||
|
loadMoreIssues={loadMoreIssues}
|
||||||
|
getPaginationData={getPaginationData}
|
||||||
|
getGroupIssueCount={getGroupIssueCount}
|
||||||
isDragDisabled={readOnly}
|
isDragDisabled={readOnly}
|
||||||
addIssuesToView={addIssuesToView}
|
addIssuesToView={addIssuesToView}
|
||||||
disableIssueCreation={disableIssueCreation}
|
disableIssueCreation={disableIssueCreation}
|
||||||
@ -126,33 +124,6 @@ export const CalendarDayTile: React.FC<Props> = observer((props) => {
|
|||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{enableQuickIssueCreate && !disableIssueCreation && !readOnly && (
|
|
||||||
<div className="px-2 py-1">
|
|
||||||
<CalendarQuickAddIssueForm
|
|
||||||
formKey="target_date"
|
|
||||||
groupId={formattedDatePayload}
|
|
||||||
prePopulatedData={{
|
|
||||||
target_date: renderFormattedPayloadDate(date.date) ?? undefined,
|
|
||||||
}}
|
|
||||||
quickAddCallback={quickAddCallback}
|
|
||||||
addIssuesToView={addIssuesToView}
|
|
||||||
viewId={viewId}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{shouldLoadMore && (
|
|
||||||
<div className="flex items-center px-2.5 py-1">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="w-min whitespace-nowrap rounded text-xs px-1.5 py-1 text-custom-text-400 font-medium hover:bg-custom-background-80 hover:text-custom-text-300"
|
|
||||||
onClick={() => loadMoreIssues(formattedDatePayload)}
|
|
||||||
>
|
|
||||||
Load More
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { useState } from "react";
|
|
||||||
import { Draggable } from "@hello-pangea/dnd";
|
import { Draggable } from "@hello-pangea/dnd";
|
||||||
import { Placement } from "@popperjs/core";
|
import { Placement } from "@popperjs/core";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { TIssue, TIssueMap } from "@plane/types";
|
import { TIssue, TIssueMap, TPaginationData } from "@plane/types";
|
||||||
// components
|
// components
|
||||||
import { CalendarQuickAddIssueForm, CalendarIssueBlockRoot } from "@/components/issues";
|
import { CalendarQuickAddIssueForm, CalendarIssueBlockRoot } from "@/components/issues";
|
||||||
// helpers
|
// helpers
|
||||||
@ -12,8 +11,11 @@ import { renderFormattedPayloadDate } from "@/helpers/date-time.helper";
|
|||||||
type Props = {
|
type Props = {
|
||||||
date: Date;
|
date: Date;
|
||||||
issues: TIssueMap | undefined;
|
issues: TIssueMap | undefined;
|
||||||
issueIdList: string[] | null;
|
issueIdList: string[];
|
||||||
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
|
||||||
|
loadMoreIssues: (dateString: string) => void;
|
||||||
|
getPaginationData: (groupId: string | undefined) => TPaginationData | undefined;
|
||||||
|
getGroupIssueCount: (groupId: string | undefined) => number | undefined;
|
||||||
isDragDisabled?: boolean;
|
isDragDisabled?: boolean;
|
||||||
enableQuickIssueCreate?: boolean;
|
enableQuickIssueCreate?: boolean;
|
||||||
disableIssueCreation?: boolean;
|
disableIssueCreation?: boolean;
|
||||||
@ -35,6 +37,9 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
|||||||
issues,
|
issues,
|
||||||
issueIdList,
|
issueIdList,
|
||||||
quickActions,
|
quickActions,
|
||||||
|
loadMoreIssues,
|
||||||
|
getPaginationData,
|
||||||
|
getGroupIssueCount,
|
||||||
isDragDisabled = false,
|
isDragDisabled = false,
|
||||||
enableQuickIssueCreate,
|
enableQuickIssueCreate,
|
||||||
disableIssueCreation,
|
disableIssueCreation,
|
||||||
@ -45,13 +50,18 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
|||||||
isMobileView = false,
|
isMobileView = false,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [showAllIssues, setShowAllIssues] = useState(false);
|
|
||||||
|
|
||||||
const formattedDatePayload = renderFormattedPayloadDate(date);
|
const formattedDatePayload = renderFormattedPayloadDate(date);
|
||||||
const totalIssues = issueIdList?.length ?? 0;
|
|
||||||
|
|
||||||
if (!formattedDatePayload) return null;
|
if (!formattedDatePayload) return null;
|
||||||
|
|
||||||
|
const dayIssueCount = getGroupIssueCount(formattedDatePayload);
|
||||||
|
const nextPageResults = getPaginationData(formattedDatePayload)?.nextPageResults;
|
||||||
|
|
||||||
|
const shouldLoadMore =
|
||||||
|
nextPageResults === undefined && dayIssueCount !== undefined
|
||||||
|
? issueIdList?.length < dayIssueCount
|
||||||
|
: !!nextPageResults;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{issueIdList?.map((issueId, index) =>
|
{issueIdList?.map((issueId, index) =>
|
||||||
@ -79,7 +89,7 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{enableQuickIssueCreate && !disableIssueCreation && !readOnly && (
|
{enableQuickIssueCreate && !disableIssueCreation && !readOnly && (
|
||||||
<div className="px-1 md:px-2 py-1 border-custom-border-200 border-b md:border-none">
|
<div className="px-1 md:px-2 py-1 border-custom-border-200 border-b md:border-none md:hidden group-hover:block">
|
||||||
<CalendarQuickAddIssueForm
|
<CalendarQuickAddIssueForm
|
||||||
formKey="target_date"
|
formKey="target_date"
|
||||||
groupId={formattedDatePayload}
|
groupId={formattedDatePayload}
|
||||||
@ -89,18 +99,18 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
|||||||
quickAddCallback={quickAddCallback}
|
quickAddCallback={quickAddCallback}
|
||||||
addIssuesToView={addIssuesToView}
|
addIssuesToView={addIssuesToView}
|
||||||
viewId={viewId}
|
viewId={viewId}
|
||||||
onOpen={() => setShowAllIssues(true)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{totalIssues > 4 && (
|
|
||||||
<div className="hidden md:flex items-center px-2.5 py-1">
|
{shouldLoadMore && (
|
||||||
|
<div className="flex items-center px-2.5 py-1">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="w-min whitespace-nowrap rounded text-xs px-1.5 py-1 text-custom-text-400 font-medium hover:bg-custom-background-80 hover:text-custom-text-300"
|
className="w-min whitespace-nowrap rounded text-xs px-1.5 py-1 text-custom-text-400 font-medium hover:bg-custom-background-80 hover:text-custom-text-300"
|
||||||
onClick={() => setShowAllIssues(!showAllIssues)}
|
onClick={() => loadMoreIssues(formattedDatePayload)}
|
||||||
>
|
>
|
||||||
{showAllIssues ? "Hide" : totalIssues - 4 + " more"}
|
Load More
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -800,11 +800,11 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
return this.getIssueIds(orderBy(array, "sort_order"));
|
return this.getIssueIds(orderBy(array, "sort_order"));
|
||||||
case "state__name":
|
case "state__name":
|
||||||
return this.getIssueIds(
|
return this.getIssueIds(
|
||||||
orderBy(array, (issue) => this.populateIssueDataForSorting("state_id", issue["state_id"]))
|
orderBy(array, (issue) => this.populateIssueDataForSorting("state_id", issue?.["state_id"]))
|
||||||
);
|
);
|
||||||
case "-state__name":
|
case "-state__name":
|
||||||
return this.getIssueIds(
|
return this.getIssueIds(
|
||||||
orderBy(array, (issue) => this.populateIssueDataForSorting("state_id", issue["state_id"]), ["desc"])
|
orderBy(array, (issue) => this.populateIssueDataForSorting("state_id", issue?.["state_id"]), ["desc"])
|
||||||
);
|
);
|
||||||
// dates
|
// dates
|
||||||
case "created_at":
|
case "created_at":
|
||||||
@ -844,12 +844,12 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
// custom
|
// custom
|
||||||
case "priority": {
|
case "priority": {
|
||||||
const sortArray = ISSUE_PRIORITIES.map((i) => i.key);
|
const sortArray = ISSUE_PRIORITIES.map((i) => i.key);
|
||||||
return this.getIssueIds(orderBy(array, (currentIssue: TIssue) => indexOf(sortArray, currentIssue.priority)));
|
return this.getIssueIds(orderBy(array, (currentIssue: TIssue) => indexOf(sortArray, currentIssue?.priority)));
|
||||||
}
|
}
|
||||||
case "-priority": {
|
case "-priority": {
|
||||||
const sortArray = ISSUE_PRIORITIES.map((i) => i.key);
|
const sortArray = ISSUE_PRIORITIES.map((i) => i.key);
|
||||||
return this.getIssueIds(
|
return this.getIssueIds(
|
||||||
orderBy(array, (currentIssue: TIssue) => indexOf(sortArray, currentIssue.priority), ["desc"])
|
orderBy(array, (currentIssue: TIssue) => indexOf(sortArray, currentIssue?.priority), ["desc"])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -887,7 +887,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
return this.getIssueIds(
|
return this.getIssueIds(
|
||||||
orderBy(array, [
|
orderBy(array, [
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "label_ids"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "label_ids"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("label_ids", issue["label_ids"], "asc"),
|
(issue) => this.populateIssueDataForSorting("label_ids", issue?.["label_ids"], "asc"),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
case "-labels__name":
|
case "-labels__name":
|
||||||
@ -896,7 +896,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
array,
|
array,
|
||||||
[
|
[
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "label_ids"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "label_ids"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("label_ids", issue["label_ids"], "desc"),
|
(issue) => this.populateIssueDataForSorting("label_ids", issue?.["label_ids"], "desc"),
|
||||||
],
|
],
|
||||||
["asc", "desc"]
|
["asc", "desc"]
|
||||||
)
|
)
|
||||||
@ -906,7 +906,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
return this.getIssueIds(
|
return this.getIssueIds(
|
||||||
orderBy(array, [
|
orderBy(array, [
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "module_ids"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "module_ids"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("module_ids", issue["module_ids"], "asc"),
|
(issue) => this.populateIssueDataForSorting("module_ids", issue?.["module_ids"], "asc"),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
case "-issue_module__module__name":
|
case "-issue_module__module__name":
|
||||||
@ -915,7 +915,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
array,
|
array,
|
||||||
[
|
[
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "module_ids"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "module_ids"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("module_ids", issue["module_ids"], "desc"),
|
(issue) => this.populateIssueDataForSorting("module_ids", issue?.["module_ids"], "desc"),
|
||||||
],
|
],
|
||||||
["asc", "desc"]
|
["asc", "desc"]
|
||||||
)
|
)
|
||||||
@ -925,7 +925,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
return this.getIssueIds(
|
return this.getIssueIds(
|
||||||
orderBy(array, [
|
orderBy(array, [
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "cycle_id"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "cycle_id"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("cycle_id", issue["cycle_id"], "asc"),
|
(issue) => this.populateIssueDataForSorting("cycle_id", issue?.["cycle_id"], "asc"),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
case "-issue_cycle__cycle__name":
|
case "-issue_cycle__cycle__name":
|
||||||
@ -934,7 +934,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
array,
|
array,
|
||||||
[
|
[
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "cycle_id"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "cycle_id"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("cycle_id", issue["cycle_id"], "desc"),
|
(issue) => this.populateIssueDataForSorting("cycle_id", issue?.["cycle_id"], "desc"),
|
||||||
],
|
],
|
||||||
["asc", "desc"]
|
["asc", "desc"]
|
||||||
)
|
)
|
||||||
@ -944,7 +944,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
return this.getIssueIds(
|
return this.getIssueIds(
|
||||||
orderBy(array, [
|
orderBy(array, [
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "assignee_ids"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "assignee_ids"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("assignee_ids", issue["assignee_ids"], "asc"),
|
(issue) => this.populateIssueDataForSorting("assignee_ids", issue?.["assignee_ids"], "asc"),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
case "-assignees__first_name":
|
case "-assignees__first_name":
|
||||||
@ -953,7 +953,7 @@ export class BaseIssuesStore implements IBaseIssuesStore {
|
|||||||
array,
|
array,
|
||||||
[
|
[
|
||||||
this.getSortOrderToFilterEmptyValues.bind(null, "assignee_ids"), //preferring sorting based on empty values to always keep the empty values below
|
this.getSortOrderToFilterEmptyValues.bind(null, "assignee_ids"), //preferring sorting based on empty values to always keep the empty values below
|
||||||
(issue) => this.populateIssueDataForSorting("assignee_ids", issue["assignee_ids"], "desc"),
|
(issue) => this.populateIssueDataForSorting("assignee_ids", issue?.["assignee_ids"], "desc"),
|
||||||
],
|
],
|
||||||
["asc", "desc"]
|
["asc", "desc"]
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user