fix: store changes

This commit is contained in:
sriram veeraghanta 2023-12-11 20:15:07 +05:30
parent 9d909d2953
commit 2068f54f1d
10 changed files with 1039 additions and 11 deletions

View File

@ -11,7 +11,7 @@ export interface IAppConfigStore {
fetchAppConfig: () => Promise<any>;
}
class AppConfigStore implements IAppConfigStore {
export class AppConfigStore implements IAppConfigStore {
// observables
envConfig: IAppConfig | null = null;
@ -43,5 +43,3 @@ class AppConfigStore implements IAppConfigStore {
}
};
}
export default AppConfigStore;

View File

@ -0,0 +1,198 @@
import { observable, action, makeObservable, computed } from "mobx";
// types
import { RootStore } from "../root.store";
// services
import { ProjectService } from "services/project";
import { PageService } from "services/page.service";
export enum EProjectStore {
PROJECT = "ProjectStore",
PROJECT_VIEW = "ProjectViewStore",
PROFILE = "ProfileStore",
MODULE = "ModuleStore",
CYCLE = "CycleStore",
}
export interface ModalData {
store: EProjectStore;
viewId: string;
}
export interface ICommandPaletteStore {
isCommandPaletteOpen: boolean;
isShortcutModalOpen: boolean;
isCreateProjectModalOpen: boolean;
isCreateCycleModalOpen: boolean;
isCreateModuleModalOpen: boolean;
isCreateViewModalOpen: boolean;
isCreatePageModalOpen: boolean;
isCreateIssueModalOpen: boolean;
isDeleteIssueModalOpen: boolean;
isBulkDeleteIssueModalOpen: boolean;
// computed
isAnyModalOpen: boolean;
toggleCommandPaletteModal: (value?: boolean) => void;
toggleShortcutModal: (value?: boolean) => void;
toggleCreateProjectModal: (value?: boolean) => void;
toggleCreateCycleModal: (value?: boolean) => void;
toggleCreateViewModal: (value?: boolean) => void;
toggleCreatePageModal: (value?: boolean) => void;
toggleCreateIssueModal: (value?: boolean, storeType?: EProjectStore) => void;
toggleCreateModuleModal: (value?: boolean) => void;
toggleDeleteIssueModal: (value?: boolean) => void;
toggleBulkDeleteIssueModal: (value?: boolean) => void;
createIssueStoreType: EProjectStore;
}
export class CommandPaletteStore implements ICommandPaletteStore {
isCommandPaletteOpen: boolean = false;
isShortcutModalOpen: boolean = false;
isCreateProjectModalOpen: boolean = false;
isCreateCycleModalOpen: boolean = false;
isCreateModuleModalOpen: boolean = false;
isCreateViewModalOpen: boolean = false;
isCreatePageModalOpen: boolean = false;
isCreateIssueModalOpen: boolean = false;
isDeleteIssueModalOpen: boolean = false;
isBulkDeleteIssueModalOpen: boolean = false;
// root store
rootStore;
// service
projectService;
pageService;
createIssueStoreType: EProjectStore = EProjectStore.PROJECT;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
isCommandPaletteOpen: observable.ref,
isShortcutModalOpen: observable.ref,
isCreateProjectModalOpen: observable.ref,
isCreateCycleModalOpen: observable.ref,
isCreateModuleModalOpen: observable.ref,
isCreateViewModalOpen: observable.ref,
isCreatePageModalOpen: observable.ref,
isCreateIssueModalOpen: observable.ref,
isDeleteIssueModalOpen: observable.ref,
isBulkDeleteIssueModalOpen: observable.ref,
// computed
isAnyModalOpen: computed,
// projectPages: computed,
// action
toggleCommandPaletteModal: action,
toggleShortcutModal: action,
toggleCreateProjectModal: action,
toggleCreateCycleModal: action,
toggleCreateViewModal: action,
toggleCreatePageModal: action,
toggleCreateIssueModal: action,
toggleCreateModuleModal: action,
toggleDeleteIssueModal: action,
toggleBulkDeleteIssueModal: action,
});
this.rootStore = _rootStore;
this.projectService = new ProjectService();
this.pageService = new PageService();
}
get isAnyModalOpen() {
return Boolean(
this.isCreateIssueModalOpen ||
this.isCreateCycleModalOpen ||
this.isCreatePageModalOpen ||
this.isCreateProjectModalOpen ||
this.isCreateModuleModalOpen ||
this.isCreateViewModalOpen ||
this.isShortcutModalOpen ||
this.isBulkDeleteIssueModalOpen ||
this.isDeleteIssueModalOpen
);
}
toggleCommandPaletteModal = (value?: boolean) => {
if (value !== undefined) {
this.isCommandPaletteOpen = value;
} else {
this.isCommandPaletteOpen = !this.isCommandPaletteOpen;
}
};
toggleShortcutModal = (value?: boolean) => {
if (value !== undefined) {
this.isShortcutModalOpen = value;
} else {
this.isShortcutModalOpen = !this.isShortcutModalOpen;
}
};
toggleCreateProjectModal = (value?: boolean) => {
if (value !== undefined) {
this.isCreateProjectModalOpen = value;
} else {
this.isCreateProjectModalOpen = !this.isCreateProjectModalOpen;
}
};
toggleCreateCycleModal = (value?: boolean) => {
if (value !== undefined) {
this.isCreateCycleModalOpen = value;
} else {
this.isCreateCycleModalOpen = !this.isCreateCycleModalOpen;
}
};
toggleCreateViewModal = (value?: boolean) => {
if (value !== undefined) {
this.isCreateViewModalOpen = value;
} else {
this.isCreateViewModalOpen = !this.isCreateViewModalOpen;
}
};
toggleCreatePageModal = (value?: boolean) => {
if (value !== undefined) {
this.isCreatePageModalOpen = value;
} else {
this.isCreatePageModalOpen = !this.isCreatePageModalOpen;
}
};
toggleCreateIssueModal = (value?: boolean, storeType?: EProjectStore) => {
if (value !== undefined) {
this.isCreateIssueModalOpen = value;
this.createIssueStoreType = storeType || EProjectStore.PROJECT;
} else {
this.isCreateIssueModalOpen = !this.isCreateIssueModalOpen;
this.createIssueStoreType = EProjectStore.PROJECT;
}
};
toggleDeleteIssueModal = (value?: boolean) => {
if (value !== undefined) {
this.isDeleteIssueModalOpen = value;
} else {
this.isDeleteIssueModalOpen = !this.isDeleteIssueModalOpen;
}
};
toggleCreateModuleModal = (value?: boolean) => {
if (value !== undefined) {
this.isCreateModuleModalOpen = value;
} else {
this.isCreateModuleModalOpen = !this.isCreateModuleModalOpen;
}
};
toggleBulkDeleteIssueModal = (value?: boolean) => {
if (value !== undefined) {
this.isBulkDeleteIssueModalOpen = value;
} else {
this.isBulkDeleteIssueModalOpen = !this.isBulkDeleteIssueModalOpen;
}
};
}

View File

@ -0,0 +1,78 @@
import { action, makeObservable, observable } from "mobx";
import posthog from "posthog-js";
// stores
import { RootStore } from "../root.store";
export interface IEventTrackerStore {
trackElement: string;
setTrackElement: (element: string) => void;
postHogEventTracker: (
eventName: string,
payload: object | [] | null,
group?: { isGrouping: boolean | null; groupType: string | null; gorupId: string | null } | null
) => void;
}
export class EventTrackerStore implements IEventTrackerStore {
trackElement: string = "";
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
trackElement: observable,
setTrackElement: action,
postHogEventTracker: action,
});
this.rootStore = _rootStore;
}
setTrackElement = (element: string) => {
this.trackElement = element;
};
postHogEventTracker = (
eventName: string,
payload: object | [] | null,
group?: { isGrouping: boolean | null; groupType: string | null; gorupId: string | null } | null
) => {
try {
let extras: any = {
workspace_name: this.rootStore.workspace.currentWorkspace?.name ?? "",
workspace_id: this.rootStore.workspace.currentWorkspace?.id ?? "",
workspace_slug: this.rootStore.workspace.currentWorkspace?.slug ?? "",
project_name: this.rootStore.project.currentProjectDetails?.name ?? "",
project_id: this.rootStore.project.currentProjectDetails?.id ?? "",
project_identifier: this.rootStore.project.currentProjectDetails?.identifier ?? "",
};
if (["PROJECT_CREATED", "PROJECT_UPDATED"].includes(eventName)) {
const project_details: any = payload as object;
extras = {
...extras,
project_name: project_details?.name ?? "",
project_id: project_details?.id ?? "",
project_identifier: project_details?.identifier ?? "",
};
}
if (group && group!.isGrouping === true) {
posthog?.group(group!.groupType!, group!.gorupId!, {
date: new Date(),
workspace_id: group!.gorupId,
});
posthog?.capture(eventName, {
...payload,
extras: extras,
element: this.trackElement ?? "",
});
} else {
posthog?.capture(eventName, {
...payload,
extras: extras,
element: this.trackElement ?? "",
});
}
} catch (error) {
throw error;
}
this.setTrackElement("");
};
}

View File

@ -1,17 +1,25 @@
import { RootStore } from "../root.store";
import { AppConfigStore } from "./app-config.store";
import { CommandPaletteStore } from "./command-palette.store";
import { EventTrackerStore } from "./event-tracker.store";
import { InstanceStore } from "./instance.store";
import { RouterStore } from "./router.store";
import { ThemeStore } from "./theme.store";
export class AppRootStore {
config;
commandPalette;
eventTracker;
instance;
theme;
config: AppConfigStore;
commandPalette: CommandPaletteStore;
eventTracker: EventTrackerStore;
instance: InstanceStore;
theme: ThemeStore;
router: RouterStore;
constructor(rootStore: RootStore) {
this.config = new ConfigStore(rootStore);
this.config = new AppConfigStore(rootStore);
this.commandPalette = new CommandPaletteStore(rootStore);
this.eventTracker = new EventTrackerStore(rootStore);
this.instance = new InstanceStore(rootStore);
this.theme = new ThemeStore(rootStore);
this.router = new RouterStore();
}
}

View File

@ -0,0 +1,178 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx";
// store
import { RootStore } from "../root.store";
// types
import { IInstance, IInstanceConfiguration, IFormattedInstanceConfiguration, IInstanceAdmin } from "types/instance";
// services
import { InstanceService } from "services/instance.service";
export interface IInstanceStore {
loader: boolean;
error: any | null;
// issues
instance: IInstance | null;
instanceAdmins: IInstanceAdmin[] | null;
configurations: IInstanceConfiguration[] | null;
// computed
formattedConfig: IFormattedInstanceConfiguration | null;
// action
fetchInstanceInfo: () => Promise<IInstance>;
fetchInstanceAdmins: () => Promise<IInstanceAdmin[]>;
updateInstanceInfo: (data: Partial<IInstance>) => Promise<IInstance>;
fetchInstanceConfigurations: () => Promise<any>;
updateInstanceConfigurations: (data: Partial<IFormattedInstanceConfiguration>) => Promise<IInstanceConfiguration[]>;
}
export class InstanceStore implements IInstanceStore {
loader: boolean = false;
error: any | null = null;
instance: IInstance | null = null;
instanceAdmins: IInstanceAdmin[] | null = null;
configurations: IInstanceConfiguration[] | null = null;
// service
instanceService;
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
loader: observable.ref,
error: observable.ref,
instance: observable,
instanceAdmins: observable,
configurations: observable,
// computed
formattedConfig: computed,
// actions
fetchInstanceInfo: action,
fetchInstanceAdmins: action,
updateInstanceInfo: action,
fetchInstanceConfigurations: action,
updateInstanceConfigurations: action,
});
this.rootStore = _rootStore;
this.instanceService = new InstanceService();
}
/**
* computed value for instance configurations data for forms.
* @returns configurations in the form of {key, value} pair.
*/
get formattedConfig() {
if (!this.configurations) return null;
return this.configurations?.reduce((formData: IFormattedInstanceConfiguration, config) => {
formData[config.key] = config.value;
return formData;
}, {});
}
/**
* fetch instance info from API
*/
fetchInstanceInfo = async () => {
try {
const instance = await this.instanceService.getInstanceInfo();
runInAction(() => {
this.instance = instance;
});
return instance;
} catch (error) {
console.log("Error while fetching the instance info");
throw error;
}
};
/**
* fetch instance admins from API
*/
fetchInstanceAdmins = async () => {
try {
const instanceAdmins = await this.instanceService.getInstanceAdmins();
runInAction(() => {
this.instanceAdmins = instanceAdmins;
});
return instanceAdmins;
} catch (error) {
console.log("Error while fetching the instance admins");
throw error;
}
};
/**
* update instance info
* @param data
*/
updateInstanceInfo = async (data: Partial<IInstance>) => {
try {
runInAction(() => {
this.loader = true;
this.error = null;
});
const response = await this.instanceService.updateInstanceInfo(data);
runInAction(() => {
this.loader = false;
this.error = null;
this.instance = response;
});
return response;
} catch (error) {
runInAction(() => {
this.loader = false;
this.error = error;
});
throw error;
}
};
/**
* fetch instace configurations from API
*/
fetchInstanceConfigurations = async () => {
try {
const configurations = await this.instanceService.getInstanceConfigurations();
runInAction(() => {
this.configurations = configurations;
});
return configurations;
} catch (error) {
console.log("Error while fetching the instance configurations");
throw error;
}
};
/**
* update instance configurations
* @param data
*/
updateInstanceConfigurations = async (data: Partial<IFormattedInstanceConfiguration>) => {
try {
runInAction(() => {
this.loader = true;
this.error = null;
});
const response = await this.instanceService.updateInstanceConfigurations(data);
runInAction(() => {
this.loader = false;
this.error = null;
this.configurations = this.configurations ? [...this.configurations, ...response] : response;
});
return response;
} catch (error) {
runInAction(() => {
this.loader = false;
this.error = error;
});
throw error;
}
};
}

View File

@ -0,0 +1,21 @@
import { action, makeObservable, observable } from "mobx";
export interface IRouterStore {
query: any;
setQuery: (query: any) => void;
}
export class RouterStore implements IRouterStore {
query = {};
constructor() {
makeObservable(this, {
query: observable,
setQuery: action,
});
}
setQuery(query: any) {
this.query = query;
}
}

View File

@ -0,0 +1,65 @@
// mobx
import { action, observable, makeObservable } from "mobx";
// helper
import { applyTheme, unsetCustomCssVariables } from "helpers/theme.helper";
export interface IThemeStore {
theme: string | null;
sidebarCollapsed: boolean | undefined;
toggleSidebar: (collapsed?: boolean) => void;
setTheme: (theme: any) => void;
}
export class ThemeStore implements IThemeStore {
sidebarCollapsed: boolean | undefined = undefined;
theme: string | null = null;
// root store
rootStore;
constructor(_rootStore: any | null = null) {
makeObservable(this, {
// observable
sidebarCollapsed: observable.ref,
theme: observable.ref,
// action
toggleSidebar: action,
setTheme: action,
// computed
});
this.rootStore = _rootStore;
}
toggleSidebar = (collapsed?: boolean) => {
if (collapsed === undefined) {
this.sidebarCollapsed = !this.sidebarCollapsed;
} else {
this.sidebarCollapsed = collapsed;
}
localStorage.setItem("app_sidebar_collapsed", this.sidebarCollapsed.toString());
};
setTheme = async (_theme: { theme: any }) => {
try {
const currentTheme: string = _theme?.theme?.theme?.toString();
// updating the local storage theme value
localStorage.setItem("theme", currentTheme);
// updating the mobx theme value
this.theme = currentTheme;
// applying the theme to platform if the selected theme is custom
if (currentTheme === "custom") {
const themeSettings = this.rootStore.user.currentUserSettings || null;
applyTheme(
themeSettings?.theme?.palette !== ",,,,"
? themeSettings?.theme?.palette
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
themeSettings?.theme?.darkPalette
);
} else unsetCustomCssVariables();
} catch (error) {
console.error("setting user theme error", error);
}
};
}

View File

@ -1,6 +1,7 @@
import { enableStaticRendering } from "mobx-react-lite";
// root stores
import { AppRootStore } from "./application";
import { UserStore } from "./user";
enableStaticRendering(typeof window === "undefined");
@ -14,8 +15,8 @@ export class RootStore {
projectView;
constructor() {
this.app = new AppRootStore();
this.user = new UserRootStore();
this.app = new AppRootStore(this);
this.user = new UserStore(this);
this.workspace = new WorkspaceRootStore();
this.project = new ProjectRootStore();
this.cycle = new CycleRootStore();

252
web/store/user/index.ts Normal file
View File

@ -0,0 +1,252 @@
import { action, observable, runInAction, makeObservable, computed } from "mobx";
// services
import { UserService } from "services/user.service";
import { AuthService } from "services/auth.service";
// interfaces
import { IUser, IUserSettings } from "types/users";
// store
import { RootStore } from "../root.store";
import { UserMembershipStore } from "./user-membership.store";
export interface IUserStore {
loader: boolean;
currentUserError: any;
isUserLoggedIn: boolean | null;
currentUser: IUser | null;
isUserInstanceAdmin: boolean | null;
currentUserSettings: IUserSettings | null;
dashboardInfo: any;
fetchCurrentUser: () => Promise<IUser>;
fetchCurrentUserInstanceAdminStatus: () => Promise<boolean>;
fetchCurrentUserSettings: () => Promise<IUserSettings>;
fetchUserDashboardInfo: (workspaceSlug: string, month: number) => Promise<any>;
updateUserOnBoard: () => Promise<void>;
updateTourCompleted: () => Promise<void>;
updateCurrentUser: (data: Partial<IUser>) => Promise<IUser>;
updateCurrentUserTheme: (theme: string) => Promise<IUser>;
deactivateAccount: () => Promise<void>;
signOut: () => Promise<void>;
membership: UserMembershipStore;
}
export class UserStore implements IUserStore {
loader: boolean = false;
currentUserError: any = null;
isUserLoggedIn: boolean | null = null;
currentUser: IUser | null = null;
isUserInstanceAdmin: boolean | null = null;
currentUserSettings: IUserSettings | null = null;
dashboardInfo: any = null;
membership: UserMembershipStore;
// root store
rootStore;
// services
userService;
authService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
loader: observable.ref,
isUserLoggedIn: observable.ref,
currentUser: observable,
isUserInstanceAdmin: observable.ref,
currentUserSettings: observable,
dashboardInfo: observable,
// action
fetchCurrentUser: action,
fetchCurrentUserInstanceAdminStatus: action,
fetchCurrentUserSettings: action,
fetchUserDashboardInfo: action,
updateUserOnBoard: action,
updateTourCompleted: action,
updateCurrentUser: action,
updateCurrentUserTheme: action,
deactivateAccount: action,
signOut: action,
});
this.rootStore = _rootStore;
this.userService = new UserService();
this.authService = new AuthService();
this.membership = new UserMembershipStore(_rootStore);
}
fetchCurrentUser = async () => {
try {
const response = await this.userService.currentUser();
if (response) {
runInAction(() => {
this.currentUserError = null;
this.currentUser = response;
this.isUserLoggedIn = true;
});
}
return response;
} catch (error) {
runInAction(() => {
this.currentUserError = error;
this.isUserLoggedIn = false;
});
throw error;
}
};
fetchCurrentUserInstanceAdminStatus = async () => {
try {
const response = await this.userService.currentUserInstanceAdminStatus();
if (response) {
runInAction(() => {
this.isUserInstanceAdmin = response.is_instance_admin;
});
}
return response.is_instance_admin;
} catch (error) {
runInAction(() => {
this.isUserInstanceAdmin = false;
});
throw error;
}
};
fetchCurrentUserSettings = async () => {
try {
const response = await this.userService.currentUserSettings();
if (response) {
runInAction(() => {
this.currentUserSettings = response;
});
}
return response;
} catch (error) {
throw error;
}
};
fetchUserDashboardInfo = async (workspaceSlug: string, month: number) => {
try {
const response = await this.userService.userWorkspaceDashboard(workspaceSlug, month);
runInAction(() => {
this.dashboardInfo = response;
});
return response;
} catch (error) {
throw error;
}
};
updateUserOnBoard = async () => {
try {
runInAction(() => {
this.currentUser = {
...this.currentUser,
is_onboarded: true,
} as IUser;
});
const user = this.currentUser ?? undefined;
if (!user) return;
await this.userService.updateUserOnBoard();
} catch (error) {
this.fetchCurrentUser();
throw error;
}
};
updateTourCompleted = async () => {
try {
if (this.currentUser) {
runInAction(() => {
this.currentUser = {
...this.currentUser,
is_tour_completed: true,
} as IUser;
});
const response = await this.userService.updateUserTourCompleted();
return response;
}
} catch (error) {
throw error;
}
};
updateCurrentUser = async (data: Partial<IUser>) => {
try {
runInAction(() => {
this.currentUser = {
...this.currentUser,
...data,
} as IUser;
});
const response = await this.userService.updateUser(data);
runInAction(() => {
this.currentUser = response;
});
return response;
} catch (error) {
this.fetchCurrentUser();
throw error;
}
};
updateCurrentUserTheme = async (theme: string) => {
try {
runInAction(() => {
this.currentUser = {
...this.currentUser,
theme: {
...this.currentUser?.theme,
theme,
},
} as IUser;
});
const response = await this.userService.updateUser({
theme: { ...this.currentUser?.theme, theme },
} as IUser);
return response;
} catch (error) {
throw error;
}
};
deactivateAccount = async () => {
try {
await this.userService.deactivateAccount();
this.currentUserError = null;
this.currentUser = null;
this.isUserLoggedIn = false;
} catch (error) {
throw error;
}
};
signOut = async () => {
try {
await this.authService.signOut();
runInAction(() => {
this.currentUserError = null;
this.currentUser = null;
this.isUserLoggedIn = false;
});
} catch (error) {
throw error;
}
};
}

View File

@ -0,0 +1,229 @@
// mobx
import { action, observable, runInAction, makeObservable, computed } from "mobx";
// services
import { ProjectMemberService, ProjectService } from "services/project";
import { UserService } from "services/user.service";
import { WorkspaceService } from "services/workspace.service";
import { AuthService } from "services/auth.service";
// interfaces
import { IUser, IUserSettings } from "types/users";
import { IWorkspaceMemberMe, IProjectMember, TUserProjectRole, TUserWorkspaceRole } from "types";
import { RootStore } from "../root.store";
export interface IUserMembershipStore {
workspaceMemberInfo: {
[workspaceSlug: string]: IWorkspaceMemberMe;
};
hasPermissionToWorkspace: {
[workspaceSlug: string]: boolean | null;
};
projectMemberInfo: {
[projectId: string]: IProjectMember;
};
hasPermissionToProject: {
[projectId: string]: boolean | null;
};
currentProjectMemberInfo: IProjectMember | undefined;
currentWorkspaceMemberInfo: IWorkspaceMemberMe | undefined;
currentProjectRole: TUserProjectRole | undefined;
currentWorkspaceRole: TUserWorkspaceRole | undefined;
hasPermissionToCurrentWorkspace: boolean | undefined;
hasPermissionToCurrentProject: boolean | undefined;
fetchUserWorkspaceInfo: (workspaceSlug: string) => Promise<IWorkspaceMemberMe>;
fetchUserProjectInfo: (workspaceSlug: string, projectId: string) => Promise<IProjectMember>;
leaveWorkspace: (workspaceSlug: string) => Promise<void>;
joinProject: (workspaceSlug: string, projectIds: string[]) => Promise<any>;
leaveProject: (workspaceSlug: string, projectId: string) => Promise<void>;
}
export class UserMembershipStore implements IUserMembershipStore {
workspaceMemberInfo: {
[workspaceSlug: string]: IWorkspaceMemberMe;
} = {};
hasPermissionToWorkspace: {
[workspaceSlug: string]: boolean;
} = {};
projectMemberInfo: {
[projectId: string]: IProjectMember;
} = {};
hasPermissionToProject: {
[projectId: string]: boolean;
} = {};
// root store
rootStore;
// services
userService;
workspaceService;
projectService;
projectMemberService;
authService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
workspaceMemberInfo: observable.ref,
hasPermissionToWorkspace: observable.ref,
projectMemberInfo: observable.ref,
hasPermissionToProject: observable.ref,
// action
fetchUserWorkspaceInfo: action,
fetchUserProjectInfo: action,
leaveWorkspace: action,
joinProject: action,
leaveProject: action,
// computed
currentProjectMemberInfo: computed,
currentWorkspaceMemberInfo: computed,
currentProjectRole: computed,
currentWorkspaceRole: computed,
hasPermissionToCurrentWorkspace: computed,
hasPermissionToCurrentProject: computed,
});
this.rootStore = _rootStore;
this.userService = new UserService();
this.workspaceService = new WorkspaceService();
this.projectService = new ProjectService();
this.projectMemberService = new ProjectMemberService();
this.authService = new AuthService();
}
get currentWorkspaceMemberInfo() {
if (!this.rootStore.workspace.workspaceSlug) return;
return this.workspaceMemberInfo[this.rootStore.workspace.workspaceSlug];
}
get currentWorkspaceRole() {
if (!this.rootStore.workspace.workspaceSlug) return;
return this.workspaceMemberInfo[this.rootStore.workspace.workspaceSlug]?.role;
}
get currentProjectMemberInfo() {
if (!this.rootStore.project.projectId) return;
return this.projectMemberInfo[this.rootStore.project.projectId];
}
get currentProjectRole() {
if (!this.rootStore.project.projectId) return;
return this.projectMemberInfo[this.rootStore.project.projectId]?.role;
}
get hasPermissionToCurrentWorkspace() {
if (!this.rootStore.workspace.workspaceSlug) return;
return this.hasPermissionToWorkspace[this.rootStore.workspace.workspaceSlug];
}
get hasPermissionToCurrentProject() {
if (!this.rootStore.project.projectId) return;
return this.hasPermissionToProject[this.rootStore.project.projectId];
}
fetchUserWorkspaceInfo = async (workspaceSlug: string) => {
try {
const response = await this.workspaceService.workspaceMemberMe(workspaceSlug);
runInAction(() => {
this.workspaceMemberInfo = {
...this.workspaceMemberInfo,
[workspaceSlug]: response,
};
this.hasPermissionToWorkspace = {
...this.hasPermissionToWorkspace,
[workspaceSlug]: true,
};
});
return response;
} catch (error) {
runInAction(() => {
this.hasPermissionToWorkspace = {
...this.hasPermissionToWorkspace,
[workspaceSlug]: false,
};
});
throw error;
}
};
fetchUserProjectInfo = async (workspaceSlug: string, projectId: string) => {
try {
const response = await this.projectMemberService.projectMemberMe(workspaceSlug, projectId);
runInAction(() => {
this.projectMemberInfo = {
...this.projectMemberInfo,
[projectId]: response,
};
this.hasPermissionToProject = {
...this.hasPermissionToProject,
[projectId]: true,
};
});
return response;
} catch (error: any) {
runInAction(() => {
this.hasPermissionToProject = {
...this.hasPermissionToProject,
[projectId]: false,
};
});
throw error;
}
};
leaveWorkspace = async (workspaceSlug: string) => {
try {
await this.userService.leaveWorkspace(workspaceSlug);
runInAction(() => {
delete this.workspaceMemberInfo[workspaceSlug];
delete this.hasPermissionToWorkspace[workspaceSlug];
});
} catch (error) {
throw error;
}
};
joinProject = async (workspaceSlug: string, projectIds: string[]) => {
const newPermissions: { [projectId: string]: boolean } = {};
projectIds.forEach((projectId) => {
newPermissions[projectId] = true;
});
try {
const response = await this.userService.joinProject(workspaceSlug, projectIds);
runInAction(() => {
this.hasPermissionToProject = {
...this.hasPermissionToProject,
...newPermissions,
};
});
return response;
} catch (error) {
throw error;
}
};
leaveProject = async (workspaceSlug: string, projectId: string) => {
const newPermissions: { [projectId: string]: boolean } = {};
newPermissions[projectId] = false;
try {
await this.userService.leaveProject(workspaceSlug, projectId);
runInAction(() => {
this.hasPermissionToProject = {
...this.hasPermissionToProject,
...newPermissions,
};
});
} catch (error) {
throw error;
}
};
}