mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: mobx changes
This commit is contained in:
parent
91910d106c
commit
d7c27b75fa
@ -9,6 +9,8 @@ import { observer } from "mobx-react-lite";
|
|||||||
// mobx
|
// mobx
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
import { RootStore } from "store/root";
|
import { RootStore } from "store/root";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
const renderEmoji = (emoji: string | { name: string; color: string }) => {
|
const renderEmoji = (emoji: string | { name: string; color: string }) => {
|
||||||
if (!emoji) return;
|
if (!emoji) return;
|
||||||
@ -23,21 +25,30 @@ const renderEmoji = (emoji: string | { name: string; color: string }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const IssueNavbar = observer(() => {
|
const IssueNavbar = observer(() => {
|
||||||
const store: RootStore = useMobxStore();
|
const { project: projectStore }: RootStore = useMobxStore();
|
||||||
|
// router
|
||||||
|
const router = useRouter();
|
||||||
|
const { workspace_slug, project_slug } = router.query;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (workspace_slug && project_slug) {
|
||||||
|
projectStore.fetchProjectSettings(workspace_slug.toString(), project_slug.toString());
|
||||||
|
}
|
||||||
|
}, [projectStore, workspace_slug, project_slug]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-5 relative w-full flex items-center gap-4">
|
<div className="px-5 relative w-full flex items-center gap-4">
|
||||||
{/* project detail */}
|
{/* project detail */}
|
||||||
<div className="flex-shrink-0 flex items-center gap-2">
|
<div className="flex-shrink-0 flex items-center gap-2">
|
||||||
<div className="w-[32px] h-[32px] rounded-sm flex justify-center items-center text-[24px]">
|
<div className="w-[32px] h-[32px] rounded-sm flex justify-center items-center text-[24px]">
|
||||||
{store?.project?.project && store?.project?.project?.emoji ? (
|
{projectStore?.project && projectStore?.project?.emoji ? (
|
||||||
renderEmoji(store?.project?.project?.emoji)
|
renderEmoji(projectStore?.project?.emoji)
|
||||||
) : (
|
) : (
|
||||||
<Image src="/plane-logo.webp" alt="plane logo" className="w-[24px] h-[24px]" height="24" width="24" />
|
<Image src="/plane-logo.webp" alt="plane logo" className="w-[24px] h-[24px]" height="24" width="24" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="font-medium text-lg max-w-[300px] line-clamp-1 overflow-hidden">
|
<div className="font-medium text-lg max-w-[300px] line-clamp-1 overflow-hidden">
|
||||||
{store?.project?.project?.name || `...`}
|
{projectStore?.project?.name || `...`}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -49,7 +60,6 @@ const IssueNavbar = observer(() => {
|
|||||||
{/* issue filters */}
|
{/* issue filters */}
|
||||||
<div className="flex-shrink-0 relative flex items-center gap-2">
|
<div className="flex-shrink-0 relative flex items-center gap-2">
|
||||||
<NavbarIssueFilter />
|
<NavbarIssueFilter />
|
||||||
{/* <NavbarIssueView /> */}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* issue views */}
|
{/* issue views */}
|
||||||
|
@ -10,52 +10,64 @@ import { IssuePeekOverview } from "components/issues/peek-overview";
|
|||||||
// mobx store
|
// mobx store
|
||||||
import { RootStore } from "store/root";
|
import { RootStore } from "store/root";
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export const ProjectDetailsView = () => {
|
export const ProjectDetailsView = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspace_slug } = router.query;
|
const { workspace_slug, project_slug, states, labels, priorities } = router.query;
|
||||||
|
|
||||||
const store: RootStore = useMobxStore();
|
const { issue: issueStore }: RootStore = useMobxStore();
|
||||||
|
|
||||||
const activeIssueId = store.issue.activePeekOverviewIssueId;
|
const activeIssueId = issueStore.activePeekOverviewIssueId;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (workspace_slug && project_slug) {
|
||||||
|
const params = {
|
||||||
|
state: states || null,
|
||||||
|
labels: labels || null,
|
||||||
|
priority: priorities || null,
|
||||||
|
};
|
||||||
|
issueStore.fetchPublicIssues(workspace_slug?.toString(), project_slug.toString(), params);
|
||||||
|
}
|
||||||
|
}, [workspace_slug, project_slug, issueStore, states, labels, priorities]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative w-full h-full overflow-hidden">
|
<div className="relative w-full h-full overflow-hidden">
|
||||||
{workspace_slug && (
|
{workspace_slug && (
|
||||||
<IssuePeekOverview
|
<IssuePeekOverview
|
||||||
isOpen={Boolean(activeIssueId)}
|
isOpen={Boolean(activeIssueId)}
|
||||||
onClose={() => store.issue.setActivePeekOverviewIssueId(null)}
|
onClose={() => issueStore.setActivePeekOverviewIssueId(null)}
|
||||||
issue={store?.issue?.issues?.find((_issue) => _issue.id === activeIssueId) || null}
|
issue={issueStore?.issues?.find((_issue) => _issue.id === activeIssueId) || null}
|
||||||
workspaceSlug={workspace_slug.toString()}
|
workspaceSlug={workspace_slug.toString()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{store?.issue?.loader && !store.issue.issues ? (
|
{issueStore?.loader && !issueStore.issues ? (
|
||||||
<div className="text-sm text-center py-10 text-custom-text-100">Loading...</div>
|
<div className="text-sm text-center py-10 text-custom-text-100">Loading...</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{store?.issue?.error ? (
|
{issueStore?.error ? (
|
||||||
<div className="text-sm text-center py-10 bg-custom-background-200 text-custom-text-100">
|
<div className="text-sm text-center py-10 bg-custom-background-200 text-custom-text-100">
|
||||||
Something went wrong.
|
Something went wrong.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
store?.issue?.currentIssueBoardView && (
|
issueStore?.currentIssueBoardView && (
|
||||||
<>
|
<>
|
||||||
{store?.issue?.currentIssueBoardView === "list" && (
|
{issueStore?.currentIssueBoardView === "list" && (
|
||||||
<div className="relative w-full h-full overflow-y-auto">
|
<div className="relative w-full h-full overflow-y-auto">
|
||||||
<div className="mx-auto px-4">
|
<div className="mx-auto px-4">
|
||||||
<IssueListView />
|
<IssueListView />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{store?.issue?.currentIssueBoardView === "kanban" && (
|
{issueStore?.currentIssueBoardView === "kanban" && (
|
||||||
<div className="relative w-full h-full mx-auto px-9 py-5">
|
<div className="relative w-full h-full mx-auto px-9 py-5">
|
||||||
<IssueKanbanView />
|
<IssueKanbanView />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{store?.issue?.currentIssueBoardView === "calendar" && <IssueCalendarView />}
|
{issueStore?.currentIssueBoardView === "calendar" && <IssueCalendarView />}
|
||||||
{store?.issue?.currentIssueBoardView === "spreadsheet" && <IssueSpreadsheetView />}
|
{issueStore?.currentIssueBoardView === "spreadsheet" && <IssueSpreadsheetView />}
|
||||||
{store?.issue?.currentIssueBoardView === "gantt" && <IssueGanttView />}
|
{issueStore?.currentIssueBoardView === "gantt" && <IssueGanttView />}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
// components
|
// components
|
||||||
import IssueNavbar from "components/issues/navbar";
|
import IssueNavbar from "components/issues/navbar";
|
||||||
|
|
||||||
type LayoutProps = {
|
|
||||||
params: { workspace_slug: string; project_slug: string };
|
|
||||||
};
|
|
||||||
|
|
||||||
const ProjectLayout = ({ children }: { children: React.ReactNode }) => (
|
const ProjectLayout = ({ children }: { children: React.ReactNode }) => (
|
||||||
<div className="relative w-screen min-h-[500px] h-screen overflow-hidden flex flex-col">
|
<div className="relative w-screen min-h-[500px] h-screen overflow-hidden flex flex-col">
|
||||||
<div className="flex-shrink-0 h-[60px] border-b border-gray-300 relative flex items-center bg-white select-none">
|
<div className="flex-shrink-0 h-[60px] border-b border-gray-300 relative flex items-center bg-white select-none">
|
||||||
@ -28,4 +25,4 @@ const ProjectLayout = ({ children }: { children: React.ReactNode }) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default ProjectLayout;
|
export default observer(ProjectLayout);
|
||||||
|
@ -109,12 +109,12 @@ const WorkspaceProjectPage = (props: any) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps<any> = async ({ query: { workspace_slug, project_slug } }) => {
|
// export const getServerSideProps: GetServerSideProps<any> = async ({ query: { workspace_slug, project_slug } }) => {
|
||||||
const res = await fetch(
|
// const res = await fetch(
|
||||||
`${process.env.NEXT_PUBLIC_API_BASE_URL}/api/public/workspaces/${workspace_slug}/project-boards/${project_slug}/settings/`
|
// `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/public/workspaces/${workspace_slug}/project-boards/${project_slug}/settings/`
|
||||||
);
|
// );
|
||||||
const project_settings = await res.json();
|
// const project_settings = await res.json();
|
||||||
return { props: { project_settings } };
|
// return { props: { project_settings } };
|
||||||
};
|
// };
|
||||||
|
|
||||||
export default WorkspaceProjectPage;
|
export default WorkspaceProjectPage;
|
||||||
|
@ -6,7 +6,7 @@ class ProjectService extends APIService {
|
|||||||
super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||||
}
|
}
|
||||||
|
|
||||||
async getProjectSettingsAsync(workspace_slug: string, project_slug: string): Promise<any> {
|
async getProjectSettings(workspace_slug: string, project_slug: string): Promise<any> {
|
||||||
return this.get(`/api/public/workspaces/${workspace_slug}/project-boards/${project_slug}/settings/`)
|
return this.get(`/api/public/workspaces/${workspace_slug}/project-boards/${project_slug}/settings/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
@ -4,9 +4,41 @@ import { observable, action, computed, makeObservable, runInAction, reaction } f
|
|||||||
import IssueService from "services/issue.service";
|
import IssueService from "services/issue.service";
|
||||||
// types
|
// types
|
||||||
import { IssueDetailType, TIssueBoardKeys } from "store/types/issue";
|
import { IssueDetailType, TIssueBoardKeys } from "store/types/issue";
|
||||||
import { IIssueStore, IIssue, IIssueState, IIssueLabel } from "./types";
|
import { IIssue, IIssueState, IIssueLabel } from "./types";
|
||||||
|
|
||||||
|
export interface IIssueStore {
|
||||||
|
currentIssueBoardView: TIssueBoardKeys | null;
|
||||||
|
loader: boolean;
|
||||||
|
error: any | null;
|
||||||
|
states: IIssueState[] | null;
|
||||||
|
labels: IIssueLabel[] | null;
|
||||||
|
issues: IIssue[] | null;
|
||||||
|
issue_detail: IssueDetailType;
|
||||||
|
userSelectedStates: string[];
|
||||||
|
userSelectedLabels: string[];
|
||||||
|
userSelectedPriorities: string[];
|
||||||
|
activePeekOverviewIssueId: string | null;
|
||||||
|
getCountOfIssuesByState: (state: string) => number;
|
||||||
|
getFilteredIssuesByState: (state: string) => IIssue[];
|
||||||
|
getUserSelectedFilter: (key: "state" | "priority" | "label", value: string) => boolean;
|
||||||
|
checkIfFilterExistsForKey: (key: "state" | "priority" | "label") => boolean;
|
||||||
|
clearUserSelectedFilter: (key: "state" | "priority" | "label" | "all") => void;
|
||||||
|
getIfFiltersIsEmpty: () => boolean;
|
||||||
|
getURLDefinition: (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string,
|
||||||
|
action?: {
|
||||||
|
key: "state" | "priority" | "label" | "all";
|
||||||
|
value?: string;
|
||||||
|
removeAll?: boolean;
|
||||||
|
}
|
||||||
|
) => string;
|
||||||
|
setActivePeekOverviewIssueId: (value: any) => void;
|
||||||
|
setCurrentIssueBoardView: (view: TIssueBoardKeys) => void;
|
||||||
|
fetchPublicIssues: (workspaceSlug: string, projectId: string, params: any) => Promise<void>;
|
||||||
|
getIssueByIdAsync: (workspaceSlug: string, projectId: string, issueId: string) => Promise<IssueDetailType>;
|
||||||
|
}
|
||||||
|
|
||||||
// class IssueStore implements IIssueStore {
|
|
||||||
class IssueStore {
|
class IssueStore {
|
||||||
currentIssueBoardView: TIssueBoardKeys | null = null;
|
currentIssueBoardView: TIssueBoardKeys | null = null;
|
||||||
|
|
||||||
@ -49,7 +81,7 @@ class IssueStore {
|
|||||||
userSelectedPriorities: observable.ref,
|
userSelectedPriorities: observable.ref,
|
||||||
// action
|
// action
|
||||||
setCurrentIssueBoardView: action,
|
setCurrentIssueBoardView: action,
|
||||||
getIssuesAsync: action,
|
fetchPublicIssues: action,
|
||||||
// computed
|
// computed
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -167,7 +199,7 @@ class IssueStore {
|
|||||||
this.currentIssueBoardView = view;
|
this.currentIssueBoardView = view;
|
||||||
};
|
};
|
||||||
|
|
||||||
getIssuesAsync = async (workspaceSlug: string, projectId: string, params: any) => {
|
fetchPublicIssues = async (workspaceSlug: string, projectId: string, params: any) => {
|
||||||
try {
|
try {
|
||||||
this.loader = true;
|
this.loader = true;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
@ -3,15 +3,26 @@ import { observable, action, makeObservable, runInAction } from "mobx";
|
|||||||
// service
|
// service
|
||||||
import ProjectService from "services/project.service";
|
import ProjectService from "services/project.service";
|
||||||
// types
|
// types
|
||||||
import { IProjectStore, IWorkspace, IProject, IProjectSettings } from "./types";
|
import { IWorkspace, IProject, IProjectSettings } from "./types";
|
||||||
|
|
||||||
|
export interface IProjectStore {
|
||||||
|
loader: boolean;
|
||||||
|
error: any | null;
|
||||||
|
workspace: IWorkspace | null;
|
||||||
|
project: IProject | null;
|
||||||
|
projectDeploySettings: IProjectSettings | null;
|
||||||
|
viewOptions: any;
|
||||||
|
fetchProjectSettings: (workspace_slug: string, project_slug: string) => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
class ProjectStore implements IProjectStore {
|
class ProjectStore implements IProjectStore {
|
||||||
loader: boolean = false;
|
loader: boolean = false;
|
||||||
error: any | null = null;
|
error: any | null = null;
|
||||||
|
// data
|
||||||
workspace: IWorkspace | null = null;
|
workspace: IWorkspace | null = null;
|
||||||
project: IProject | null = null;
|
project: IProject | null = null;
|
||||||
workspaceProjectSettings: IProjectSettings | null = null;
|
projectDeploySettings: IProjectSettings | null = null;
|
||||||
|
viewOptions: any = null;
|
||||||
// root store
|
// root store
|
||||||
rootStore;
|
rootStore;
|
||||||
// service
|
// service
|
||||||
@ -19,14 +30,16 @@ class ProjectStore implements IProjectStore {
|
|||||||
|
|
||||||
constructor(_rootStore: any | null = null) {
|
constructor(_rootStore: any | null = null) {
|
||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
|
// loaders and error observables
|
||||||
|
loader: observable,
|
||||||
|
error: observable.ref,
|
||||||
// observable
|
// observable
|
||||||
workspace: observable.ref,
|
workspace: observable.ref,
|
||||||
project: observable.ref,
|
project: observable.ref,
|
||||||
workspaceProjectSettings: observable.ref,
|
projectDeploySettings: observable.ref,
|
||||||
loader: observable,
|
viewOptions: observable.ref,
|
||||||
error: observable.ref,
|
// actions
|
||||||
// action
|
fetchProjectSettings: action,
|
||||||
getProjectSettingsAsync: action,
|
|
||||||
// computed
|
// computed
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -34,26 +47,21 @@ class ProjectStore implements IProjectStore {
|
|||||||
this.projectService = new ProjectService();
|
this.projectService = new ProjectService();
|
||||||
}
|
}
|
||||||
|
|
||||||
getProjectSettingsAsync = async (workspace_slug: string, project_slug: string) => {
|
fetchProjectSettings = async (workspace_slug: string, project_slug: string) => {
|
||||||
try {
|
try {
|
||||||
this.loader = true;
|
this.loader = true;
|
||||||
this.error = null;
|
this.error = null;
|
||||||
|
|
||||||
const response = await this.projectService.getProjectSettingsAsync(workspace_slug, project_slug);
|
const response = await this.projectService.getProjectSettings(workspace_slug, project_slug);
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
const _project: IProject = { ...response?.project_details };
|
const _project: IProject = { ...response?.project_details };
|
||||||
const _workspace: IWorkspace = { ...response?.workspace_detail };
|
const _workspace: IWorkspace = { ...response?.workspace_detail };
|
||||||
const _workspaceProjectSettings: IProjectSettings = {
|
const _viewOptions = { ...response?.views };
|
||||||
comments: response?.comments,
|
|
||||||
reactions: response?.reactions,
|
|
||||||
votes: response?.votes,
|
|
||||||
views: { ...response?.views },
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.project = _project;
|
this.project = _project;
|
||||||
this.workspace = _workspace;
|
this.workspace = _workspace;
|
||||||
this.workspaceProjectSettings = _workspaceProjectSettings;
|
this.viewOptions = _viewOptions;
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,17 @@ import { enableStaticRendering } from "mobx-react-lite";
|
|||||||
// store imports
|
// store imports
|
||||||
import UserStore from "./user";
|
import UserStore from "./user";
|
||||||
import ThemeStore from "./theme";
|
import ThemeStore from "./theme";
|
||||||
import IssueStore from "./issue";
|
import IssueStore, { IIssueStore } from "./issue";
|
||||||
import ProjectStore from "./project";
|
import ProjectStore, { IProjectStore } from "./project";
|
||||||
// types
|
// types
|
||||||
import { IIssueStore, IProjectStore, IThemeStore } from "./types";
|
import { IThemeStore } from "./types";
|
||||||
|
|
||||||
enableStaticRendering(typeof window === "undefined");
|
enableStaticRendering(typeof window === "undefined");
|
||||||
|
|
||||||
export class RootStore {
|
export class RootStore {
|
||||||
user: UserStore;
|
user: UserStore;
|
||||||
theme: IThemeStore;
|
theme: IThemeStore;
|
||||||
issue: IssueStore;
|
issue: IIssueStore;
|
||||||
project: IProjectStore;
|
project: IProjectStore;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -143,45 +143,3 @@ export interface IssueDetailType {
|
|||||||
votes: any[];
|
votes: any[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IIssueStore {
|
|
||||||
currentIssueBoardView: TIssueBoardKeys | null;
|
|
||||||
loader: boolean;
|
|
||||||
error: any | null;
|
|
||||||
|
|
||||||
states: IIssueState[] | null;
|
|
||||||
labels: IIssueLabel[] | null;
|
|
||||||
issues: IIssue[] | null;
|
|
||||||
|
|
||||||
issue_detail: IssueDetailType;
|
|
||||||
|
|
||||||
userSelectedStates: string[];
|
|
||||||
userSelectedLabels: string[];
|
|
||||||
userSelectedPriorities: string[];
|
|
||||||
|
|
||||||
getCountOfIssuesByState: (state: string) => number;
|
|
||||||
getFilteredIssuesByState: (state: string) => IIssue[];
|
|
||||||
|
|
||||||
getUserSelectedFilter: (key: "state" | "priority" | "label", value: string) => boolean;
|
|
||||||
|
|
||||||
checkIfFilterExistsForKey: (key: "state" | "priority" | "label") => boolean;
|
|
||||||
|
|
||||||
clearUserSelectedFilter: (key: "state" | "priority" | "label" | "all") => void;
|
|
||||||
|
|
||||||
getIfFiltersIsEmpty: () => boolean;
|
|
||||||
|
|
||||||
getURLDefinition: (
|
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
action?: {
|
|
||||||
key: "state" | "priority" | "label" | "all";
|
|
||||||
value?: string;
|
|
||||||
removeAll?: boolean;
|
|
||||||
}
|
|
||||||
) => string;
|
|
||||||
|
|
||||||
setCurrentIssueBoardView: (view: TIssueBoardKeys) => void;
|
|
||||||
getIssuesAsync: (workspaceSlug: string, projectId: string, params: any) => Promise<void>;
|
|
||||||
|
|
||||||
getIssueByIdAsync: (workspaceSlug: string, projectId: string, issueId: string) => Promise<IssueDetailType>;
|
|
||||||
}
|
|
||||||
|
@ -27,14 +27,3 @@ export interface IProjectSettings {
|
|||||||
spreadsheet: boolean;
|
spreadsheet: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProjectStore {
|
|
||||||
loader: boolean;
|
|
||||||
error: any | null;
|
|
||||||
|
|
||||||
workspace: IWorkspace | null;
|
|
||||||
project: IProject | null;
|
|
||||||
workspaceProjectSettings: IProjectSettings | null;
|
|
||||||
|
|
||||||
getProjectSettingsAsync: (workspace_slug: string, project_slug: string) => Promise<void>;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user