mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
Merge pull request #2059 from makeplane/develop
Promote: Develop to Stage Release
This commit is contained in:
commit
c1102180e6
@ -32,19 +32,11 @@ class Migration(migrations.Migration):
|
|||||||
field=models.CharField(blank=True, max_length=255, null=True),
|
field=models.CharField(blank=True, max_length=255, null=True),
|
||||||
),
|
),
|
||||||
migrations.RunPython(update_user_timezones),
|
migrations.RunPython(update_user_timezones),
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='issuevote',
|
|
||||||
unique_together=set(),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='issuevote',
|
model_name='issuevote',
|
||||||
name='vote',
|
name='vote',
|
||||||
field=models.IntegerField(choices=[(-1, 'DOWNVOTE'), (1, 'UPVOTE')], default=1),
|
field=models.IntegerField(choices=[(-1, 'DOWNVOTE'), (1, 'UPVOTE')], default=1),
|
||||||
),
|
),
|
||||||
migrations.AlterUniqueTogether(
|
|
||||||
name='issuevote',
|
|
||||||
unique_together={('issue', 'actor', 'vote')},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='ProjectPublicMember',
|
name='ProjectPublicMember',
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -481,7 +481,7 @@ class IssueVote(ProjectBaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ["issue", "actor", "vote"]
|
unique_together = ["issue", "actor",]
|
||||||
verbose_name = "Issue Vote"
|
verbose_name = "Issue Vote"
|
||||||
verbose_name_plural = "Issue Votes"
|
verbose_name_plural = "Issue Votes"
|
||||||
db_table = "issue_votes"
|
db_table = "issue_votes"
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
import { issueGroupFilter } from "constants/data";
|
import { issueGroupFilter } from "constants/data";
|
||||||
|
|
||||||
@ -8,8 +6,8 @@ export const IssueBlockState = ({ state }: any) => {
|
|||||||
|
|
||||||
if (stateGroup === null) return <></>;
|
if (stateGroup === null) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between gap-1 w-full rounded shadow-sm border-[0.5px] border-custom-border-300 duration-300 focus:outline-none px-2.5 py-1 text-xs cursor-pointer hover:bg-custom-background-80">
|
<div className="flex items-center justify-between gap-1 w-full rounded shadow-sm border-[0.5px] border-custom-border-300 duration-300 focus:outline-none px-2.5 py-1 text-xs">
|
||||||
<div className="flex items-center cursor-pointer w-full gap-1.5 text-custom-text-200">
|
<div className="flex items-center w-full gap-1.5 text-custom-text-200">
|
||||||
<stateGroup.icon />
|
<stateGroup.icon />
|
||||||
<div className="text-xs">{state?.name}</div>
|
<div className="text-xs">{state?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,6 +14,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
|||||||
import { IIssue } from "types/issue";
|
import { IIssue } from "types/issue";
|
||||||
// store
|
// store
|
||||||
import { RootStore } from "store/root";
|
import { RootStore } from "store/root";
|
||||||
|
import { IssueVotes } from "components/issues/peek-overview";
|
||||||
|
|
||||||
export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
|
export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
|
||||||
const { issue } = props;
|
const { issue } = props;
|
||||||
@ -56,19 +57,6 @@ export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="inline-flex flex-shrink-0 items-center gap-2 text-xs">
|
<div className="inline-flex flex-shrink-0 items-center gap-2 text-xs">
|
||||||
{projectStore.deploySettings?.votes && (
|
|
||||||
<>
|
|
||||||
{/* upvotes */}
|
|
||||||
<div className="flex-shrink-0">
|
|
||||||
<IssueBlockUpVotes number={totalUpVotes.length} />
|
|
||||||
</div>
|
|
||||||
{/* downotes */}
|
|
||||||
<div className="flex-shrink-0">
|
|
||||||
<IssueBlockDownVotes number={totalDownVotes.length} />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* priority */}
|
{/* priority */}
|
||||||
{issue?.priority && (
|
{issue?.priority && (
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
|
@ -1,25 +1,32 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
// next theme
|
// next theme
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
|
|
||||||
// mobx react lite
|
// mobx react lite
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export const NavbarTheme = observer(() => {
|
export const NavbarTheme = observer(() => {
|
||||||
|
const [appTheme, setAppTheme] = useState("light");
|
||||||
|
|
||||||
const { setTheme, theme } = useTheme();
|
const { setTheme, theme } = useTheme();
|
||||||
|
|
||||||
const handleTheme = () => {
|
const handleTheme = () => {
|
||||||
setTheme(theme === "light" ? "dark" : "light");
|
setTheme(theme === "light" ? "dark" : "light");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!theme) return;
|
||||||
|
|
||||||
|
setAppTheme(theme);
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleTheme}
|
onClick={handleTheme}
|
||||||
className="relative w-7 h-7 grid place-items-center bg-custom-background-100 hover:bg-custom-background-80 text-custom-text-100 rounded"
|
className="relative w-7 h-7 grid place-items-center bg-custom-background-100 hover:bg-custom-background-80 text-custom-text-100 rounded"
|
||||||
>
|
>
|
||||||
<span className="material-symbols-rounded text-sm">{theme === "light" ? "dark_mode" : "light_mode"}</span>
|
<span className="material-symbols-rounded text-sm">{appTheme === "light" ? "dark_mode" : "light_mode"}</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -61,8 +61,8 @@ export const CommentCard: React.FC<Props> = observer((props) => {
|
|||||||
) : (
|
) : (
|
||||||
<div className={`grid h-7 w-7 place-items-center rounded-full border-2 border-white bg-gray-500 text-white`}>
|
<div className={`grid h-7 w-7 place-items-center rounded-full border-2 border-white bg-gray-500 text-white`}>
|
||||||
{comment.actor_detail.is_bot
|
{comment.actor_detail.is_bot
|
||||||
? comment.actor_detail.first_name.charAt(0)
|
? comment?.actor_detail?.first_name?.charAt(0)
|
||||||
: comment.actor_detail.display_name.charAt(0)}
|
: comment?.actor_detail?.display_name?.charAt(0)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ export const PeekOverviewHeader: React.FC<Props> = (props) => {
|
|||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{issueDetailStore.peekMode === "side" && (
|
{issueDetailStore.peekMode === "side" && (
|
||||||
<button type="button" onClick={handleClose} autoFocus={false}>
|
<button type="button" onClick={handleClose}>
|
||||||
<East
|
<East
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: "14px",
|
fontSize: "14px",
|
||||||
@ -134,7 +134,7 @@ export const PeekOverviewHeader: React.FC<Props> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
{(issueDetailStore.peekMode === "side" || issueDetailStore.peekMode === "modal") && (
|
{(issueDetailStore.peekMode === "side" || issueDetailStore.peekMode === "modal") && (
|
||||||
<div className="flex items-center gap-2 flex-shrink-0">
|
<div className="flex items-center gap-2 flex-shrink-0">
|
||||||
<button type="button" onClick={handleCopyLink} className="-rotate-45">
|
<button type="button" onClick={handleCopyLink} className="-rotate-45 focus:outline-none" tabIndex={1}>
|
||||||
<Icon iconName="link" />
|
<Icon iconName="link" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,7 +47,7 @@ export const PeekOverviewIssueActivity: React.FC<Props> = observer((props) => {
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="bg-custom-background-80 px-2 py-2.5 flex items-center justify-between gap-2 border border-custom-border-300 rounded">
|
<div className="bg-custom-background-80 px-2 py-2.5 flex items-center justify-between gap-2 border border-custom-border-300 rounded mt-4">
|
||||||
<p className="flex gap-2 text-sm text-custom-text-200 break-words overflow-hidden">
|
<p className="flex gap-2 text-sm text-custom-text-200 break-words overflow-hidden">
|
||||||
<Icon iconName="lock" className="!text-sm" />
|
<Icon iconName="lock" className="!text-sm" />
|
||||||
Sign in to add your comment
|
Sign in to add your comment
|
||||||
|
@ -24,9 +24,7 @@ export const IssueEmojiReactions: React.FC = observer(() => {
|
|||||||
if (!workspace_slug || !project_slug || !issueId) return;
|
if (!workspace_slug || !project_slug || !issueId) return;
|
||||||
const userReaction = reactions?.find((r) => r.actor_detail.id === user?.id && r.reaction === reactionHex);
|
const userReaction = reactions?.find((r) => r.actor_detail.id === user?.id && r.reaction === reactionHex);
|
||||||
if (userReaction) return;
|
if (userReaction) return;
|
||||||
issueDetailsStore.addIssueReaction(workspace_slug.toString(), project_slug.toString(), issueId, {
|
issueDetailsStore.addIssueReaction(workspace_slug.toString(), project_slug.toString(), issueId, reactionHex);
|
||||||
reaction: reactionHex,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleReactionClick = (reactionHex: string) => {
|
const handleReactionClick = (reactionHex: string) => {
|
||||||
@ -57,6 +55,7 @@ export const IssueEmojiReactions: React.FC = observer(() => {
|
|||||||
if (reactions.length > 0)
|
if (reactions.length > 0)
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
|
key={reaction}
|
||||||
tooltipContent={
|
tooltipContent={
|
||||||
<div>
|
<div>
|
||||||
{reactions
|
{reactions
|
||||||
@ -74,7 +73,6 @@ export const IssueEmojiReactions: React.FC = observer(() => {
|
|||||||
handleReactionClick(reaction);
|
handleReactionClick(reaction);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
key={reaction}
|
|
||||||
className={`flex items-center gap-1 text-custom-text-100 text-sm h-full px-2 py-1 rounded-md ${
|
className={`flex items-center gap-1 text-custom-text-100 text-sm h-full px-2 py-1 rounded-md ${
|
||||||
reactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
|
reactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
|
||||||
? "bg-custom-primary-100/10"
|
? "bg-custom-primary-100/10"
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { makeObservable, observable, action, runInAction } from "mobx";
|
import { makeObservable, observable, action, runInAction } from "mobx";
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
// store
|
// store
|
||||||
import { RootStore } from "./root";
|
import { RootStore } from "./root";
|
||||||
// services
|
// services
|
||||||
import IssueService from "services/issue.service";
|
import IssueService from "services/issue.service";
|
||||||
import { IIssue } from "types/issue";
|
import { IIssue, IVote } from "types/issue";
|
||||||
|
|
||||||
export type IPeekMode = "side" | "modal" | "full";
|
export type IPeekMode = "side" | "modal" | "full";
|
||||||
|
|
||||||
@ -32,8 +33,8 @@ export interface IIssueDetailStore {
|
|||||||
) => Promise<any>;
|
) => Promise<any>;
|
||||||
deleteIssueComment: (workspaceId: string, projectId: string, issueId: string, comment_id: string) => void;
|
deleteIssueComment: (workspaceId: string, projectId: string, issueId: string, comment_id: string) => void;
|
||||||
// issue reactions
|
// issue reactions
|
||||||
addIssueReaction: (workspaceId: string, projectId: string, issueId: string, data: any) => void;
|
addIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
|
||||||
removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionId: string) => void;
|
removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
|
||||||
// issue votes
|
// issue votes
|
||||||
addIssueVote: (workspaceId: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => Promise<void>;
|
addIssueVote: (workspaceId: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => Promise<void>;
|
||||||
removeIssueVote: (workspaceId: string, projectId: string, issueId: string) => Promise<void>;
|
removeIssueVote: (workspaceId: string, projectId: string, issueId: string) => Promise<void>;
|
||||||
@ -88,7 +89,7 @@ class IssueDetailStore implements IssueDetailStore {
|
|||||||
this.details = {
|
this.details = {
|
||||||
...this.details,
|
...this.details,
|
||||||
[issueId]: {
|
[issueId]: {
|
||||||
...issueDetails,
|
...(this.details[issueId] ?? issueDetails),
|
||||||
comments: commentsResponse,
|
comments: commentsResponse,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -174,84 +175,144 @@ class IssueDetailStore implements IssueDetailStore {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
addIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => {
|
addIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
|
||||||
try {
|
try {
|
||||||
const issueVoteResponse = await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, data);
|
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,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
if (issueVoteResponse) {
|
await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, {
|
||||||
runInAction(() => {
|
reaction: reactionHex,
|
||||||
this.details = {
|
});
|
||||||
...this.details,
|
|
||||||
[issueId]: {
|
|
||||||
...this.details[issueId],
|
|
||||||
reactions: [...this.details[issueId].reactions, issueVoteResponse],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Failed to add issue vote");
|
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, reactionId: string) => {
|
removeIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
|
||||||
try {
|
try {
|
||||||
await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, reactionId);
|
const newReactions = this.details[issueId].reactions.filter(
|
||||||
const reactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
|
(_r) => !(_r.reaction === reactionHex && _r.actor_detail.id === this.rootStore.user.currentUser?.id)
|
||||||
|
);
|
||||||
|
|
||||||
if (reactions) {
|
runInAction(() => {
|
||||||
runInAction(() => {
|
this.details = {
|
||||||
this.details = {
|
...this.details,
|
||||||
...this.details,
|
[issueId]: {
|
||||||
[issueId]: {
|
...this.details[issueId],
|
||||||
...this.details[issueId],
|
reactions: newReactions,
|
||||||
reactions: reactions,
|
},
|
||||||
},
|
};
|
||||||
};
|
});
|
||||||
});
|
|
||||||
}
|
await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, reactionHex);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Failed to remove issue reaction");
|
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 }) => {
|
addIssueVote = async (workspaceSlug: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => {
|
||||||
try {
|
const newVote: IVote = {
|
||||||
const issueVoteResponse = await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data);
|
actor: this.rootStore.user.currentUser?.id ?? "",
|
||||||
const issueDetails = await this.issueService.getIssueById(workspaceSlug, projectId, issueId);
|
actor_detail: this.rootStore.user.currentActor,
|
||||||
|
issue: issueId,
|
||||||
|
project: projectId,
|
||||||
|
workspace: workspaceSlug,
|
||||||
|
vote: data.vote,
|
||||||
|
};
|
||||||
|
|
||||||
if (issueVoteResponse) {
|
const filteredVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);
|
||||||
runInAction(() => {
|
|
||||||
this.details = {
|
try {
|
||||||
...this.details,
|
runInAction(() => {
|
||||||
[issueId]: {
|
this.details = {
|
||||||
...issueDetails,
|
...this.details,
|
||||||
},
|
[issueId]: {
|
||||||
};
|
...this.details[issueId],
|
||||||
});
|
votes: [...filteredVotes, newVote],
|
||||||
}
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Failed to add issue vote");
|
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) => {
|
removeIssueVote = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||||
try {
|
const newVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);
|
||||||
await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId);
|
|
||||||
const issueDetails = await this.issueService.getIssueById(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (issueDetails) {
|
try {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.details = {
|
this.details = {
|
||||||
...this.details,
|
...this.details,
|
||||||
[issueId]: {
|
[issueId]: {
|
||||||
...issueDetails,
|
...this.details[issueId],
|
||||||
},
|
votes: newVotes,
|
||||||
};
|
},
|
||||||
});
|
};
|
||||||
}
|
});
|
||||||
|
|
||||||
|
await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Failed to remove issue vote");
|
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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,566 +0,0 @@
|
|||||||
// mobx
|
|
||||||
import { observable, action, computed, makeObservable, runInAction, reaction } from "mobx";
|
|
||||||
// service
|
|
||||||
import IssueService from "services/issue.service";
|
|
||||||
// types
|
|
||||||
import { IssueDetailType, TIssueBoardKeys, IIssueLabel, IIssueState, IIssue } from "types/issue";
|
|
||||||
|
|
||||||
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 IssueLegacyStore {
|
|
||||||
currentIssueBoardView: TIssueBoardKeys | null = null;
|
|
||||||
|
|
||||||
loader: boolean = false;
|
|
||||||
error: any | null = null;
|
|
||||||
|
|
||||||
states: IIssueState[] | null = null;
|
|
||||||
labels: IIssueLabel[] | null = null;
|
|
||||||
issues: IIssue[] | null = null;
|
|
||||||
|
|
||||||
issue_detail: IssueDetailType = {};
|
|
||||||
|
|
||||||
activePeekOverviewIssueId: string | null = null;
|
|
||||||
|
|
||||||
userSelectedStates: string[] = [];
|
|
||||||
userSelectedLabels: string[] = [];
|
|
||||||
userSelectedPriorities: string[] = [];
|
|
||||||
// root store
|
|
||||||
rootStore;
|
|
||||||
// service
|
|
||||||
issueService;
|
|
||||||
|
|
||||||
constructor(_rootStore: any) {
|
|
||||||
makeObservable(this, {
|
|
||||||
// observable
|
|
||||||
currentIssueBoardView: observable,
|
|
||||||
|
|
||||||
loader: observable,
|
|
||||||
error: observable,
|
|
||||||
|
|
||||||
states: observable.ref,
|
|
||||||
labels: observable.ref,
|
|
||||||
issues: observable.ref,
|
|
||||||
issue_detail: observable.ref,
|
|
||||||
|
|
||||||
activePeekOverviewIssueId: observable.ref,
|
|
||||||
|
|
||||||
userSelectedStates: observable.ref,
|
|
||||||
userSelectedLabels: observable.ref,
|
|
||||||
userSelectedPriorities: observable.ref,
|
|
||||||
// action
|
|
||||||
setCurrentIssueBoardView: action,
|
|
||||||
fetchPublicIssues: action,
|
|
||||||
// computed
|
|
||||||
});
|
|
||||||
|
|
||||||
this.rootStore = _rootStore;
|
|
||||||
this.issueService = new IssueService();
|
|
||||||
}
|
|
||||||
|
|
||||||
// computed
|
|
||||||
getCountOfIssuesByState(state_id: string): number {
|
|
||||||
return this.issues?.filter((issue) => issue.state == state_id).length || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
getFilteredIssuesByState(state_id: string): IIssue[] | [] {
|
|
||||||
return this.issues?.filter((issue) => issue.state == state_id) || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
setActivePeekOverviewIssueId = (issueId: string | null) => (this.activePeekOverviewIssueId = issueId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param key Is the key of the filter, i.e. state, label, priority
|
|
||||||
* @param value Is the value of the filter, i.e. state_id, label_id, priority
|
|
||||||
* @returns boolean
|
|
||||||
*/
|
|
||||||
|
|
||||||
getUserSelectedFilter(key: "state" | "priority" | "label", value: string): boolean {
|
|
||||||
if (key == "state") {
|
|
||||||
return this.userSelectedStates.includes(value);
|
|
||||||
} else if (key == "label") {
|
|
||||||
return this.userSelectedLabels.includes(value);
|
|
||||||
} else if (key == "priority") {
|
|
||||||
return this.userSelectedPriorities.includes(value);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checkIfFilterExistsForKey: (key: "state" | "priority" | "label") => boolean = (key) => {
|
|
||||||
if (key == "state") {
|
|
||||||
return this.userSelectedStates.length > 0;
|
|
||||||
} else if (key == "label") {
|
|
||||||
return this.userSelectedLabels.length > 0;
|
|
||||||
} else if (key == "priority") {
|
|
||||||
return this.userSelectedPriorities.length > 0;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
clearUserSelectedFilter(key: "state" | "priority" | "label" | "all") {
|
|
||||||
if (key == "state") {
|
|
||||||
this.userSelectedStates = [];
|
|
||||||
} else if (key == "label") {
|
|
||||||
this.userSelectedLabels = [];
|
|
||||||
} else if (key == "priority") {
|
|
||||||
this.userSelectedPriorities = [];
|
|
||||||
} else if (key == "all") {
|
|
||||||
this.userSelectedStates = [];
|
|
||||||
this.userSelectedLabels = [];
|
|
||||||
this.userSelectedPriorities = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getIfFiltersIsEmpty: () => boolean = () =>
|
|
||||||
this.userSelectedStates.length === 0 &&
|
|
||||||
this.userSelectedLabels.length === 0 &&
|
|
||||||
this.userSelectedPriorities.length === 0;
|
|
||||||
|
|
||||||
getURLDefinition = (
|
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
action?: {
|
|
||||||
key: "state" | "priority" | "label" | "all";
|
|
||||||
value?: string;
|
|
||||||
removeAll?: boolean;
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
let url = `/${workspaceSlug}/${projectId}?board=${this.currentIssueBoardView}`;
|
|
||||||
|
|
||||||
if (action) {
|
|
||||||
if (action.key === "state")
|
|
||||||
this.userSelectedStates = action.removeAll
|
|
||||||
? []
|
|
||||||
: [...this.userSelectedStates].filter((state) => state !== action.value);
|
|
||||||
if (action.key === "label")
|
|
||||||
this.userSelectedLabels = action.removeAll
|
|
||||||
? []
|
|
||||||
: [...this.userSelectedLabels].filter((label) => label !== action.value);
|
|
||||||
if (action.key === "priority")
|
|
||||||
this.userSelectedPriorities = action.removeAll
|
|
||||||
? []
|
|
||||||
: [...this.userSelectedPriorities].filter((priority) => priority !== action.value);
|
|
||||||
if (action.key === "all") {
|
|
||||||
this.userSelectedStates = [];
|
|
||||||
this.userSelectedLabels = [];
|
|
||||||
this.userSelectedPriorities = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.checkIfFilterExistsForKey("state")) {
|
|
||||||
url += `&states=${this.userSelectedStates.join(",")}`;
|
|
||||||
}
|
|
||||||
if (this.checkIfFilterExistsForKey("label")) {
|
|
||||||
url += `&labels=${this.userSelectedLabels.join(",")}`;
|
|
||||||
}
|
|
||||||
if (this.checkIfFilterExistsForKey("priority")) {
|
|
||||||
url += `&priorities=${this.userSelectedPriorities.join(",")}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
};
|
|
||||||
|
|
||||||
// action
|
|
||||||
setCurrentIssueBoardView = async (view: TIssueBoardKeys) => {
|
|
||||||
this.currentIssueBoardView = view;
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
getIssueByIdAsync = async (workspaceSlug: string, projectId: string, issueId: string): Promise<IssueDetailType> => {
|
|
||||||
try {
|
|
||||||
const response = this.issues?.find((issue) => issue.id === issueId);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
issue: response,
|
|
||||||
comments: [],
|
|
||||||
reactions: [],
|
|
||||||
votes: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.getIssueReactionsAsync(workspaceSlug, projectId, issueId);
|
|
||||||
this.getIssueVotesAsync(workspaceSlug, projectId, issueId);
|
|
||||||
this.getIssueCommentsAsync(workspaceSlug, projectId, issueId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.issue_detail[issueId] as any;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
getIssueVotesAsync = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
|
||||||
try {
|
|
||||||
const response = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
votes: response,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
createIssueVoteAsync = async (
|
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
issueId: string,
|
|
||||||
data: {
|
|
||||||
vote: 1 | -1;
|
|
||||||
}
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const response = await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
votes: [
|
|
||||||
...{ ...this.issue_detail }[issueId].votes.filter(
|
|
||||||
(vote) => vote.actor !== this.rootStore?.user?.currentUser?.id
|
|
||||||
),
|
|
||||||
response,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteIssueVoteAsync = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
|
||||||
try {
|
|
||||||
const _votes = (this.issue_detail[issueId].votes = this.issue_detail[issueId].votes.filter(
|
|
||||||
(vote) => vote.actor !== this.rootStore?.user?.user?.id
|
|
||||||
));
|
|
||||||
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail[issueId].votes = _votes;
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
const votesAfterCall = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (votesAfterCall)
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail[issueId].votes = votesAfterCall;
|
|
||||||
});
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
getIssueReactionsAsync = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
|
||||||
try {
|
|
||||||
const response = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
reactions: response,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
createIssueReactionAsync = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => {
|
|
||||||
try {
|
|
||||||
const response = await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, data);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
reactions: [...this.issue_detail[issueId].reactions, response],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteIssueReactionAsync = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
|
|
||||||
try {
|
|
||||||
const newReactionsList = this.issue_detail[issueId].reactions.filter(
|
|
||||||
(reaction) => reaction.reaction !== reactionHex
|
|
||||||
);
|
|
||||||
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
reactions: newReactionsList,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, reactionHex);
|
|
||||||
|
|
||||||
const reactionsAfterCall = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (reactionsAfterCall) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
reactions: reactionsAfterCall,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
getIssueCommentsAsync = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
|
||||||
try {
|
|
||||||
const response = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
comments: response,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
createIssueCommentAsync = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => {
|
|
||||||
try {
|
|
||||||
const response = await this.issueService.createIssueComment(workspaceSlug, projectId, issueId, data);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
comments: [...this.issue_detail[issueId].comments, response],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updateIssueCommentAsync = async (
|
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
issueId: string,
|
|
||||||
commentId: string,
|
|
||||||
data: any
|
|
||||||
) => {
|
|
||||||
try {
|
|
||||||
const response = await this.issueService.updateIssueComment(workspaceSlug, projectId, issueId, commentId, data);
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
comments: [
|
|
||||||
...this.issue_detail[issueId].comments.filter((comment) => comment.id !== response.id),
|
|
||||||
response,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteIssueCommentAsync = async (workspaceSlug: string, projectId: string, issueId: string, commentId: string) => {
|
|
||||||
try {
|
|
||||||
const newCommentsList = this.issue_detail[issueId].comments.filter((comment) => comment.id !== commentId);
|
|
||||||
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
comments: newCommentsList,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await this.issueService.deleteIssueComment(workspaceSlug, projectId, issueId, commentId);
|
|
||||||
|
|
||||||
const commentsAfterCall = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
|
|
||||||
|
|
||||||
if (commentsAfterCall) {
|
|
||||||
const _issue_detail = {
|
|
||||||
...this.issue_detail,
|
|
||||||
[issueId]: {
|
|
||||||
...this.issue_detail[issueId],
|
|
||||||
comments: commentsAfterCall,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
runInAction(() => {
|
|
||||||
this.issue_detail = _issue_detail;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
this.loader = false;
|
|
||||||
this.error = error;
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default IssueLegacyStore;
|
|
@ -2,14 +2,18 @@
|
|||||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||||
// service
|
// service
|
||||||
import UserService from "services/user.service";
|
import UserService from "services/user.service";
|
||||||
|
import { ActorDetail } from "types/issue";
|
||||||
|
// types
|
||||||
|
import { IUser } from "types/user";
|
||||||
|
|
||||||
export interface IUserStore {
|
export interface IUserStore {
|
||||||
currentUser: any | null;
|
currentUser: any | null;
|
||||||
fetchCurrentUser: () => void;
|
fetchCurrentUser: () => void;
|
||||||
|
currentActor: () => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserStore implements IUserStore {
|
class UserStore implements IUserStore {
|
||||||
currentUser: any | null = null;
|
currentUser: IUser | null = null;
|
||||||
// root store
|
// root store
|
||||||
rootStore;
|
rootStore;
|
||||||
// service
|
// service
|
||||||
@ -22,6 +26,7 @@ class UserStore implements IUserStore {
|
|||||||
// actions
|
// actions
|
||||||
setCurrentUser: action,
|
setCurrentUser: action,
|
||||||
// computed
|
// computed
|
||||||
|
currentActor: computed,
|
||||||
});
|
});
|
||||||
this.rootStore = _rootStore;
|
this.rootStore = _rootStore;
|
||||||
this.userService = new UserService();
|
this.userService = new UserService();
|
||||||
@ -33,6 +38,17 @@ class UserStore implements IUserStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
* @param callback
|
||||||
|
@ -42,14 +42,7 @@ export interface IIssue {
|
|||||||
state: string;
|
state: string;
|
||||||
state_detail: any;
|
state_detail: any;
|
||||||
target_date: any;
|
target_date: any;
|
||||||
votes: {
|
votes: IVote[];
|
||||||
issue: string;
|
|
||||||
vote: -1 | 1;
|
|
||||||
workspace: string;
|
|
||||||
project: string;
|
|
||||||
actor: string;
|
|
||||||
actor_detail: ActorDetail;
|
|
||||||
}[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IIssueState {
|
export interface IIssueState {
|
||||||
@ -65,6 +58,15 @@ export interface IIssueLabel {
|
|||||||
color: string;
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IVote {
|
||||||
|
issue: string;
|
||||||
|
vote: -1 | 1;
|
||||||
|
workspace: string;
|
||||||
|
project: string;
|
||||||
|
actor: string;
|
||||||
|
actor_detail: ActorDetail;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Comment {
|
export interface Comment {
|
||||||
id: string;
|
id: string;
|
||||||
actor_detail: ActorDetail;
|
actor_detail: ActorDetail;
|
||||||
@ -95,12 +97,12 @@ export interface IIssueReaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ActorDetail {
|
export interface ActorDetail {
|
||||||
avatar: string;
|
avatar?: string;
|
||||||
display_name: string;
|
display_name?: string;
|
||||||
first_name: string;
|
first_name?: string;
|
||||||
id: string;
|
id?: string;
|
||||||
is_bot: boolean;
|
is_bot?: boolean;
|
||||||
last_name: string;
|
last_name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IssueDetail {
|
export interface IssueDetail {
|
||||||
|
@ -1,3 +1,23 @@
|
|||||||
export interface IUser {
|
export interface IUser {
|
||||||
|
avatar: string;
|
||||||
|
cover_image: string | null;
|
||||||
|
created_at: Date;
|
||||||
|
created_location: string;
|
||||||
|
date_joined: Date;
|
||||||
|
email: string;
|
||||||
|
display_name: string;
|
||||||
first_name: string;
|
first_name: string;
|
||||||
|
id: string;
|
||||||
|
is_email_verified: boolean;
|
||||||
|
is_onboarded: boolean;
|
||||||
|
is_tour_completed: boolean;
|
||||||
|
last_location: string;
|
||||||
|
last_login: Date;
|
||||||
|
last_name: string;
|
||||||
|
mobile_number: string;
|
||||||
|
role: string;
|
||||||
|
token: string;
|
||||||
|
updated_at: Date;
|
||||||
|
username: string;
|
||||||
|
user_timezone: string;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user