ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: frontend read-layer и первый экран двусторонней доски внешних контуров
This commit is contained in:
@@ -102,8 +102,6 @@ export const NotificationsRoot = observer(function NotificationsRoot({ workspace
|
||||
</div>
|
||||
) : (
|
||||
<ExternalContoursContentRoot
|
||||
setIsMobileSidebar={() => {}}
|
||||
isMobileSidebar={false}
|
||||
workspaceSlug={workspace_slug}
|
||||
projectId={project_id}
|
||||
inboxIssueId={issue_id}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import { useContext } from "react";
|
||||
import { StoreContext } from "@/lib/store-context";
|
||||
import type { IProjectExternalContoursBoardStore } from "@/store/external-contours/project-external-contours-board.store";
|
||||
|
||||
export const useProjectExternalContoursBoard = (): IProjectExternalContoursBoardStore => {
|
||||
const context = useContext(StoreContext);
|
||||
if (context === undefined) throw new Error("useProjectExternalContoursBoard must be used within StoreProvider");
|
||||
return context.projectExternalContoursBoard;
|
||||
};
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
import { API_BASE_URL } from "@plane/constants";
|
||||
import type {
|
||||
TExternalContourBoardFilter,
|
||||
TExternalContourBoardResponse,
|
||||
TExternalContourRequest,
|
||||
TExternalContourRequestResponse,
|
||||
TExternalContourTargetOptions,
|
||||
@@ -27,6 +29,26 @@ export class ExternalContourService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async listBoard(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
filters: Partial<TExternalContourBoardFilter> = {}
|
||||
): Promise<TExternalContourBoardResponse> {
|
||||
const params = Object.fromEntries(
|
||||
Object.entries(filters).flatMap(([key, value]) => {
|
||||
if (value === undefined || value === null || value === "") return [];
|
||||
if (Array.isArray(value)) return [[key, value.join(",")]];
|
||||
return [[key, String(value)]];
|
||||
})
|
||||
);
|
||||
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/external-contours/board/`, { params })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async retrieve(workspaceSlug: string, projectId: string, requestId: string): Promise<TExternalContourRequest> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/external-contours/${requestId}/`)
|
||||
.then((response) => response?.data)
|
||||
@@ -35,6 +57,14 @@ export class ExternalContourService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveBoardItem(workspaceSlug: string, projectId: string, requestId: string): Promise<TExternalContourRequest> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/external-contours/board-items/${requestId}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateRequest(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||
import type {
|
||||
TExternalContourBoardDirection,
|
||||
TExternalContourBoardFilter,
|
||||
TExternalContourBoardSorting,
|
||||
TExternalContourRequest,
|
||||
TInboxIssueCurrentTab,
|
||||
} from "@plane/types";
|
||||
import { EInboxIssueCurrentTab } from "@plane/types";
|
||||
import { ExternalContourService } from "@/services/external-contours";
|
||||
import type { CoreRootStore } from "../root.store";
|
||||
|
||||
type TLoader = "init-loading" | undefined;
|
||||
|
||||
export interface IProjectExternalContoursBoardStore {
|
||||
currentProjectId: string;
|
||||
currentTab: TInboxIssueCurrentTab;
|
||||
error: { message: string; status: "init-error" } | undefined;
|
||||
filters: Partial<TExternalContourBoardFilter>;
|
||||
items: Record<string, TExternalContourRequest>;
|
||||
loader: TLoader;
|
||||
sorting: TExternalContourBoardSorting;
|
||||
columnIdsMap: Record<TExternalContourBoardDirection, string[]>;
|
||||
columnCountMap: Record<TExternalContourBoardDirection, number>;
|
||||
tabCountMap: Record<TInboxIssueCurrentTab, number>;
|
||||
fetchBoard: (workspaceSlug: string, projectId: string, tab?: TInboxIssueCurrentTab) => Promise<void>;
|
||||
getColumnRequestIds: (direction: TExternalContourBoardDirection) => string[];
|
||||
getColumnTotalCount: (direction: TExternalContourBoardDirection) => number;
|
||||
getRequestById: (requestId: string) => TExternalContourRequest | undefined;
|
||||
handleCurrentTab: (workspaceSlug: string, projectId: string, tab: TInboxIssueCurrentTab) => Promise<void>;
|
||||
hasAnyItems: boolean;
|
||||
upsertBoardItems: (items: TExternalContourRequest[]) => void;
|
||||
}
|
||||
|
||||
export class ProjectExternalContoursBoardStore implements IProjectExternalContoursBoardStore {
|
||||
currentProjectId = "";
|
||||
currentTab: TInboxIssueCurrentTab = EInboxIssueCurrentTab.OPEN;
|
||||
error: { message: string; status: "init-error" } | undefined = undefined;
|
||||
filters: Partial<TExternalContourBoardFilter> = { status: [EInboxIssueCurrentTab.OPEN] };
|
||||
items: Record<string, TExternalContourRequest> = {};
|
||||
loader: TLoader = "init-loading";
|
||||
sorting: TExternalContourBoardSorting = { order_by: "updated_at", sort_by: "desc" };
|
||||
columnIdsMap: Record<TExternalContourBoardDirection, string[]> = {
|
||||
outgoing: [],
|
||||
incoming: [],
|
||||
};
|
||||
columnCountMap: Record<TExternalContourBoardDirection, number> = {
|
||||
outgoing: 0,
|
||||
incoming: 0,
|
||||
};
|
||||
tabCountMap: Record<TInboxIssueCurrentTab, number> = {
|
||||
[EInboxIssueCurrentTab.OPEN]: 0,
|
||||
[EInboxIssueCurrentTab.CLOSED]: 0,
|
||||
};
|
||||
|
||||
externalContourService;
|
||||
|
||||
constructor(private store: CoreRootStore) {
|
||||
makeObservable(this, {
|
||||
currentProjectId: observable.ref,
|
||||
currentTab: observable.ref,
|
||||
error: observable.ref,
|
||||
filters: observable.ref,
|
||||
items: observable,
|
||||
loader: observable.ref,
|
||||
sorting: observable.ref,
|
||||
columnIdsMap: observable,
|
||||
columnCountMap: observable,
|
||||
tabCountMap: observable,
|
||||
hasAnyItems: computed,
|
||||
fetchBoard: action,
|
||||
handleCurrentTab: action,
|
||||
upsertBoardItems: action,
|
||||
});
|
||||
|
||||
this.externalContourService = new ExternalContourService();
|
||||
}
|
||||
|
||||
get hasAnyItems() {
|
||||
return this.columnIdsMap.outgoing.length > 0 || this.columnIdsMap.incoming.length > 0;
|
||||
}
|
||||
|
||||
getRequestById = (requestId: string) => this.items[requestId];
|
||||
|
||||
getColumnRequestIds = (direction: TExternalContourBoardDirection) => this.columnIdsMap[direction] ?? [];
|
||||
|
||||
getColumnTotalCount = (direction: TExternalContourBoardDirection) => this.columnCountMap[direction] ?? 0;
|
||||
|
||||
upsertBoardItems = (items: TExternalContourRequest[]) => {
|
||||
items.forEach((request) => {
|
||||
this.items[request.id] = request;
|
||||
});
|
||||
|
||||
this.store.projectExternalContours.upsertRequests(items);
|
||||
};
|
||||
|
||||
handleCurrentTab = async (workspaceSlug: string, projectId: string, tab: TInboxIssueCurrentTab) => {
|
||||
this.currentProjectId = projectId;
|
||||
this.currentTab = tab;
|
||||
this.filters = {
|
||||
...this.filters,
|
||||
status: [tab],
|
||||
};
|
||||
await this.fetchBoard(workspaceSlug, projectId, tab);
|
||||
};
|
||||
|
||||
fetchBoard = async (workspaceSlug: string, projectId: string, tab = this.currentTab) => {
|
||||
this.loader = "init-loading";
|
||||
this.error = undefined;
|
||||
this.currentProjectId = projectId;
|
||||
this.currentTab = tab;
|
||||
this.filters = {
|
||||
...this.filters,
|
||||
status: [tab],
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await this.externalContourService.listBoard(workspaceSlug, projectId, {
|
||||
status: tab,
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
this.items = {};
|
||||
this.columnIdsMap = { outgoing: [], incoming: [] };
|
||||
this.columnCountMap = { outgoing: 0, incoming: 0 };
|
||||
this.filters = response.filters || { status: [tab] };
|
||||
this.sorting = response.sorting || { order_by: "updated_at", sort_by: "desc" };
|
||||
|
||||
response.columns.forEach((column) => {
|
||||
this.columnIdsMap[column.key] = column.results.map((request) => request.id);
|
||||
this.columnCountMap[column.key] = column.total_count;
|
||||
this.upsertBoardItems(column.results);
|
||||
});
|
||||
|
||||
this.tabCountMap = {
|
||||
...this.tabCountMap,
|
||||
[tab]: response.columns.reduce((total, column) => total + column.total_count, 0),
|
||||
};
|
||||
|
||||
this.loader = undefined;
|
||||
});
|
||||
} catch (error: any) {
|
||||
runInAction(() => {
|
||||
this.loader = undefined;
|
||||
this.error = {
|
||||
message: error?.error || "Не удалось загрузить доску внешних контуров",
|
||||
status: "init-error",
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -215,7 +215,7 @@ export class ProjectExternalContoursStore implements IProjectExternalContoursSto
|
||||
fetchRequestById = async (workspaceSlug: string, projectId: string, requestId: string) => {
|
||||
this.loader = "issue-loading";
|
||||
try {
|
||||
const request = await this.externalContourService.retrieve(workspaceSlug, projectId, requestId);
|
||||
const request = await this.externalContourService.retrieveBoardItem(workspaceSlug, projectId, requestId);
|
||||
runInAction(() => {
|
||||
this.upsertRequests([request]);
|
||||
this.loader = undefined;
|
||||
|
||||
@@ -32,6 +32,8 @@ import { EditorAssetStore } from "./editor/asset.store";
|
||||
import type { IProjectEstimateStore } from "./estimates/project-estimate.store";
|
||||
import { ProjectEstimateStore } from "./estimates/project-estimate.store";
|
||||
import type { IProjectExternalContoursStore } from "./external-contours/project-external-contours.store";
|
||||
import type { IProjectExternalContoursBoardStore } from "./external-contours/project-external-contours-board.store";
|
||||
import { ProjectExternalContoursBoardStore } from "./external-contours/project-external-contours-board.store";
|
||||
import { ProjectExternalContoursStore } from "./external-contours/project-external-contours.store";
|
||||
import type { IFavoriteStore } from "./favorite.store";
|
||||
import { FavoriteStore } from "./favorite.store";
|
||||
@@ -95,6 +97,7 @@ export class CoreRootStore {
|
||||
instance: IInstanceStore;
|
||||
user: IUserStore;
|
||||
projectInbox: IProjectInboxStore;
|
||||
projectExternalContoursBoard: IProjectExternalContoursBoardStore;
|
||||
projectExternalContours: IProjectExternalContoursStore;
|
||||
projectEstimate: IProjectEstimateStore;
|
||||
multipleSelect: IMultipleSelectStore;
|
||||
@@ -127,6 +130,7 @@ export class CoreRootStore {
|
||||
this.multipleSelect = new MultipleSelectStore();
|
||||
this.projectInbox = new ProjectInboxStore(this);
|
||||
this.projectExternalContours = new ProjectExternalContoursStore(this);
|
||||
this.projectExternalContoursBoard = new ProjectExternalContoursBoardStore(this);
|
||||
this.projectPages = new ProjectPageStore(this as unknown as RootStore);
|
||||
this.projectEstimate = new ProjectEstimateStore(this);
|
||||
this.workspaceNotification = new WorkspaceNotificationStore(this);
|
||||
@@ -161,6 +165,7 @@ export class CoreRootStore {
|
||||
this.dashboard = new DashboardStore(this);
|
||||
this.projectInbox = new ProjectInboxStore(this);
|
||||
this.projectExternalContours = new ProjectExternalContoursStore(this);
|
||||
this.projectExternalContoursBoard = new ProjectExternalContoursBoardStore(this);
|
||||
this.projectPages = new ProjectPageStore(this as unknown as RootStore);
|
||||
this.multipleSelect = new MultipleSelectStore();
|
||||
this.projectEstimate = new ProjectEstimateStore(this);
|
||||
|
||||
Reference in New Issue
Block a user