New Directory Setup (#2065)
* chore: moved app & space from apps to root * chore: modified workspace configuration * chore: modified dockerfiles for space and web * chore: modified icons for space * feat: updated files for new svg icons supported by next-images * chore: added /spaces base path for next * chore: added compose config for space * chore: updated husky configuration * chore: updated workflows for new configuration * chore: changed app name to web * fix: resolved build errors with web * chore: reset file tracing root for both projects * chore: added nginx config for deploy * fix: eslint and tsconfig settings for space app * husky setup fixes based on new dir * eslint fixes * prettier formatting --------- Co-authored-by: Henit Chobisa <chobisa.henit@gmail.com>
This commit is contained in:
parent
20e36194b4
commit
1e152c666c
1022 changed files with 1475 additions and 1240 deletions
|
|
@ -1,103 +0,0 @@
|
|||
import { observable, action, computed, makeObservable, runInAction, reaction } from "mobx";
|
||||
// services
|
||||
import IssueService from "services/issue.service";
|
||||
// store
|
||||
import { RootStore } from "./root";
|
||||
// types
|
||||
// import { IssueDetailType, TIssueBoardKeys } from "types/issue";
|
||||
import { IIssue, IIssueState, IIssueLabel } from "types/issue";
|
||||
|
||||
export interface IIssueStore {
|
||||
loader: boolean;
|
||||
error: any;
|
||||
// issue options
|
||||
issues: IIssue[] | null;
|
||||
states: IIssueState[] | null;
|
||||
labels: IIssueLabel[] | null;
|
||||
// filtering
|
||||
filteredStates: string[];
|
||||
filteredLabels: string[];
|
||||
filteredPriorities: string[];
|
||||
// service
|
||||
issueService: any;
|
||||
// actions
|
||||
fetchPublicIssues: (workspace_slug: string, project_slug: string, params: any) => void;
|
||||
getCountOfIssuesByState: (state: string) => number;
|
||||
getFilteredIssuesByState: (state: string) => IIssue[];
|
||||
}
|
||||
|
||||
class IssueStore implements IIssueStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
states: IIssueState[] | null = [];
|
||||
labels: IIssueLabel[] | null = [];
|
||||
|
||||
filteredStates: string[] = [];
|
||||
filteredLabels: string[] = [];
|
||||
filteredPriorities: string[] = [];
|
||||
|
||||
issues: IIssue[] | null = [];
|
||||
issue_detail: any = {};
|
||||
|
||||
rootStore: RootStore;
|
||||
issueService: any;
|
||||
|
||||
constructor(_rootStore: any) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable,
|
||||
error: observable,
|
||||
// issue options
|
||||
states: observable.ref,
|
||||
labels: observable.ref,
|
||||
// filtering
|
||||
filteredStates: observable.ref,
|
||||
filteredLabels: observable.ref,
|
||||
filteredPriorities: observable.ref,
|
||||
// issues
|
||||
issues: observable.ref,
|
||||
issue_detail: observable.ref,
|
||||
// actions
|
||||
fetchPublicIssues: action,
|
||||
getFilteredIssuesByState: action,
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.issueService = new IssueService();
|
||||
}
|
||||
|
||||
fetchPublicIssues = async (workspaceSlug: string, projectId: string, params: any) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const response = await this.issueService.getPublicIssues(workspaceSlug, projectId, params);
|
||||
|
||||
if (response) {
|
||||
const _states: IIssueState[] = [...response?.states];
|
||||
const _labels: IIssueLabel[] = [...response?.labels];
|
||||
const _issues: IIssue[] = [...response?.issues];
|
||||
runInAction(() => {
|
||||
this.states = _states;
|
||||
this.labels = _labels;
|
||||
this.issues = _issues;
|
||||
this.loader = false;
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
|
||||
// computed
|
||||
getCountOfIssuesByState(state_id: string): number {
|
||||
return this.issues?.filter((issue) => issue.state == state_id).length || 0;
|
||||
}
|
||||
|
||||
getFilteredIssuesByState = (state_id: string): IIssue[] | [] =>
|
||||
this.issues?.filter((issue) => issue.state == state_id) || [];
|
||||
}
|
||||
|
||||
export default IssueStore;
|
||||
|
|
@ -1,320 +0,0 @@
|
|||
import { makeObservable, observable, action, runInAction } from "mobx";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
// store
|
||||
import { RootStore } from "./root";
|
||||
// services
|
||||
import IssueService from "services/issue.service";
|
||||
import { IIssue, IVote } from "types/issue";
|
||||
|
||||
export type IPeekMode = "side" | "modal" | "full";
|
||||
|
||||
export interface IIssueDetailStore {
|
||||
loader: boolean;
|
||||
error: any;
|
||||
// peek info
|
||||
peekId: string | null;
|
||||
peekMode: IPeekMode;
|
||||
details: {
|
||||
[key: string]: IIssue;
|
||||
};
|
||||
// peek actions
|
||||
setPeekId: (issueId: string | null) => void;
|
||||
setPeekMode: (mode: IPeekMode) => void;
|
||||
// issue details
|
||||
fetchIssueDetails: (workspaceId: string, projectId: string, issueId: string) => void;
|
||||
// issue comments
|
||||
addIssueComment: (workspaceId: string, projectId: string, issueId: string, data: any) => Promise<void>;
|
||||
updateIssueComment: (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
comment_id: string,
|
||||
data: any
|
||||
) => Promise<any>;
|
||||
deleteIssueComment: (workspaceId: string, projectId: string, issueId: string, comment_id: string) => void;
|
||||
// issue reactions
|
||||
addIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
|
||||
removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
|
||||
// issue votes
|
||||
addIssueVote: (workspaceId: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => Promise<void>;
|
||||
removeIssueVote: (workspaceId: string, projectId: string, issueId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
class IssueDetailStore implements IssueDetailStore {
|
||||
loader: boolean = false;
|
||||
error: any = null;
|
||||
peekId: string | null = null;
|
||||
peekMode: IPeekMode = "side";
|
||||
details: {
|
||||
[key: string]: IIssue;
|
||||
} = {};
|
||||
issueService;
|
||||
rootStore: RootStore;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
// peek
|
||||
peekId: observable.ref,
|
||||
peekMode: observable.ref,
|
||||
details: observable.ref,
|
||||
// actions
|
||||
setPeekId: action,
|
||||
fetchIssueDetails: action,
|
||||
setPeekMode: action,
|
||||
});
|
||||
this.issueService = new IssueService();
|
||||
this.rootStore = _rootStore;
|
||||
}
|
||||
|
||||
setPeekId = (issueId: string | null) => {
|
||||
this.peekId = issueId;
|
||||
};
|
||||
|
||||
setPeekMode = (mode: IPeekMode) => {
|
||||
this.peekMode = mode;
|
||||
};
|
||||
|
||||
fetchIssueDetails = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId);
|
||||
const commentsResponse = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
|
||||
|
||||
if (issueDetails) {
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...(this.details[issueId] ?? issueDetails),
|
||||
comments: commentsResponse,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
|
||||
addIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => {
|
||||
try {
|
||||
const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId);
|
||||
const issueCommentResponse = await this.issueService.createIssueComment(workspaceSlug, projectId, issueId, data);
|
||||
if (issueDetails) {
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...issueDetails,
|
||||
comments: [...this.details[issueId].comments, issueCommentResponse],
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
return issueCommentResponse;
|
||||
} catch (error) {
|
||||
console.log("Failed to add issue comment");
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
updateIssueComment = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
commentId: string,
|
||||
data: any
|
||||
) => {
|
||||
try {
|
||||
const issueCommentUpdateResponse = await this.issueService.updateIssueComment(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
commentId,
|
||||
data
|
||||
);
|
||||
|
||||
if (issueCommentUpdateResponse) {
|
||||
const remainingComments = this.details[issueId].comments.filter((com) => com.id != commentId);
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
comments: [...remainingComments, issueCommentUpdateResponse],
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
return issueCommentUpdateResponse;
|
||||
} catch (error) {
|
||||
console.log("Failed to add issue comment");
|
||||
}
|
||||
};
|
||||
|
||||
deleteIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, comment_id: string) => {
|
||||
try {
|
||||
await this.issueService.deleteIssueComment(workspaceSlug, projectId, issueId, comment_id);
|
||||
const remainingComments = this.details[issueId].comments.filter((c) => c.id != comment_id);
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
comments: remainingComments,
|
||||
},
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Failed to add issue vote");
|
||||
}
|
||||
};
|
||||
|
||||
addIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
reactions: [
|
||||
...this.details[issueId].reactions,
|
||||
{
|
||||
id: uuidv4(),
|
||||
issue: issueId,
|
||||
reaction: reactionHex,
|
||||
actor_detail: this.rootStore.user.currentActor,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, {
|
||||
reaction: reactionHex,
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Failed to add issue vote");
|
||||
const issueReactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
reactions: issueReactions,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
removeIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
|
||||
try {
|
||||
const newReactions = this.details[issueId].reactions.filter(
|
||||
(_r) => !(_r.reaction === reactionHex && _r.actor_detail.id === this.rootStore.user.currentUser?.id)
|
||||
);
|
||||
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
reactions: newReactions,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, reactionHex);
|
||||
} catch (error) {
|
||||
console.log("Failed to remove issue reaction");
|
||||
const reactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
reactions: reactions,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
addIssueVote = async (workspaceSlug: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => {
|
||||
const newVote: IVote = {
|
||||
actor: this.rootStore.user.currentUser?.id ?? "",
|
||||
actor_detail: this.rootStore.user.currentActor,
|
||||
issue: issueId,
|
||||
project: projectId,
|
||||
workspace: workspaceSlug,
|
||||
vote: data.vote,
|
||||
};
|
||||
|
||||
const filteredVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);
|
||||
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
votes: [...filteredVotes, newVote],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data);
|
||||
} catch (error) {
|
||||
console.log("Failed to add issue vote");
|
||||
const issueVotes = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
votes: issueVotes,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
removeIssueVote = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
const newVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);
|
||||
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
votes: newVotes,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId);
|
||||
} catch (error) {
|
||||
console.log("Failed to remove issue vote");
|
||||
const issueVotes = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
this.details = {
|
||||
...this.details,
|
||||
[issueId]: {
|
||||
...this.details[issueId],
|
||||
votes: issueVotes,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default IssueDetailStore;
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// mobx
|
||||
import { observable, action, makeObservable, runInAction } from "mobx";
|
||||
// service
|
||||
import ProjectService from "services/project.service";
|
||||
// types
|
||||
import { IWorkspace, IProject, IProjectSettings } from "types/project";
|
||||
|
||||
export interface IProjectStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
workspace: IWorkspace | null;
|
||||
project: IProject | null;
|
||||
deploySettings: IProjectSettings | null;
|
||||
viewOptions: any;
|
||||
activeBoard: string | null;
|
||||
fetchProjectSettings: (workspace_slug: string, project_slug: string) => Promise<void>;
|
||||
setActiveBoard: (value: string) => void;
|
||||
}
|
||||
|
||||
class ProjectStore implements IProjectStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
// data
|
||||
workspace: IWorkspace | null = null;
|
||||
project: IProject | null = null;
|
||||
deploySettings: IProjectSettings | null = null;
|
||||
viewOptions: any = null;
|
||||
activeBoard: string | null = null;
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
projectService;
|
||||
|
||||
constructor(_rootStore: any | null = null) {
|
||||
makeObservable(this, {
|
||||
// loaders and error observables
|
||||
loader: observable,
|
||||
error: observable.ref,
|
||||
// observable
|
||||
workspace: observable.ref,
|
||||
project: observable.ref,
|
||||
deploySettings: observable.ref,
|
||||
viewOptions: observable.ref,
|
||||
activeBoard: observable.ref,
|
||||
// actions
|
||||
fetchProjectSettings: action,
|
||||
setActiveBoard: action,
|
||||
// computed
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.projectService = new ProjectService();
|
||||
}
|
||||
|
||||
fetchProjectSettings = async (workspace_slug: string, project_slug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const response = await this.projectService.getProjectSettings(workspace_slug, project_slug);
|
||||
|
||||
if (response) {
|
||||
const _project: IProject = { ...response?.project_details };
|
||||
const _workspace: IWorkspace = { ...response?.workspace_detail };
|
||||
const _viewOptions = { ...response?.views };
|
||||
const _deploySettings = { ...response };
|
||||
runInAction(() => {
|
||||
this.project = _project;
|
||||
this.workspace = _workspace;
|
||||
this.viewOptions = _viewOptions;
|
||||
this.deploySettings = _deploySettings;
|
||||
this.loader = false;
|
||||
});
|
||||
}
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
setActiveBoard = (boardValue: string) => {
|
||||
this.activeBoard = boardValue;
|
||||
};
|
||||
}
|
||||
|
||||
export default ProjectStore;
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// mobx lite
|
||||
import { enableStaticRendering } from "mobx-react-lite";
|
||||
// store imports
|
||||
import UserStore from "./user";
|
||||
import IssueStore, { IIssueStore } from "./issue";
|
||||
import ProjectStore, { IProjectStore } from "./project";
|
||||
import IssueDetailStore, { IIssueDetailStore } from "./issue_details";
|
||||
|
||||
enableStaticRendering(typeof window === "undefined");
|
||||
|
||||
export class RootStore {
|
||||
user: UserStore;
|
||||
issue: IIssueStore;
|
||||
issueDetails: IIssueDetailStore;
|
||||
project: IProjectStore;
|
||||
|
||||
constructor() {
|
||||
this.user = new UserStore(this);
|
||||
this.issue = new IssueStore(this);
|
||||
this.project = new ProjectStore(this);
|
||||
this.issueDetails = new IssueDetailStore(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
// mobx
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// service
|
||||
import UserService from "services/user.service";
|
||||
import { ActorDetail } from "types/issue";
|
||||
// types
|
||||
import { IUser } from "types/user";
|
||||
|
||||
export interface IUserStore {
|
||||
currentUser: any | null;
|
||||
fetchCurrentUser: () => void;
|
||||
currentActor: () => any;
|
||||
}
|
||||
|
||||
class UserStore implements IUserStore {
|
||||
currentUser: IUser | null = null;
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
userService;
|
||||
|
||||
constructor(_rootStore: any) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
currentUser: observable.ref,
|
||||
// actions
|
||||
setCurrentUser: action,
|
||||
// computed
|
||||
currentActor: computed,
|
||||
});
|
||||
this.rootStore = _rootStore;
|
||||
this.userService = new UserService();
|
||||
}
|
||||
|
||||
setCurrentUser = (user: any) => {
|
||||
runInAction(() => {
|
||||
this.currentUser = { ...user };
|
||||
});
|
||||
};
|
||||
|
||||
get currentActor(): any {
|
||||
return {
|
||||
avatar: this.currentUser?.avatar,
|
||||
display_name: this.currentUser?.display_name,
|
||||
first_name: this.currentUser?.first_name,
|
||||
id: this.currentUser?.id,
|
||||
is_bot: false,
|
||||
last_name: this.currentUser?.last_name,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param callback
|
||||
* @description A wrapper function to check user authentication; it redirects to the login page if not authenticated, otherwise, it executes a callback.
|
||||
* @example this.requiredLogin(() => { // do something });
|
||||
*/
|
||||
|
||||
requiredLogin = (callback: () => void) => {
|
||||
if (this.currentUser) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
this.fetchCurrentUser()
|
||||
.then(() => {
|
||||
if (!this.currentUser) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `/?next_path=${currentPath}`;
|
||||
} else callback();
|
||||
})
|
||||
.catch(() => {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.href = `/?next_path=${currentPath}`;
|
||||
});
|
||||
};
|
||||
|
||||
fetchCurrentUser = async () => {
|
||||
try {
|
||||
const response = await this.userService.currentUser();
|
||||
if (response) {
|
||||
runInAction(() => {
|
||||
this.currentUser = response;
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch current user", error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default UserStore;
|
||||
Loading…
Add table
Add a link
Reference in a new issue