mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
feat: event tracking using posthog and created application provider to render multiple wrappers (#2757)
* fix: event tracker changes * fix: App provider implementation using wrappers * fix: updating packages * fix: handling warning * fix: wrapper fixes and minor optimization changes * fix: chore app-provider clearnup * fix: cleanup * fix: removing jitsu tracking * fix: minor updates * fix: adding event to posthog event tracker (#2802) * dev: posthog event tracker update intitiate * fix: adding events for posthog integration * fix: event payload --------- Co-authored-by: Ramesh Kumar Chandra <31303617+rameshkumarchandra@users.noreply.github.com>
This commit is contained in:
parent
33be52792f
commit
78fee22fec
@ -18,10 +18,10 @@
|
|||||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react-color": "^3.0.9",
|
|
||||||
"@types/node": "^20.5.2",
|
"@types/node": "^20.5.2",
|
||||||
"@types/react": "18.2.0",
|
"@types/react": "^18.2.37",
|
||||||
"@types/react-dom": "18.2.0",
|
"@types/react-color": "^3.0.9",
|
||||||
|
"@types/react-dom": "^18.2.15",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"eslint-config-custom": "*",
|
"eslint-config-custom": "*",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@ -30,9 +30,6 @@
|
|||||||
"tsup": "^5.10.1",
|
"tsup": "^5.10.1",
|
||||||
"typescript": "4.7.4"
|
"typescript": "4.7.4"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blueprintjs/core": "^4.16.3",
|
"@blueprintjs/core": "^4.16.3",
|
||||||
"@blueprintjs/popover2": "^1.13.3",
|
"@blueprintjs/popover2": "^1.13.3",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://turbo.build/schema.json",
|
"$schema": "https://turbo.build/schema.json",
|
||||||
"globalEnv": [
|
"globalEnv": [
|
||||||
|
"NODE_ENV",
|
||||||
"NEXT_PUBLIC_API_BASE_URL",
|
"NEXT_PUBLIC_API_BASE_URL",
|
||||||
"NEXT_PUBLIC_DEPLOY_URL",
|
"NEXT_PUBLIC_DEPLOY_URL",
|
||||||
"NEXT_PUBLIC_SENTRY_DSN",
|
"NEXT_PUBLIC_SENTRY_DSN",
|
||||||
@ -16,12 +17,8 @@
|
|||||||
"NEXT_PUBLIC_DEPLOY_WITH_NGINX",
|
"NEXT_PUBLIC_DEPLOY_WITH_NGINX",
|
||||||
"NEXT_PUBLIC_POSTHOG_KEY",
|
"NEXT_PUBLIC_POSTHOG_KEY",
|
||||||
"NEXT_PUBLIC_POSTHOG_HOST",
|
"NEXT_PUBLIC_POSTHOG_HOST",
|
||||||
"SLACK_OAUTH_URL",
|
|
||||||
"SLACK_CLIENT_ID",
|
|
||||||
"SLACK_CLIENT_SECRET",
|
|
||||||
"JITSU_TRACKER_ACCESS_KEY",
|
"JITSU_TRACKER_ACCESS_KEY",
|
||||||
"JITSU_TRACKER_HOST",
|
"JITSU_TRACKER_HOST"
|
||||||
"UNSPLASH_ACCESS_KEY"
|
|
||||||
],
|
],
|
||||||
"pipeline": {
|
"pipeline": {
|
||||||
"build": {
|
"build": {
|
||||||
|
@ -4,7 +4,6 @@ import { observer } from "mobx-react-lite";
|
|||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
// services
|
// services
|
||||||
import { AnalyticsService } from "services/analytics.service";
|
import { AnalyticsService } from "services/analytics.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
@ -29,7 +28,6 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const analyticsService = new AnalyticsService();
|
const analyticsService = new AnalyticsService();
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export const CustomAnalyticsSidebar: React.FC<Props> = observer(
|
export const CustomAnalyticsSidebar: React.FC<Props> = observer(
|
||||||
({ analytics, params, fullScreen, isProjectLevel = false }) => {
|
({ analytics, params, fullScreen, isProjectLevel = false }) => {
|
||||||
@ -90,18 +88,6 @@ export const CustomAnalyticsSidebar: React.FC<Props> = observer(
|
|||||||
eventPayload.moduleId = moduleDetails.id;
|
eventPayload.moduleId = moduleDetails.id;
|
||||||
eventPayload.moduleName = moduleDetails.name;
|
eventPayload.moduleName = moduleDetails.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackEventService.trackAnalyticsEvent(
|
|
||||||
eventPayload,
|
|
||||||
cycleId
|
|
||||||
? "CYCLE_ANALYTICS_EXPORT"
|
|
||||||
: moduleId
|
|
||||||
? "MODULE_ANALYTICS_EXPORT"
|
|
||||||
: projectId
|
|
||||||
? "PROJECT_ANALYTICS_EXPORT"
|
|
||||||
: "WORKSPACE_ANALYTICS_EXPORT",
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const exportAnalytics = () => {
|
const exportAnalytics = () => {
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
// mobx store
|
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
|
||||||
// services
|
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// components
|
// components
|
||||||
import { CustomAnalytics, ScopeAndDemand } from "components/analytics";
|
import { CustomAnalytics, ScopeAndDemand } from "components/analytics";
|
||||||
// types
|
// types
|
||||||
import { ICycle, IModule, IProject, IWorkspace } from "types";
|
import { ICycle, IModule, IProject } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { ANALYTICS_TABS } from "constants/analytics";
|
import { ANALYTICS_TABS } from "constants/analytics";
|
||||||
|
|
||||||
@ -20,63 +15,8 @@ type Props = {
|
|||||||
projectDetails: IProject | undefined;
|
projectDetails: IProject | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export const ProjectAnalyticsModalMainContent: React.FC<Props> = observer((props) => {
|
export const ProjectAnalyticsModalMainContent: React.FC<Props> = observer((props) => {
|
||||||
const { fullScreen, cycleDetails, moduleDetails, projectDetails } = props;
|
const { fullScreen, cycleDetails, moduleDetails } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
const { workspaceSlug } = router.query;
|
|
||||||
|
|
||||||
const { user: userStore } = useMobxStore();
|
|
||||||
|
|
||||||
const user = userStore.currentUser;
|
|
||||||
|
|
||||||
const trackAnalyticsEvent = (tab: string) => {
|
|
||||||
if (!workspaceSlug || !user) return;
|
|
||||||
|
|
||||||
const eventPayload: any = {
|
|
||||||
workspaceSlug: workspaceSlug.toString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (projectDetails) {
|
|
||||||
const workspaceDetails = projectDetails.workspace as IWorkspace;
|
|
||||||
|
|
||||||
eventPayload.workspaceId = workspaceDetails.id;
|
|
||||||
eventPayload.workspaceName = workspaceDetails.name;
|
|
||||||
eventPayload.projectId = projectDetails.id;
|
|
||||||
eventPayload.projectIdentifier = projectDetails.identifier;
|
|
||||||
eventPayload.projectName = projectDetails.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cycleDetails || moduleDetails) {
|
|
||||||
const details = cycleDetails || moduleDetails;
|
|
||||||
|
|
||||||
eventPayload.workspaceId = details?.workspace_detail?.id;
|
|
||||||
eventPayload.workspaceName = details?.workspace_detail?.name;
|
|
||||||
eventPayload.projectId = details?.project_detail.id;
|
|
||||||
eventPayload.projectIdentifier = details?.project_detail.identifier;
|
|
||||||
eventPayload.projectName = details?.project_detail.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cycleDetails) {
|
|
||||||
eventPayload.cycleId = cycleDetails.id;
|
|
||||||
eventPayload.cycleName = cycleDetails.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moduleDetails) {
|
|
||||||
eventPayload.moduleId = moduleDetails.id;
|
|
||||||
eventPayload.moduleName = moduleDetails.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventType = tab === "scope_and_demand" ? "SCOPE_AND_DEMAND_ANALYTICS" : "CUSTOM_ANALYTICS";
|
|
||||||
|
|
||||||
trackEventService.trackAnalyticsEvent(
|
|
||||||
eventPayload,
|
|
||||||
cycleDetails ? `CYCLE_${eventType}` : moduleDetails ? `MODULE_${eventType}` : `PROJECT_${eventType}`,
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tab.Group as={React.Fragment}>
|
<Tab.Group as={React.Fragment}>
|
||||||
@ -89,7 +29,7 @@ export const ProjectAnalyticsModalMainContent: React.FC<Props> = observer((props
|
|||||||
selected ? "bg-custom-background-80" : ""
|
selected ? "bg-custom-background-80" : ""
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
onClick={() => trackAnalyticsEvent(tab.key)}
|
onClick={() => {}}
|
||||||
>
|
>
|
||||||
{tab.title}
|
{tab.title}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -125,7 +125,7 @@ export const CommandModal: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const payload = { ...formData };
|
const payload = { ...formData };
|
||||||
await issueService
|
await issueService
|
||||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||||
mutate(ISSUE_DETAILS(issueId as string));
|
mutate(ISSUE_DETAILS(issueId as string));
|
||||||
@ -134,7 +134,7 @@ export const CommandModal: React.FC<Props> = observer((props) => {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[workspaceSlug, issueId, projectId, user]
|
[workspaceSlug, issueId, projectId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleIssueAssignees = (assignee: string) => {
|
const handleIssueAssignees = (assignee: string) => {
|
||||||
|
@ -25,7 +25,7 @@ type Props = {
|
|||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
|
|
||||||
export const ChangeIssueAssignee: FC<Props> = observer((props) => {
|
export const ChangeIssueAssignee: FC<Props> = observer((props) => {
|
||||||
const { setIsPaletteOpen, issue, user } = props;
|
const { setIsPaletteOpen, issue } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, issueId } = router.query;
|
const { workspaceSlug, projectId, issueId } = router.query;
|
||||||
@ -71,7 +71,7 @@ export const ChangeIssueAssignee: FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const payload = { ...formData };
|
const payload = { ...formData };
|
||||||
await issueService
|
await issueService
|
||||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||||
})
|
})
|
||||||
@ -79,7 +79,7 @@ export const ChangeIssueAssignee: FC<Props> = observer((props) => {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[workspaceSlug, issueId, projectId, user]
|
[workspaceSlug, issueId, projectId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleIssueAssignees = (assignee: string) => {
|
const handleIssueAssignees = (assignee: string) => {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import React, { Dispatch, SetStateAction, useCallback } from "react";
|
import React, { Dispatch, SetStateAction, useCallback } from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
|
|
||||||
// cmdk
|
// cmdk
|
||||||
import { Command } from "cmdk";
|
import { Command } from "cmdk";
|
||||||
// services
|
// services
|
||||||
@ -26,7 +23,7 @@ type Props = {
|
|||||||
// services
|
// services
|
||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
|
|
||||||
export const ChangeIssuePriority: React.FC<Props> = ({ setIsPaletteOpen, issue, user }) => {
|
export const ChangeIssuePriority: React.FC<Props> = ({ setIsPaletteOpen, issue }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, issueId } = router.query;
|
const { workspaceSlug, projectId, issueId } = router.query;
|
||||||
|
|
||||||
@ -49,7 +46,7 @@ export const ChangeIssuePriority: React.FC<Props> = ({ setIsPaletteOpen, issue,
|
|||||||
|
|
||||||
const payload = { ...formData };
|
const payload = { ...formData };
|
||||||
await issueService
|
await issueService
|
||||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||||
})
|
})
|
||||||
@ -57,7 +54,7 @@ export const ChangeIssuePriority: React.FC<Props> = ({ setIsPaletteOpen, issue,
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[workspaceSlug, issueId, projectId, user]
|
[workspaceSlug, issueId, projectId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleIssueState = (priority: TIssuePriorities) => {
|
const handleIssueState = (priority: TIssuePriorities) => {
|
||||||
|
@ -25,7 +25,7 @@ type Props = {
|
|||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
const stateService = new ProjectStateService();
|
const stateService = new ProjectStateService();
|
||||||
|
|
||||||
export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue, user }) => {
|
export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, issueId } = router.query;
|
const { workspaceSlug, projectId, issueId } = router.query;
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue, use
|
|||||||
|
|
||||||
const payload = { ...formData };
|
const payload = { ...formData };
|
||||||
await issueService
|
await issueService
|
||||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutateStates();
|
mutateStates();
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||||
@ -61,7 +61,7 @@ export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue, use
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[workspaceSlug, issueId, projectId, mutateStates, user]
|
[workspaceSlug, issueId, projectId, mutateStates]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleIssueState = (stateId: string) => {
|
const handleIssueState = (stateId: string) => {
|
||||||
|
@ -31,7 +31,7 @@ type Props = {
|
|||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
|
|
||||||
export const BulkDeleteIssuesModal: React.FC<Props> = (props) => {
|
export const BulkDeleteIssuesModal: React.FC<Props> = (props) => {
|
||||||
const { isOpen, onClose, user } = props;
|
const { isOpen, onClose } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, projectId } = router.query;
|
||||||
@ -78,14 +78,9 @@ export const BulkDeleteIssuesModal: React.FC<Props> = (props) => {
|
|||||||
if (!Array.isArray(data.delete_issue_ids)) data.delete_issue_ids = [data.delete_issue_ids];
|
if (!Array.isArray(data.delete_issue_ids)) data.delete_issue_ids = [data.delete_issue_ids];
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.bulkDeleteIssues(
|
.bulkDeleteIssues(workspaceSlug as string, projectId as string, {
|
||||||
workspaceSlug as string,
|
issue_ids: data.delete_issue_ids,
|
||||||
projectId as string,
|
})
|
||||||
{
|
|
||||||
issue_ids: data.delete_issue_ids,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
|
@ -4,10 +4,8 @@ import { useRouter } from "next/router";
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
// services
|
// services
|
||||||
import { AIService } from "services/ai.service";
|
import { AIService } from "services/ai.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
import useUserAuth from "hooks/use-user-auth";
|
|
||||||
// ui
|
// ui
|
||||||
import { Button, Input } from "@plane/ui";
|
import { Button, Input } from "@plane/ui";
|
||||||
// components
|
// components
|
||||||
@ -34,27 +32,15 @@ type FormData = {
|
|||||||
|
|
||||||
// services
|
// services
|
||||||
const aiService = new AIService();
|
const aiService = new AIService();
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export const GptAssistantModal: React.FC<Props> = ({
|
export const GptAssistantModal: React.FC<Props> = (props) => {
|
||||||
isOpen,
|
const { isOpen, handleClose, inset = "top-0 left-0", content, htmlContent, onResponse, projectId } = props;
|
||||||
handleClose,
|
|
||||||
inset = "top-0 left-0",
|
|
||||||
content,
|
|
||||||
htmlContent,
|
|
||||||
onResponse,
|
|
||||||
projectId,
|
|
||||||
block,
|
|
||||||
issue,
|
|
||||||
}) => {
|
|
||||||
const [response, setResponse] = useState("");
|
const [response, setResponse] = useState("");
|
||||||
const [invalidResponse, setInvalidResponse] = useState(false);
|
const [invalidResponse, setInvalidResponse] = useState(false);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
|
|
||||||
const { user } = useUserAuth();
|
|
||||||
|
|
||||||
const editorRef = useRef<any>(null);
|
const editorRef = useRef<any>(null);
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
@ -92,15 +78,10 @@ export const GptAssistantModal: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
await aiService
|
await aiService
|
||||||
.createGptTask(
|
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||||
workspaceSlug as string,
|
prompt: content && content !== "" ? content : htmlContent ?? "",
|
||||||
projectId as string,
|
task: formData.task,
|
||||||
{
|
})
|
||||||
prompt: content && content !== "" ? content : htmlContent ?? "",
|
|
||||||
task: formData.task,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setResponse(res.response_html);
|
setResponse(res.response_html);
|
||||||
setFocus("task");
|
setFocus("task");
|
||||||
@ -193,10 +174,6 @@ export const GptAssistantModal: React.FC<Props> = ({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
onResponse(response);
|
onResponse(response);
|
||||||
onClose();
|
onClose();
|
||||||
if (block && user)
|
|
||||||
trackEventService.trackUseGPTResponseEvent(block, "USE_GPT_RESPONSE_IN_PAGE_BLOCK", user);
|
|
||||||
else if (issue && user)
|
|
||||||
trackEventService.trackUseGPTResponseEvent(issue, "USE_GPT_RESPONSE_IN_ISSUE", user);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Use this response
|
Use this response
|
||||||
|
@ -11,7 +11,7 @@ import useUser from "hooks/use-user";
|
|||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
import { GanttChartRoot, IBlockUpdateData, CycleGanttSidebar } from "components/gantt-chart";
|
import { GanttChartRoot, IBlockUpdateData, CycleGanttSidebar } from "components/gantt-chart";
|
||||||
import { CycleGanttBlock, CycleGanttSidebarBlock } from "components/cycles";
|
import { CycleGanttBlock } from "components/cycles";
|
||||||
// types
|
// types
|
||||||
import { ICycle } from "types";
|
import { ICycle } from "types";
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ export const CyclesListGanttChartView: FC<Props> = ({ cycles, mutateCycles }) =>
|
|||||||
|
|
||||||
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
if (newPayload.sort_order && payload.sort_order) newPayload.sort_order = payload.sort_order.newSortOrder;
|
||||||
|
|
||||||
cycleService.patchCycle(workspaceSlug.toString(), cycle.project, cycle.id, newPayload, user);
|
cycleService.patchCycle(workspaceSlug.toString(), cycle.project, cycle.id, newPayload);
|
||||||
};
|
};
|
||||||
|
|
||||||
const blockFormat = (blocks: ICycle[]) =>
|
const blockFormat = (blocks: ICycle[]) =>
|
||||||
|
@ -52,9 +52,8 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, peekCycle } = router.query;
|
const { workspaceSlug, projectId, peekCycle } = router.query;
|
||||||
|
|
||||||
const { user: userStore, cycle: cycleDetailsStore } = useMobxStore();
|
const { cycle: cycleDetailsStore } = useMobxStore();
|
||||||
|
|
||||||
const user = userStore.currentUser ?? undefined;
|
|
||||||
const cycleDetails = cycleDetailsStore.cycle_details[cycleId] ?? undefined;
|
const cycleDetails = cycleDetailsStore.cycle_details[cycleId] ?? undefined;
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
@ -74,7 +73,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
mutate<ICycle>(CYCLE_DETAILS(cycleId as string), (prevData) => ({ ...(prevData as ICycle), ...data }), false);
|
mutate<ICycle>(CYCLE_DETAILS(cycleId as string), (prevData) => ({ ...(prevData as ICycle), ...data }), false);
|
||||||
|
|
||||||
cycleService
|
cycleService
|
||||||
.patchCycle(workspaceSlug as string, projectId as string, cycleId as string, data, user)
|
.patchCycle(workspaceSlug as string, projectId as string, cycleId as string, data)
|
||||||
.then(() => mutate(CYCLE_DETAILS(cycleId as string)))
|
.then(() => mutate(CYCLE_DETAILS(cycleId as string)))
|
||||||
.catch((e) => console.log(e));
|
.catch((e) => console.log(e));
|
||||||
};
|
};
|
||||||
|
@ -63,7 +63,7 @@ export const Exporter: React.FC<Props> = observer((props) => {
|
|||||||
multiple: multiple,
|
multiple: multiple,
|
||||||
};
|
};
|
||||||
await projectExportService
|
await projectExportService
|
||||||
.csvExport(workspaceSlug as string, payload, user)
|
.csvExport(workspaceSlug as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutateServices();
|
mutateServices();
|
||||||
router.push(`/${workspaceSlug}/settings/exports`);
|
router.push(`/${workspaceSlug}/settings/exports`);
|
||||||
|
@ -41,7 +41,7 @@ export const InboxIssueActivity: React.FC<Props> = observer(({ issueDetails }) =
|
|||||||
if (!workspaceSlug || !projectId || !inboxIssueId || !user) return;
|
if (!workspaceSlug || !projectId || !inboxIssueId || !user) return;
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.patchIssueComment(workspaceSlug as string, projectId as string, inboxIssueId as string, commentId, data, user)
|
.patchIssueComment(workspaceSlug as string, projectId as string, inboxIssueId as string, commentId, data)
|
||||||
.then(() => mutateIssueActivity());
|
.then(() => mutateIssueActivity());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ export const InboxIssueActivity: React.FC<Props> = observer(({ issueDetails }) =
|
|||||||
mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false);
|
mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false);
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.deleteIssueComment(workspaceSlug as string, projectId as string, inboxIssueId as string, commentId, user)
|
.deleteIssueComment(workspaceSlug as string, projectId as string, inboxIssueId as string, commentId)
|
||||||
.then(() => mutateIssueActivity());
|
.then(() => mutateIssueActivity());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ export const InboxIssueActivity: React.FC<Props> = observer(({ issueDetails }) =
|
|||||||
if (!workspaceSlug || !issueDetails || !user) return;
|
if (!workspaceSlug || !issueDetails || !user) return;
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.createIssueComment(workspaceSlug.toString(), issueDetails.project, issueDetails.id, formData, user)
|
.createIssueComment(workspaceSlug.toString(), issueDetails.project, issueDetails.id, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issueDetails.id));
|
mutate(PROJECT_ISSUES_ACTIVITY(issueDetails.id));
|
||||||
})
|
})
|
||||||
|
@ -29,7 +29,7 @@ type Props = {
|
|||||||
// services
|
// services
|
||||||
const integrationService = new IntegrationService();
|
const integrationService = new IntegrationService();
|
||||||
|
|
||||||
export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data, user }) => {
|
export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data }) => {
|
||||||
const [deleteLoading, setDeleteLoading] = useState(false);
|
const [deleteLoading, setDeleteLoading] = useState(false);
|
||||||
const [confirmDeleteImport, setConfirmDeleteImport] = useState(false);
|
const [confirmDeleteImport, setConfirmDeleteImport] = useState(false);
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ export const DeleteImportModal: React.FC<Props> = ({ isOpen, handleClose, data,
|
|||||||
);
|
);
|
||||||
|
|
||||||
integrationService
|
integrationService
|
||||||
.deleteImporterService(workspaceSlug as string, data.service, data.id, user)
|
.deleteImporterService(workspaceSlug as string, data.service, data.id)
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
|
@ -87,7 +87,7 @@ type Props = {
|
|||||||
const integrationService = new IntegrationService();
|
const integrationService = new IntegrationService();
|
||||||
const githubIntegrationService = new GithubIntegrationService();
|
const githubIntegrationService = new GithubIntegrationService();
|
||||||
|
|
||||||
export const GithubImporterRoot: React.FC<Props> = ({ user }) => {
|
export const GithubImporterRoot: React.FC<Props> = () => {
|
||||||
const [currentStep, setCurrentStep] = useState<IIntegrationData>({
|
const [currentStep, setCurrentStep] = useState<IIntegrationData>({
|
||||||
state: "import-configure",
|
state: "import-configure",
|
||||||
});
|
});
|
||||||
@ -147,7 +147,7 @@ export const GithubImporterRoot: React.FC<Props> = ({ user }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await githubIntegrationService
|
await githubIntegrationService
|
||||||
.createGithubServiceImport(workspaceSlug as string, payload, user)
|
.createGithubServiceImport(workspaceSlug as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
router.push(`/${workspaceSlug}/settings/imports`);
|
router.push(`/${workspaceSlug}/settings/imports`);
|
||||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
|
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
|
||||||
|
@ -60,7 +60,7 @@ type Props = {
|
|||||||
// services
|
// services
|
||||||
const jiraImporterService = new JiraImporterService();
|
const jiraImporterService = new JiraImporterService();
|
||||||
|
|
||||||
export const JiraImporterRoot: React.FC<Props> = ({ user }) => {
|
export const JiraImporterRoot: React.FC<Props> = () => {
|
||||||
const [currentStep, setCurrentStep] = useState<IJiraIntegrationData>({
|
const [currentStep, setCurrentStep] = useState<IJiraIntegrationData>({
|
||||||
state: "import-configure",
|
state: "import-configure",
|
||||||
});
|
});
|
||||||
@ -81,7 +81,7 @@ export const JiraImporterRoot: React.FC<Props> = ({ user }) => {
|
|||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
await jiraImporterService
|
await jiraImporterService
|
||||||
.createJiraImporter(workspaceSlug.toString(), data, user)
|
.createJiraImporter(workspaceSlug.toString(), data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(IMPORTER_SERVICES_LIST(workspaceSlug.toString()));
|
mutate(IMPORTER_SERVICES_LIST(workspaceSlug.toString()));
|
||||||
router.push(`/${workspaceSlug}/settings/imports`);
|
router.push(`/${workspaceSlug}/settings/imports`);
|
||||||
|
@ -231,15 +231,10 @@ export const DraftIssueForm: FC<IssueFormProps> = (props) => {
|
|||||||
setIAmFeelingLucky(true);
|
setIAmFeelingLucky(true);
|
||||||
|
|
||||||
aiService
|
aiService
|
||||||
.createGptTask(
|
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||||
workspaceSlug as string,
|
prompt: issueName,
|
||||||
projectId as string,
|
task: "Generate a proper description for this issue.",
|
||||||
{
|
})
|
||||||
prompt: issueName,
|
|
||||||
task: "Generate a proper description for this issue.",
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.response === "")
|
if (res.response === "")
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
|
@ -226,36 +226,24 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = observer(
|
|||||||
const addIssueToCycle = async (issueId: string, cycleId: string) => {
|
const addIssueToCycle = async (issueId: string, cycleId: string) => {
|
||||||
if (!workspaceSlug || !activeProject || !user) return;
|
if (!workspaceSlug || !activeProject || !user) return;
|
||||||
|
|
||||||
await issueService.addIssueToCycle(
|
await issueService.addIssueToCycle(workspaceSlug as string, activeProject ?? "", cycleId, {
|
||||||
workspaceSlug as string,
|
issues: [issueId],
|
||||||
activeProject ?? "",
|
});
|
||||||
cycleId,
|
|
||||||
{
|
|
||||||
issues: [issueId],
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const addIssueToModule = async (issueId: string, moduleId: string) => {
|
const addIssueToModule = async (issueId: string, moduleId: string) => {
|
||||||
if (!workspaceSlug || !activeProject || !user) return;
|
if (!workspaceSlug || !activeProject || !user) return;
|
||||||
|
|
||||||
await moduleService.addIssuesToModule(
|
await moduleService.addIssuesToModule(workspaceSlug as string, activeProject ?? "", moduleId as string, {
|
||||||
workspaceSlug as string,
|
issues: [issueId],
|
||||||
activeProject ?? "",
|
});
|
||||||
moduleId as string,
|
|
||||||
{
|
|
||||||
issues: [issueId],
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createIssue = async (payload: Partial<IIssue>) => {
|
const createIssue = async (payload: Partial<IIssue>) => {
|
||||||
if (!workspaceSlug || !activeProject || !user) return;
|
if (!workspaceSlug || !activeProject || !user) return;
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.createIssue(workspaceSlug.toString(), activeProject, payload, user)
|
.createIssue(workspaceSlug.toString(), activeProject, payload)
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
if (payload.cycle && payload.cycle !== "") await addIssueToCycle(res.id, payload.cycle);
|
||||||
if (payload.module && payload.module !== "") await addIssueToModule(res.id, payload.module);
|
if (payload.module && payload.module !== "") await addIssueToModule(res.id, payload.module);
|
||||||
|
@ -188,15 +188,10 @@ export const IssueForm: FC<IssueFormProps> = observer((props) => {
|
|||||||
setIAmFeelingLucky(true);
|
setIAmFeelingLucky(true);
|
||||||
|
|
||||||
aiService
|
aiService
|
||||||
.createGptTask(
|
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||||
workspaceSlug as string,
|
prompt: issueName,
|
||||||
projectId as string,
|
task: "Generate a proper description for this issue.",
|
||||||
{
|
})
|
||||||
prompt: issueName,
|
|
||||||
task: "Generate a proper description for this issue.",
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.response === "")
|
if (res.response === "")
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React, { FC } from "react";
|
import React, { FC } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
// services
|
// services
|
||||||
import { ModuleService } from "services/module.service";
|
import { ModuleService } from "services/module.service";
|
||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
@ -11,7 +10,6 @@ import { ExistingIssuesListModal } from "components/core";
|
|||||||
// lucide icons
|
// lucide icons
|
||||||
import { Minimize2, Maximize2, Circle, Plus } from "lucide-react";
|
import { Minimize2, Maximize2, Circle, Plus } from "lucide-react";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "hooks/use-user";
|
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// mobx
|
// mobx
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
@ -43,8 +41,6 @@ export const HeaderGroupByCard: FC<IHeaderGroupByCard> = observer((props) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, moduleId, cycleId } = router.query;
|
const { workspaceSlug, projectId, moduleId, cycleId } = router.query;
|
||||||
|
|
||||||
const { user } = useUser();
|
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const renderExistingIssueModal = moduleId || cycleId;
|
const renderExistingIssueModal = moduleId || cycleId;
|
||||||
@ -58,7 +54,7 @@ export const HeaderGroupByCard: FC<IHeaderGroupByCard> = observer((props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await moduleService
|
await moduleService
|
||||||
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleId as string, payload, user)
|
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleId as string, payload)
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
@ -76,7 +72,7 @@ export const HeaderGroupByCard: FC<IHeaderGroupByCard> = observer((props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId as string, payload, user)
|
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId as string, payload)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
// services
|
// services
|
||||||
import { ModuleService } from "services/module.service";
|
import { ModuleService } from "services/module.service";
|
||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
@ -11,7 +10,6 @@ import { CreateUpdateIssueModal } from "components/issues/modal";
|
|||||||
import { ExistingIssuesListModal } from "components/core";
|
import { ExistingIssuesListModal } from "components/core";
|
||||||
import { CustomMenu } from "@plane/ui";
|
import { CustomMenu } from "@plane/ui";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "hooks/use-user";
|
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// mobx
|
// mobx
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
@ -34,8 +32,6 @@ export const HeaderGroupByCard = observer(({ icon, title, count, issuePayload }:
|
|||||||
const [isOpen, setIsOpen] = React.useState(false);
|
const [isOpen, setIsOpen] = React.useState(false);
|
||||||
const [openExistingIssueListModal, setOpenExistingIssueListModal] = React.useState(false);
|
const [openExistingIssueListModal, setOpenExistingIssueListModal] = React.useState(false);
|
||||||
|
|
||||||
const { user } = useUser();
|
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const verticalAlignPosition = false;
|
const verticalAlignPosition = false;
|
||||||
@ -51,7 +47,7 @@ export const HeaderGroupByCard = observer(({ icon, title, count, issuePayload }:
|
|||||||
};
|
};
|
||||||
|
|
||||||
await moduleService
|
await moduleService
|
||||||
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleId as string, payload, user)
|
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleId as string, payload)
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
@ -69,7 +65,7 @@ export const HeaderGroupByCard = observer(({ icon, title, count, issuePayload }:
|
|||||||
};
|
};
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId as string, payload, user)
|
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId as string, payload)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
|
@ -69,7 +69,7 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
|
|||||||
if (!workspaceSlug || !projectId || !issueId) return;
|
if (!workspaceSlug || !projectId || !issueId) return;
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.patchIssueComment(workspaceSlug as string, projectId as string, issueId as string, commentId, data, user)
|
.patchIssueComment(workspaceSlug as string, projectId as string, issueId as string, commentId, data)
|
||||||
.then(() => mutateIssueActivity());
|
.then(() => mutateIssueActivity());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
|
|||||||
mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false);
|
mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false);
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.deleteIssueComment(workspaceSlug as string, projectId as string, issueId as string, commentId, user)
|
.deleteIssueComment(workspaceSlug as string, projectId as string, issueId as string, commentId)
|
||||||
.then(() => mutateIssueActivity());
|
.then(() => mutateIssueActivity());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ export const IssueMainContent: React.FC<Props> = observer((props) => {
|
|||||||
if (!workspaceSlug || !issueDetails || !user) return;
|
if (!workspaceSlug || !issueDetails || !user) return;
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.createIssueComment(workspaceSlug.toString(), issueDetails.project, issueDetails.id, formData, user)
|
.createIssueComment(workspaceSlug.toString(), issueDetails.project, issueDetails.id, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issueDetails.id));
|
mutate(PROJECT_ISSUES_ACTIVITY(issueDetails.id));
|
||||||
})
|
})
|
||||||
|
@ -2,7 +2,6 @@ import useSWR, { mutate } from "swr";
|
|||||||
// services
|
// services
|
||||||
import { IssueCommentService, IssueService } from "services/issue";
|
import { IssueCommentService, IssueService } from "services/issue";
|
||||||
// hooks
|
// hooks
|
||||||
import useUser from "hooks/use-user";
|
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
import useProjectDetails from "hooks/use-project-details";
|
import useProjectDetails from "hooks/use-project-details";
|
||||||
// components
|
// components
|
||||||
@ -26,7 +25,6 @@ export const PeekOverviewIssueActivity: React.FC<Props> = (props) => {
|
|||||||
// toast
|
// toast
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const { user } = useUser();
|
|
||||||
const { projectDetails } = useProjectDetails();
|
const { projectDetails } = useProjectDetails();
|
||||||
|
|
||||||
const { data: issueActivity, mutate: mutateIssueActivity } = useSWR(
|
const { data: issueActivity, mutate: mutateIssueActivity } = useSWR(
|
||||||
@ -40,7 +38,7 @@ export const PeekOverviewIssueActivity: React.FC<Props> = (props) => {
|
|||||||
if (!workspaceSlug || !issue) return;
|
if (!workspaceSlug || !issue) return;
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.patchIssueComment(workspaceSlug as string, issue.project, issue.id, commentId, data, user)
|
.patchIssueComment(workspaceSlug as string, issue.project, issue.id, commentId, data)
|
||||||
.then(() => mutateIssueActivity());
|
.then(() => mutateIssueActivity());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,7 +48,7 @@ export const PeekOverviewIssueActivity: React.FC<Props> = (props) => {
|
|||||||
mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false);
|
mutateIssueActivity((prevData: any) => prevData?.filter((p: any) => p.id !== commentId), false);
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.deleteIssueComment(workspaceSlug as string, issue.project, issue.id, commentId, user)
|
.deleteIssueComment(workspaceSlug as string, issue.project, issue.id, commentId)
|
||||||
.then(() => mutateIssueActivity());
|
.then(() => mutateIssueActivity());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,7 +56,7 @@ export const PeekOverviewIssueActivity: React.FC<Props> = (props) => {
|
|||||||
if (!workspaceSlug || !issue) return;
|
if (!workspaceSlug || !issue) return;
|
||||||
|
|
||||||
await issueCommentService
|
await issueCommentService
|
||||||
.createIssueComment(workspaceSlug.toString(), issue.project, issue.id, formData, user)
|
.createIssueComment(workspaceSlug.toString(), issue.project, issue.id, formData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issue.id));
|
mutate(PROJECT_ISSUES_ACTIVITY(issue.id));
|
||||||
})
|
})
|
||||||
|
@ -68,7 +68,7 @@ export const SidebarBlockedSelect: React.FC<Props> = ({ issueId, submitChanges,
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
issueService
|
issueService
|
||||||
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, user, {
|
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, {
|
||||||
related_list: [
|
related_list: [
|
||||||
...selectedIssues.map((issue) => ({
|
...selectedIssues.map((issue) => ({
|
||||||
issue: issueId as string,
|
issue: issueId as string,
|
||||||
@ -134,8 +134,7 @@ export const SidebarBlockedSelect: React.FC<Props> = ({ issueId, submitChanges,
|
|||||||
workspaceSlug as string,
|
workspaceSlug as string,
|
||||||
projectId as string,
|
projectId as string,
|
||||||
issueId as string,
|
issueId as string,
|
||||||
relation.id,
|
relation.id
|
||||||
user
|
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -69,7 +69,7 @@ export const SidebarBlockerSelect: React.FC<Props> = ({ issueId, submitChanges,
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
issueService
|
issueService
|
||||||
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, user, {
|
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, {
|
||||||
related_list: [
|
related_list: [
|
||||||
...selectedIssues.map((issue) => ({
|
...selectedIssues.map((issue) => ({
|
||||||
issue: issue.blocker_issue_detail.id,
|
issue: issue.blocker_issue_detail.id,
|
||||||
@ -144,8 +144,7 @@ export const SidebarBlockerSelect: React.FC<Props> = ({ issueId, submitChanges,
|
|||||||
workspaceSlug as string,
|
workspaceSlug as string,
|
||||||
projectId as string,
|
projectId as string,
|
||||||
relation.issue_detail?.id as string,
|
relation.issue_detail?.id as string,
|
||||||
relation.id,
|
relation.id
|
||||||
user
|
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -67,7 +67,7 @@ export const SidebarDuplicateSelect: React.FC<Props> = (props) => {
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
issueService
|
issueService
|
||||||
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, user, {
|
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, {
|
||||||
related_list: [
|
related_list: [
|
||||||
...selectedIssues.map((issue) => ({
|
...selectedIssues.map((issue) => ({
|
||||||
issue: issueId as string,
|
issue: issueId as string,
|
||||||
@ -137,8 +137,7 @@ export const SidebarDuplicateSelect: React.FC<Props> = (props) => {
|
|||||||
workspaceSlug as string,
|
workspaceSlug as string,
|
||||||
projectId as string,
|
projectId as string,
|
||||||
issueId as string,
|
issueId as string,
|
||||||
relation.id,
|
relation.id
|
||||||
user
|
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
submitChanges();
|
submitChanges();
|
||||||
|
@ -7,8 +7,6 @@ import { TwitterPicker } from "react-color";
|
|||||||
import { Popover, Transition } from "@headlessui/react";
|
import { Popover, Transition } from "@headlessui/react";
|
||||||
// services
|
// services
|
||||||
import { IssueLabelService } from "services/issue";
|
import { IssueLabelService } from "services/issue";
|
||||||
// hooks
|
|
||||||
import useUser from "hooks/use-user";
|
|
||||||
// ui
|
// ui
|
||||||
import { Input } from "@plane/ui";
|
import { Input } from "@plane/ui";
|
||||||
import { IssueLabelSelect } from "../select";
|
import { IssueLabelSelect } from "../select";
|
||||||
@ -61,8 +59,6 @@ export const SidebarLabelSelect: React.FC<Props> = ({
|
|||||||
defaultValues,
|
defaultValues,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { user } = useUser();
|
|
||||||
|
|
||||||
const { data: issueLabels, mutate: issueLabelMutate } = useSWR<IIssueLabel[]>(
|
const { data: issueLabels, mutate: issueLabelMutate } = useSWR<IIssueLabel[]>(
|
||||||
workspaceSlug && projectId ? PROJECT_ISSUE_LABELS(projectId as string) : null,
|
workspaceSlug && projectId ? PROJECT_ISSUE_LABELS(projectId as string) : null,
|
||||||
workspaceSlug && projectId
|
workspaceSlug && projectId
|
||||||
@ -74,7 +70,7 @@ export const SidebarLabelSelect: React.FC<Props> = ({
|
|||||||
if (!workspaceSlug || !projectId || isSubmitting) return;
|
if (!workspaceSlug || !projectId || isSubmitting) return;
|
||||||
|
|
||||||
await issueLabelService
|
await issueLabelService
|
||||||
.createIssueLabel(workspaceSlug as string, projectId as string, formData, user)
|
.createIssueLabel(workspaceSlug as string, projectId as string, formData)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
reset(defaultValues);
|
reset(defaultValues);
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ export const SidebarRelatesSelect: React.FC<Props> = (props) => {
|
|||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
issueService
|
issueService
|
||||||
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, user, {
|
.createIssueRelation(workspaceSlug as string, projectId as string, issueId as string, {
|
||||||
related_list: [
|
related_list: [
|
||||||
...selectedIssues.map((issue) => ({
|
...selectedIssues.map((issue) => ({
|
||||||
issue: issueId as string,
|
issue: issueId as string,
|
||||||
@ -138,8 +138,7 @@ export const SidebarRelatesSelect: React.FC<Props> = (props) => {
|
|||||||
workspaceSlug as string,
|
workspaceSlug as string,
|
||||||
projectId as string,
|
projectId as string,
|
||||||
issueId as string,
|
issueId as string,
|
||||||
relation.id,
|
relation.id
|
||||||
user
|
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
submitChanges();
|
submitChanges();
|
||||||
|
@ -101,15 +101,9 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
if (!workspaceSlug || !projectId || !issueDetail || !user) return;
|
if (!workspaceSlug || !projectId || !issueDetail || !user) return;
|
||||||
|
|
||||||
issueService
|
issueService
|
||||||
.addIssueToCycle(
|
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId, {
|
||||||
workspaceSlug as string,
|
issues: [issueDetail.id],
|
||||||
projectId as string,
|
})
|
||||||
cycleId,
|
|
||||||
{
|
|
||||||
issues: [issueDetail.id],
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(ISSUE_DETAILS(issueId as string));
|
mutate(ISSUE_DETAILS(issueId as string));
|
||||||
});
|
});
|
||||||
@ -122,15 +116,9 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
if (!workspaceSlug || !projectId || !issueDetail || !user) return;
|
if (!workspaceSlug || !projectId || !issueDetail || !user) return;
|
||||||
|
|
||||||
moduleService
|
moduleService
|
||||||
.addIssuesToModule(
|
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleId, {
|
||||||
workspaceSlug as string,
|
issues: [issueDetail.id],
|
||||||
projectId as string,
|
})
|
||||||
moduleId,
|
|
||||||
{
|
|
||||||
issues: [issueDetail.id],
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(ISSUE_DETAILS(issueId as string));
|
mutate(ISSUE_DETAILS(issueId as string));
|
||||||
});
|
});
|
||||||
|
@ -5,7 +5,6 @@ import { mutate } from "swr";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// services
|
// services
|
||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// components
|
// components
|
||||||
import { ViewDueDateSelect, ViewStartDateSelect } from "components/issues";
|
import { ViewDueDateSelect, ViewStartDateSelect } from "components/issues";
|
||||||
import { PrioritySelect } from "components/project";
|
import { PrioritySelect } from "components/project";
|
||||||
@ -25,7 +24,6 @@ export interface IIssueProperty {
|
|||||||
|
|
||||||
// services
|
// services
|
||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
|
export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
|
||||||
const { workspaceSlug, parentIssue, issue, user, editable } = props;
|
const { workspaceSlug, parentIssue, issue, user, editable } = props;
|
||||||
@ -36,18 +34,6 @@ export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
|
|||||||
|
|
||||||
const handlePriorityChange = (data: any) => {
|
const handlePriorityChange = (data: any) => {
|
||||||
partialUpdateIssue({ priority: data });
|
partialUpdateIssue({ priority: data });
|
||||||
trackEventService.trackIssuePartialPropertyUpdateEvent(
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
workspaceId: issue.workspace,
|
|
||||||
projectId: issue.project_detail.id,
|
|
||||||
projectIdentifier: issue.project_detail.identifier,
|
|
||||||
projectName: issue.project_detail.name,
|
|
||||||
issueId: issue.id,
|
|
||||||
},
|
|
||||||
"ISSUE_PROPERTY_UPDATE_PRIORITY",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStateChange = (data: IState) => {
|
const handleStateChange = (data: IState) => {
|
||||||
@ -55,35 +41,10 @@ export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
|
|||||||
state: data.id,
|
state: data.id,
|
||||||
state_detail: data,
|
state_detail: data,
|
||||||
});
|
});
|
||||||
trackEventService.trackIssuePartialPropertyUpdateEvent(
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
workspaceId: issue.workspace,
|
|
||||||
projectId: issue.project_detail.id,
|
|
||||||
projectIdentifier: issue.project_detail.identifier,
|
|
||||||
projectName: issue.project_detail.name,
|
|
||||||
issueId: issue.id,
|
|
||||||
},
|
|
||||||
"ISSUE_PROPERTY_UPDATE_STATE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAssigneeChange = (data: string[]) => {
|
const handleAssigneeChange = (data: string[]) => {
|
||||||
partialUpdateIssue({ assignees: data });
|
partialUpdateIssue({ assignees: data });
|
||||||
|
|
||||||
trackEventService.trackIssuePartialPropertyUpdateEvent(
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
workspaceId: issue.workspace,
|
|
||||||
projectId: issue.project_detail.id,
|
|
||||||
projectIdentifier: issue.project_detail.identifier,
|
|
||||||
projectName: issue.project_detail.name,
|
|
||||||
issueId: issue.id,
|
|
||||||
},
|
|
||||||
"ISSUE_PROPERTY_UPDATE_ASSIGNEE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const partialUpdateIssue = async (data: Partial<IIssue>) => {
|
const partialUpdateIssue = async (data: Partial<IIssue>) => {
|
||||||
@ -100,7 +61,7 @@ export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
const issueResponse = await issueService.patchIssue(workspaceSlug as string, issue.project, issue.id, data, user);
|
const issueResponse = await issueService.patchIssue(workspaceSlug as string, issue.project, issue.id, data);
|
||||||
|
|
||||||
mutate(
|
mutate(
|
||||||
SUB_ISSUES(parentIssue.id),
|
SUB_ISSUES(parentIssue.id),
|
||||||
|
@ -126,7 +126,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
|
|||||||
const removeIssueFromSubIssues = async (parentIssueId: string, issue: IIssue) => {
|
const removeIssueFromSubIssues = async (parentIssueId: string, issue: IIssue) => {
|
||||||
if (!workspaceSlug || !projectId || !parentIssue || !issue?.id) return;
|
if (!workspaceSlug || !projectId || !parentIssue || !issue?.id) return;
|
||||||
issueService
|
issueService
|
||||||
.patchIssue(workspaceSlug.toString(), projectId.toString(), issue.id, { parent: null }, user)
|
.patchIssue(workspaceSlug.toString(), projectId.toString(), issue.id, { parent: null })
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
if (parentIssueId) await mutate(SUB_ISSUES(parentIssueId));
|
if (parentIssueId) await mutate(SUB_ISSUES(parentIssueId));
|
||||||
handleIssuesLoader({ key: "delete", issueId: issue?.id });
|
handleIssuesLoader({ key: "delete", issueId: issue?.id });
|
||||||
|
@ -57,7 +57,6 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const { module: moduleStore, user: userStore } = useMobxStore();
|
const { module: moduleStore, user: userStore } = useMobxStore();
|
||||||
|
|
||||||
const user = userStore.currentUser ?? undefined;
|
|
||||||
const userRole = userStore.currentProjectRole;
|
const userRole = userStore.currentProjectRole;
|
||||||
const moduleDetails = moduleStore.moduleDetails[moduleId] ?? undefined;
|
const moduleDetails = moduleStore.moduleDetails[moduleId] ?? undefined;
|
||||||
|
|
||||||
@ -80,7 +79,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
moduleService
|
moduleService
|
||||||
.patchModule(workspaceSlug as string, projectId as string, moduleId as string, data, user)
|
.patchModule(workspaceSlug as string, projectId as string, moduleId as string, data)
|
||||||
.then(() => mutate(MODULE_DETAILS(moduleId as string)))
|
.then(() => mutate(MODULE_DETAILS(moduleId as string)))
|
||||||
.catch((e) => console.log(e));
|
.catch((e) => console.log(e));
|
||||||
};
|
};
|
||||||
|
@ -164,7 +164,7 @@ const InviteMemberForm: React.FC<InviteMemberFormProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const InviteMembers: React.FC<Props> = (props) => {
|
export const InviteMembers: React.FC<Props> = (props) => {
|
||||||
const { finishOnboarding, stepChange, user, workspace } = props;
|
const { finishOnboarding, stepChange, workspace } = props;
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ export const InviteMembers: React.FC<Props> = (props) => {
|
|||||||
const payload = { ...formData };
|
const payload = { ...formData };
|
||||||
|
|
||||||
await workspaceService
|
await workspaceService
|
||||||
.inviteWorkspace(workspace.slug, payload, user)
|
.inviteWorkspace(workspace.slug, payload)
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
|
@ -18,6 +18,7 @@ import { IWorkspaceMemberInvitation, TOnboardingSteps } from "types";
|
|||||||
import { USER_WORKSPACES, USER_WORKSPACE_INVITATIONS } from "constants/fetch-keys";
|
import { USER_WORKSPACES, USER_WORKSPACE_INVITATIONS } from "constants/fetch-keys";
|
||||||
// constants
|
// constants
|
||||||
import { ROLE } from "constants/workspace";
|
import { ROLE } from "constants/workspace";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
finishOnboarding: () => Promise<void>;
|
finishOnboarding: () => Promise<void>;
|
||||||
@ -61,7 +62,11 @@ export const JoinWorkspaces: React.FC<Props> = ({ finishOnboarding, stepChange,
|
|||||||
|
|
||||||
await workspaceService
|
await workspaceService
|
||||||
.joinWorkspaces({ invitations: invitationsRespond })
|
.joinWorkspaces({ invitations: invitationsRespond })
|
||||||
.then(async () => {
|
.then(async (res) => {
|
||||||
|
trackEvent(
|
||||||
|
'WORKSPACE_USER_INVITE_ACCEPT',
|
||||||
|
res
|
||||||
|
)
|
||||||
await mutateInvitations();
|
await mutateInvitations();
|
||||||
await mutate(USER_WORKSPACES);
|
await mutate(USER_WORKSPACES);
|
||||||
await updateLastWorkspace();
|
await updateLastWorkspace();
|
||||||
@ -83,9 +88,8 @@ export const JoinWorkspaces: React.FC<Props> = ({ finishOnboarding, stepChange,
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={invitation.id}
|
key={invitation.id}
|
||||||
className={`flex cursor-pointer items-center gap-2 border py-5 px-3.5 rounded ${
|
className={`flex cursor-pointer items-center gap-2 border py-5 px-3.5 rounded ${isSelected ? "border-custom-primary-100" : "border-custom-border-200 hover:bg-custom-background-80"
|
||||||
isSelected ? "border-custom-primary-100" : "border-custom-border-200 hover:bg-custom-background-80"
|
}`}
|
||||||
}`}
|
|
||||||
onClick={() => handleInvitation(invitation, isSelected ? "withdraw" : "accepted")}
|
onClick={() => handleInvitation(invitation, isSelected ? "withdraw" : "accepted")}
|
||||||
>
|
>
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
|
@ -24,7 +24,7 @@ type Props = {
|
|||||||
|
|
||||||
const pageService = new PageService();
|
const pageService = new PageService();
|
||||||
|
|
||||||
export const CreateBlock: FC<Props> = ({ user }) => {
|
export const CreateBlock: FC<Props> = () => {
|
||||||
// const [blockTitle, setBlockTitle] = useState("");
|
// const [blockTitle, setBlockTitle] = useState("");
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -46,15 +46,9 @@ export const CreateBlock: FC<Props> = ({ user }) => {
|
|||||||
if (!workspaceSlug || !projectId || !pageId) return;
|
if (!workspaceSlug || !projectId || !pageId) return;
|
||||||
|
|
||||||
await pageService
|
await pageService
|
||||||
.createPageBlock(
|
.createPageBlock(workspaceSlug as string, projectId as string, pageId as string, {
|
||||||
workspaceSlug as string,
|
name: watch("name"),
|
||||||
projectId as string,
|
})
|
||||||
pageId as string,
|
|
||||||
{
|
|
||||||
name: watch("name"),
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate<IPageBlock[]>(
|
mutate<IPageBlock[]>(
|
||||||
PAGE_BLOCKS_LIST(pageId as string),
|
PAGE_BLOCKS_LIST(pageId as string),
|
||||||
|
@ -40,14 +40,7 @@ const pagesService = new PageService();
|
|||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
const fileService = new FileService();
|
const fileService = new FileService();
|
||||||
|
|
||||||
export const CreateUpdateBlockInline: FC<Props> = ({
|
export const CreateUpdateBlockInline: FC<Props> = ({ handleClose, data, handleAiAssistance, setIsSyncing, focus }) => {
|
||||||
handleClose,
|
|
||||||
data,
|
|
||||||
handleAiAssistance,
|
|
||||||
setIsSyncing,
|
|
||||||
focus,
|
|
||||||
user,
|
|
||||||
}) => {
|
|
||||||
const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false);
|
const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false);
|
||||||
const [gptAssistantModal, setGptAssistantModal] = useState(false);
|
const [gptAssistantModal, setGptAssistantModal] = useState(false);
|
||||||
|
|
||||||
@ -83,17 +76,11 @@ export const CreateUpdateBlockInline: FC<Props> = ({
|
|||||||
if (!workspaceSlug || !projectId || !pageId) return;
|
if (!workspaceSlug || !projectId || !pageId) return;
|
||||||
|
|
||||||
await pagesService
|
await pagesService
|
||||||
.createPageBlock(
|
.createPageBlock(workspaceSlug as string, projectId as string, pageId as string, {
|
||||||
workspaceSlug as string,
|
name: formData.name,
|
||||||
projectId as string,
|
description: formData.description ?? "",
|
||||||
pageId as string,
|
description_html: formData.description_html ?? "<p></p>",
|
||||||
{
|
})
|
||||||
name: formData.name,
|
|
||||||
description: formData.description ?? "",
|
|
||||||
description_html: formData.description_html ?? "<p></p>",
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate<IPageBlock[]>(
|
mutate<IPageBlock[]>(
|
||||||
PAGE_BLOCKS_LIST(pageId as string),
|
PAGE_BLOCKS_LIST(pageId as string),
|
||||||
@ -111,7 +98,7 @@ export const CreateUpdateBlockInline: FC<Props> = ({
|
|||||||
})
|
})
|
||||||
.finally(() => onClose());
|
.finally(() => onClose());
|
||||||
},
|
},
|
||||||
[workspaceSlug, projectId, pageId, onClose, setToastAlert, user]
|
[workspaceSlug, projectId, pageId, onClose, setToastAlert]
|
||||||
);
|
);
|
||||||
|
|
||||||
const updatePageBlock = useCallback(
|
const updatePageBlock = useCallback(
|
||||||
@ -132,41 +119,28 @@ export const CreateUpdateBlockInline: FC<Props> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
await pagesService
|
await pagesService
|
||||||
.patchPageBlock(
|
.patchPageBlock(workspaceSlug as string, projectId as string, pageId as string, data.id, {
|
||||||
workspaceSlug as string,
|
name: formData.name,
|
||||||
projectId as string,
|
description: formData.description,
|
||||||
pageId as string,
|
description_html: formData.description_html,
|
||||||
data.id,
|
})
|
||||||
{
|
|
||||||
name: formData.name,
|
|
||||||
description: formData.description,
|
|
||||||
description_html: formData.description_html,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate(PAGE_BLOCKS_LIST(pageId as string));
|
mutate(PAGE_BLOCKS_LIST(pageId as string));
|
||||||
editorRef.current?.setEditorValue(res.description_html);
|
editorRef.current?.setEditorValue(res.description_html);
|
||||||
if (data.issue && data.sync)
|
if (data.issue && data.sync)
|
||||||
issueService
|
issueService
|
||||||
.patchIssue(
|
.patchIssue(workspaceSlug as string, projectId as string, data.issue, {
|
||||||
workspaceSlug as string,
|
name: res.name,
|
||||||
projectId as string,
|
description: res.description,
|
||||||
data.issue,
|
description_html: res.description_html,
|
||||||
{
|
})
|
||||||
name: res.name,
|
|
||||||
description: res.description,
|
|
||||||
description_html: res.description_html,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
if (setIsSyncing) setIsSyncing(false);
|
if (setIsSyncing) setIsSyncing(false);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.finally(() => onClose());
|
.finally(() => onClose());
|
||||||
},
|
},
|
||||||
[workspaceSlug, projectId, pageId, data, onClose, setIsSyncing, user]
|
[workspaceSlug, projectId, pageId, data, onClose, setIsSyncing]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleAutoGenerateDescription = async () => {
|
const handleAutoGenerateDescription = async () => {
|
||||||
@ -175,15 +149,10 @@ export const CreateUpdateBlockInline: FC<Props> = ({
|
|||||||
setIAmFeelingLucky(true);
|
setIAmFeelingLucky(true);
|
||||||
|
|
||||||
aiService
|
aiService
|
||||||
.createGptTask(
|
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||||
workspaceSlug as string,
|
prompt: watch("name"),
|
||||||
projectId as string,
|
task: "Generate a proper description for this issue.",
|
||||||
{
|
})
|
||||||
prompt: watch("name"),
|
|
||||||
task: "Generate a proper description for this issue.",
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.response === "")
|
if (res.response === "")
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
|
|
||||||
// headless ui
|
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
// services
|
// services
|
||||||
import { PageService } from "services/page.service";
|
import { PageService } from "services/page.service";
|
||||||
@ -16,6 +12,7 @@ import { PageForm } from "./page-form";
|
|||||||
import { IUser, IPage } from "types";
|
import { IUser, IPage } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { ALL_PAGES_LIST, FAVORITE_PAGES_LIST, MY_PAGES_LIST, RECENT_PAGES_LIST } from "constants/fetch-keys";
|
import { ALL_PAGES_LIST, FAVORITE_PAGES_LIST, MY_PAGES_LIST, RECENT_PAGES_LIST } from "constants/fetch-keys";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -30,7 +27,7 @@ type Props = {
|
|||||||
const pageService = new PageService();
|
const pageService = new PageService();
|
||||||
|
|
||||||
export const CreateUpdatePageModal: React.FC<Props> = (props) => {
|
export const CreateUpdatePageModal: React.FC<Props> = (props) => {
|
||||||
const { isOpen, handleClose, data, user, workspaceSlug, projectId } = props;
|
const { isOpen, handleClose, data, workspaceSlug, projectId } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -42,7 +39,7 @@ export const CreateUpdatePageModal: React.FC<Props> = (props) => {
|
|||||||
|
|
||||||
const createPage = async (payload: IPage) => {
|
const createPage = async (payload: IPage) => {
|
||||||
await pageService
|
await pageService
|
||||||
.createPage(workspaceSlug as string, projectId as string, payload, user)
|
.createPage(workspaceSlug as string, projectId as string, payload)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate(RECENT_PAGES_LIST(projectId as string));
|
mutate(RECENT_PAGES_LIST(projectId as string));
|
||||||
mutate<IPage[]>(
|
mutate<IPage[]>(
|
||||||
@ -64,14 +61,19 @@ export const CreateUpdatePageModal: React.FC<Props> = (props) => {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
onClose();
|
onClose();
|
||||||
|
|
||||||
router.push(`/${workspaceSlug}/projects/${projectId}/pages/${res.id}`);
|
router.push(`/${workspaceSlug}/projects/${projectId}/pages/${res.id}`);
|
||||||
|
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "Page created successfully.",
|
message: "Page created successfully.",
|
||||||
});
|
});
|
||||||
|
trackEvent(
|
||||||
|
'PAGE_CREATE',
|
||||||
|
{
|
||||||
|
...res,
|
||||||
|
caase: "SUCCES"
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
@ -79,12 +81,18 @@ export const CreateUpdatePageModal: React.FC<Props> = (props) => {
|
|||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: "Page could not be created. Please try again.",
|
message: "Page could not be created. Please try again.",
|
||||||
});
|
});
|
||||||
|
trackEvent(
|
||||||
|
'PAGE_CREATE',
|
||||||
|
{
|
||||||
|
case: "FAILED"
|
||||||
|
}
|
||||||
|
)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const updatePage = async (payload: IPage) => {
|
const updatePage = async (payload: IPage) => {
|
||||||
await pageService
|
await pageService
|
||||||
.patchPage(workspaceSlug as string, projectId as string, data?.id ?? "", payload, user)
|
.patchPage(workspaceSlug as string, projectId as string, data?.id ?? "", payload)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate(RECENT_PAGES_LIST(projectId as string));
|
mutate(RECENT_PAGES_LIST(projectId as string));
|
||||||
mutate<IPage[]>(
|
mutate<IPage[]>(
|
||||||
@ -124,6 +132,13 @@ export const CreateUpdatePageModal: React.FC<Props> = (props) => {
|
|||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "Page updated successfully.",
|
message: "Page updated successfully.",
|
||||||
});
|
});
|
||||||
|
trackEvent(
|
||||||
|
'PAGE_UPDATE',
|
||||||
|
{
|
||||||
|
...res,
|
||||||
|
case: "SUCCESS"
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
@ -131,6 +146,12 @@ export const CreateUpdatePageModal: React.FC<Props> = (props) => {
|
|||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: "Page could not be updated. Please try again.",
|
message: "Page could not be updated. Please try again.",
|
||||||
});
|
});
|
||||||
|
trackEvent(
|
||||||
|
'PAGE_UPDATE',
|
||||||
|
{
|
||||||
|
case: "FAILED"
|
||||||
|
}
|
||||||
|
)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ type TConfirmPageDeletionProps = {
|
|||||||
// services
|
// services
|
||||||
const pageService = new PageService();
|
const pageService = new PageService();
|
||||||
|
|
||||||
export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = ({ isOpen, setIsOpen, data, user }) => {
|
export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = ({ isOpen, setIsOpen, data }) => {
|
||||||
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -47,7 +47,7 @@ export const DeletePageModal: React.FC<TConfirmPageDeletionProps> = ({ isOpen, s
|
|||||||
if (!data || !workspaceSlug || !projectId) return;
|
if (!data || !workspaceSlug || !projectId) return;
|
||||||
|
|
||||||
await pageService
|
await pageService
|
||||||
.deletePage(workspaceSlug as string, data.project, data.id, user)
|
.deletePage(workspaceSlug as string, data.project, data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutate(RECENT_PAGES_LIST(projectId as string));
|
mutate(RECENT_PAGES_LIST(projectId as string));
|
||||||
mutate<IPage[]>(
|
mutate<IPage[]>(
|
||||||
|
@ -182,7 +182,7 @@ export const PagesView: React.FC<Props> = observer(({ pages, viewType }) => {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
pageService.patchPage(workspaceSlug.toString(), projectId.toString(), page.id, formData, user).then(() => {
|
pageService.patchPage(workspaceSlug.toString(), projectId.toString(), page.id, formData).then(() => {
|
||||||
mutate(RECENT_PAGES_LIST(projectId.toString()));
|
mutate(RECENT_PAGES_LIST(projectId.toString()));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -85,33 +85,20 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, showBl
|
|||||||
);
|
);
|
||||||
|
|
||||||
await pageService
|
await pageService
|
||||||
.patchPageBlock(
|
.patchPageBlock(workspaceSlug as string, projectId as string, pageId as string, block.id, {
|
||||||
workspaceSlug as string,
|
name: formData.name,
|
||||||
projectId as string,
|
description: formData.description,
|
||||||
pageId as string,
|
description_html: formData.description_html,
|
||||||
block.id,
|
})
|
||||||
{
|
|
||||||
name: formData.name,
|
|
||||||
description: formData.description,
|
|
||||||
description_html: formData.description_html,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutate(PAGE_BLOCKS_LIST(pageId as string));
|
mutate(PAGE_BLOCKS_LIST(pageId as string));
|
||||||
if (block.issue && block.sync)
|
if (block.issue && block.sync)
|
||||||
issueService
|
issueService
|
||||||
.patchIssue(
|
.patchIssue(workspaceSlug as string, projectId as string, block.issue, {
|
||||||
workspaceSlug as string,
|
name: res.name,
|
||||||
projectId as string,
|
description: res.description,
|
||||||
block.issue,
|
description_html: res.description_html,
|
||||||
{
|
})
|
||||||
name: res.name,
|
|
||||||
description: res.description,
|
|
||||||
description_html: res.description_html,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.finally(() => setIsSyncing(false));
|
.finally(() => setIsSyncing(false));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -120,7 +107,7 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, showBl
|
|||||||
if (!workspaceSlug || !projectId || !pageId) return;
|
if (!workspaceSlug || !projectId || !pageId) return;
|
||||||
|
|
||||||
await pageService
|
await pageService
|
||||||
.convertPageBlockToIssue(workspaceSlug as string, projectId as string, pageId as string, block.id, user)
|
.convertPageBlockToIssue(workspaceSlug as string, projectId as string, pageId as string, block.id)
|
||||||
.then((res: IIssue) => {
|
.then((res: IIssue) => {
|
||||||
mutate<IPageBlock[]>(
|
mutate<IPageBlock[]>(
|
||||||
PAGE_BLOCKS_LIST(pageId as string),
|
PAGE_BLOCKS_LIST(pageId as string),
|
||||||
@ -158,7 +145,7 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, showBl
|
|||||||
);
|
);
|
||||||
|
|
||||||
await pageService
|
await pageService
|
||||||
.deletePageBlock(workspaceSlug as string, projectId as string, pageId as string, block.id, user)
|
.deletePageBlock(workspaceSlug as string, projectId as string, pageId as string, block.id)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
@ -174,15 +161,10 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, showBl
|
|||||||
setIAmFeelingLucky(true);
|
setIAmFeelingLucky(true);
|
||||||
|
|
||||||
aiService
|
aiService
|
||||||
.createGptTask(
|
.createGptTask(workspaceSlug as string, projectId as string, {
|
||||||
workspaceSlug as string,
|
prompt: block.name,
|
||||||
projectId as string,
|
task: "Generate a proper description for this issue.",
|
||||||
{
|
})
|
||||||
prompt: block.name,
|
|
||||||
task: "Generate a proper description for this issue.",
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.response === "")
|
if (res.response === "")
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
@ -246,16 +228,9 @@ export const SinglePageBlock: React.FC<Props> = ({ block, projectDetails, showBl
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
pageService.patchPageBlock(
|
pageService.patchPageBlock(workspaceSlug as string, projectId as string, pageId as string, block.id, {
|
||||||
workspaceSlug as string,
|
sync: !block.sync,
|
||||||
projectId as string,
|
});
|
||||||
pageId as string,
|
|
||||||
block.id,
|
|
||||||
{
|
|
||||||
sync: !block.sync,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopyText = () => {
|
const handleCopyText = () => {
|
||||||
|
@ -20,6 +20,8 @@ import { getRandomEmoji, renderEmoji } from "helpers/emoji.helper";
|
|||||||
import { IWorkspaceMember } from "types";
|
import { IWorkspaceMember } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { NETWORK_CHOICES, PROJECT_UNSPLASH_COVERS } from "constants/project";
|
import { NETWORK_CHOICES, PROJECT_UNSPLASH_COVERS } from "constants/project";
|
||||||
|
// track events
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -129,6 +131,14 @@ export const CreateProjectModal: FC<Props> = observer((props) => {
|
|||||||
return projectStore
|
return projectStore
|
||||||
.createProject(workspaceSlug.toString(), payload)
|
.createProject(workspaceSlug.toString(), payload)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
const newPayload = {
|
||||||
|
...payload,
|
||||||
|
id: res.id
|
||||||
|
}
|
||||||
|
trackEvent(
|
||||||
|
"CREATE_PROJECT",
|
||||||
|
newPayload,
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
@ -211,7 +221,7 @@ export const CreateProjectModal: FC<Props> = observer((props) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="absolute right-2 top-2 p-2">
|
<div className="absolute right-2 top-2 p-2">
|
||||||
<button type="button" onClick={handleClose}>
|
<button data-posthog="PROJECT_MODAL_CLOSE" type="button" onClick={handleClose}>
|
||||||
<X className="h-5 w-5 text-white" />
|
<X className="h-5 w-5 text-white" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,6 +12,7 @@ import { Button, Input } from "@plane/ui";
|
|||||||
import type { IProject } from "types";
|
import type { IProject } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type DeleteProjectModal = {
|
type DeleteProjectModal = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -62,6 +63,9 @@ export const DeleteProjectModal: React.FC<DeleteProjectModal> = (props) => {
|
|||||||
if (projectId && projectId.toString() === project.id) router.push(`/${workspaceSlug}/projects`);
|
if (projectId && projectId.toString() === project.id) router.push(`/${workspaceSlug}/projects`);
|
||||||
|
|
||||||
handleClose();
|
handleClose();
|
||||||
|
trackEvent(
|
||||||
|
'DELETE_PROJECT'
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
@ -69,6 +73,9 @@ export const DeleteProjectModal: React.FC<DeleteProjectModal> = (props) => {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
trackEvent(
|
||||||
|
'DELETE_PROJECT/FAIL'
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
|
@ -16,6 +16,7 @@ import { ProjectService } from "services/project";
|
|||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
export interface IProjectDetailsForm {
|
export interface IProjectDetailsForm {
|
||||||
project: IProject;
|
project: IProject;
|
||||||
@ -61,7 +62,11 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
|
|||||||
|
|
||||||
return projectStore
|
return projectStore
|
||||||
.updateProject(workspaceSlug.toString(), project.id, payload)
|
.updateProject(workspaceSlug.toString(), project.id, payload)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
|
trackEvent(
|
||||||
|
'UPDATE_PROJECT',
|
||||||
|
res
|
||||||
|
);
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
@ -69,6 +74,9 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
trackEvent(
|
||||||
|
'UPDATE_PROJECT/FAIL',
|
||||||
|
);
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
|
@ -20,6 +20,7 @@ import { IUser, TUserProjectRole } from "types";
|
|||||||
import { WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
import { WORKSPACE_MEMBERS } from "constants/fetch-keys";
|
||||||
// constants
|
// constants
|
||||||
import { ROLE } from "constants/workspace";
|
import { ROLE } from "constants/workspace";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -52,7 +53,7 @@ const projectMemberService = new ProjectMemberService();
|
|||||||
const workspaceService = new WorkspaceService();
|
const workspaceService = new WorkspaceService();
|
||||||
|
|
||||||
export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
|
export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
|
||||||
const { isOpen, setIsOpen, members, user, onSuccess } = props;
|
const { isOpen, setIsOpen, members, onSuccess } = props;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId } = router.query;
|
const { workspaceSlug, projectId } = router.query;
|
||||||
@ -91,9 +92,12 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
|
|||||||
const payload = { ...formData };
|
const payload = { ...formData };
|
||||||
|
|
||||||
await projectMemberService
|
await projectMemberService
|
||||||
.bulkAddMembersToProject(workspaceSlug.toString(), projectId.toString(), payload, user)
|
.bulkAddMembersToProject(workspaceSlug.toString(), projectId.toString(), payload)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
|
trackEvent(
|
||||||
|
'PROJECT_MEMBER_INVITE',
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
type: "success",
|
type: "success",
|
||||||
|
@ -5,8 +5,6 @@ import { ContrastIcon, FileText, Inbox, Layers } from "lucide-react";
|
|||||||
import { DiceIcon, ToggleSwitch } from "@plane/ui";
|
import { DiceIcon, ToggleSwitch } from "@plane/ui";
|
||||||
// mobx store
|
// mobx store
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// services
|
|
||||||
import { MiscellaneousEventType, TrackEventService } from "services/track_event.service";
|
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// types
|
// types
|
||||||
@ -47,26 +45,6 @@ const PROJECT_FEATURES_LIST = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const getEventType = (feature: string, toggle: boolean): MiscellaneousEventType => {
|
|
||||||
switch (feature) {
|
|
||||||
case "Cycles":
|
|
||||||
return toggle ? "TOGGLE_CYCLE_ON" : "TOGGLE_CYCLE_OFF";
|
|
||||||
case "Modules":
|
|
||||||
return toggle ? "TOGGLE_MODULE_ON" : "TOGGLE_MODULE_OFF";
|
|
||||||
case "Views":
|
|
||||||
return toggle ? "TOGGLE_VIEW_ON" : "TOGGLE_VIEW_OFF";
|
|
||||||
case "Pages":
|
|
||||||
return toggle ? "TOGGLE_PAGES_ON" : "TOGGLE_PAGES_OFF";
|
|
||||||
case "Inbox":
|
|
||||||
return toggle ? "TOGGLE_INBOX_ON" : "TOGGLE_INBOX_OFF";
|
|
||||||
default:
|
|
||||||
throw new Error("Invalid feature");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// services
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export const ProjectFeaturesList: FC<Props> = observer(() => {
|
export const ProjectFeaturesList: FC<Props> = observer(() => {
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -109,17 +87,6 @@ export const ProjectFeaturesList: FC<Props> = observer(() => {
|
|||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
value={currentProjectDetails?.[feature.property as keyof IProject]}
|
value={currentProjectDetails?.[feature.property as keyof IProject]}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
trackEventService.trackMiscellaneousEvent(
|
|
||||||
{
|
|
||||||
workspaceId: (currentProjectDetails?.workspace as any)?.id,
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
projectIdentifier: currentProjectDetails?.identifier,
|
|
||||||
projectName: currentProjectDetails?.name,
|
|
||||||
},
|
|
||||||
getEventType(feature.title, !currentProjectDetails?.[feature.property as keyof IProject]),
|
|
||||||
currentUser
|
|
||||||
);
|
|
||||||
handleSubmit({
|
handleSubmit({
|
||||||
[feature.property]: !currentProjectDetails?.[feature.property as keyof IProject],
|
[feature.property]: !currentProjectDetails?.[feature.property as keyof IProject],
|
||||||
});
|
});
|
||||||
|
@ -18,6 +18,7 @@ import type { IState } from "types";
|
|||||||
import { STATES_LIST } from "constants/fetch-keys";
|
import { STATES_LIST } from "constants/fetch-keys";
|
||||||
// constants
|
// constants
|
||||||
import { GROUP_CHOICES } from "constants/project";
|
import { GROUP_CHOICES } from "constants/project";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data: IState | null;
|
data: IState | null;
|
||||||
@ -87,8 +88,12 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
await projectStateStore
|
await projectStateStore
|
||||||
.createState(workspaceSlug.toString(), projectId.toString(), formData)
|
.createState(workspaceSlug.toString(), projectId.toString(), formData)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
handleClose();
|
handleClose();
|
||||||
|
trackEvent(
|
||||||
|
'STATE_CREATE',
|
||||||
|
res
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
@ -116,10 +121,13 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
await projectStateStore
|
await projectStateStore
|
||||||
.updateState(workspaceSlug.toString(), projectId.toString(), data.id, formData)
|
.updateState(workspaceSlug.toString(), projectId.toString(), data.id, formData)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
mutate(STATES_LIST(projectId.toString()));
|
mutate(STATES_LIST(projectId.toString()));
|
||||||
handleClose();
|
handleClose();
|
||||||
|
trackEvent(
|
||||||
|
'STATE_UPDATE',
|
||||||
|
res
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
@ -161,9 +169,8 @@ export const CreateUpdateStateInline: React.FC<Props> = observer((props) => {
|
|||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<>
|
<>
|
||||||
<Popover.Button
|
<Popover.Button
|
||||||
className={`group inline-flex items-center text-base font-medium focus:outline-none ${
|
className={`group inline-flex items-center text-base font-medium focus:outline-none ${open ? "text-custom-text-100" : "text-custom-text-200"
|
||||||
open ? "text-custom-text-100" : "text-custom-text-200"
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{watch("color") && watch("color") !== "" && (
|
{watch("color") && watch("color") !== "" && (
|
||||||
<span
|
<span
|
||||||
|
@ -13,6 +13,7 @@ import useToast from "hooks/use-toast";
|
|||||||
import { Button } from "@plane/ui";
|
import { Button } from "@plane/ui";
|
||||||
// types
|
// types
|
||||||
import type { IState } from "types";
|
import type { IState } from "types";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -47,7 +48,10 @@ export const DeleteStateModal: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
await projectStateStore
|
await projectStateStore
|
||||||
.deleteState(workspaceSlug.toString(), data.project, data.id)
|
.deleteState(workspaceSlug.toString(), data.project, data.id)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
|
trackEvent(
|
||||||
|
'STATE_DELETE',
|
||||||
|
)
|
||||||
handleClose();
|
handleClose();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
@ -14,6 +14,8 @@ import { Button, CustomSelect, Input } from "@plane/ui";
|
|||||||
import { IWorkspace } from "types";
|
import { IWorkspace } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { ORGANIZATION_SIZE, RESTRICTED_URLS } from "constants/workspace";
|
import { ORGANIZATION_SIZE, RESTRICTED_URLS } from "constants/workspace";
|
||||||
|
// events
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSubmit?: (res: IWorkspace) => Promise<void>;
|
onSubmit?: (res: IWorkspace) => Promise<void>;
|
||||||
@ -71,6 +73,16 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
|
|||||||
await workspaceStore
|
await workspaceStore
|
||||||
.createWorkspace(formData)
|
.createWorkspace(formData)
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
|
const payload = {
|
||||||
|
name: formData.name,
|
||||||
|
slug: formData.slug,
|
||||||
|
workspace_url: formData.url,
|
||||||
|
organization_size: formData.organization_size
|
||||||
|
};
|
||||||
|
trackEvent(
|
||||||
|
"CREATE_WORKSPACE",
|
||||||
|
payload
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
|
@ -12,6 +12,7 @@ import useToast from "hooks/use-toast";
|
|||||||
import { Button, Input } from "@plane/ui";
|
import { Button, Input } from "@plane/ui";
|
||||||
// types
|
// types
|
||||||
import type { IWorkspace } from "types";
|
import type { IWorkspace } from "types";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -57,11 +58,17 @@ export const DeleteWorkspaceModal: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
await workspaceStore
|
await workspaceStore
|
||||||
.deleteWorkspace(data.slug)
|
.deleteWorkspace(data.slug)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
handleClose();
|
handleClose();
|
||||||
|
console.log('DELETE WORKPSACE', res);
|
||||||
router.push("/");
|
router.push("/");
|
||||||
|
const payload = {
|
||||||
|
slug: data.slug
|
||||||
|
};
|
||||||
|
trackEvent(
|
||||||
|
'DELETE_WORKSPACE',
|
||||||
|
payload
|
||||||
|
);
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
|
@ -18,6 +18,7 @@ import { Button, CustomSelect, Input, Spinner } from "@plane/ui";
|
|||||||
import { IWorkspace } from "types";
|
import { IWorkspace } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { ORGANIZATION_SIZE } from "constants/workspace";
|
import { ORGANIZATION_SIZE } from "constants/workspace";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
const defaultValues: Partial<IWorkspace> = {
|
const defaultValues: Partial<IWorkspace> = {
|
||||||
name: "",
|
name: "",
|
||||||
@ -66,12 +67,17 @@ export const WorkspaceDetails: FC = observer(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await updateWorkspace(currentWorkspace.slug, payload)
|
await updateWorkspace(currentWorkspace.slug, payload)
|
||||||
.then(() =>
|
.then((res) => {
|
||||||
|
trackEvent(
|
||||||
|
'UPDATE_WORKSPACE',
|
||||||
|
res
|
||||||
|
)
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
title: "Success",
|
title: "Success",
|
||||||
type: "success",
|
type: "success",
|
||||||
message: "Workspace updated successfully",
|
message: "Workspace updated successfully",
|
||||||
})
|
})
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.catch((err) => console.error(err));
|
.catch((err) => console.error(err));
|
||||||
};
|
};
|
||||||
@ -83,7 +89,7 @@ export const WorkspaceDetails: FC = observer(() => {
|
|||||||
|
|
||||||
fileService.deleteFile(currentWorkspace.id, url).then(() => {
|
fileService.deleteFile(currentWorkspace.id, url).then(() => {
|
||||||
updateWorkspace(currentWorkspace.slug, { logo: "" })
|
updateWorkspace(currentWorkspace.slug, { logo: "" })
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
import { useCallback, useEffect } from "react";
|
|
||||||
import { observer } from "mobx-react-lite";
|
|
||||||
// hooks
|
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
$crisp: any;
|
|
||||||
CRISP_WEBSITE_ID: any;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Crisp = observer(() => {
|
|
||||||
const {
|
|
||||||
user: { currentUser },
|
|
||||||
} = useMobxStore();
|
|
||||||
|
|
||||||
const validateCurrentUser = useCallback(() => {
|
|
||||||
if (currentUser) return currentUser.email;
|
|
||||||
return null;
|
|
||||||
}, [currentUser]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (typeof window && validateCurrentUser()) {
|
|
||||||
window.$crisp = [];
|
|
||||||
window.CRISP_WEBSITE_ID = process.env.NEXT_PUBLIC_CRISP_ID;
|
|
||||||
(function () {
|
|
||||||
var d = document;
|
|
||||||
var s = d.createElement("script");
|
|
||||||
s.src = "https://client.crisp.chat/l.js";
|
|
||||||
s.async = true;
|
|
||||||
d.getElementsByTagName("head")[0].appendChild(s);
|
|
||||||
// defining email when logged in
|
|
||||||
if (validateCurrentUser()) {
|
|
||||||
window.$crisp.push(["set", "user:email", [validateCurrentUser()]]);
|
|
||||||
window.$crisp.push(["do", "chat:hide"]);
|
|
||||||
window.$crisp.push(["do", "chat:close"]);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
}, [validateCurrentUser]);
|
|
||||||
|
|
||||||
return <></>;
|
|
||||||
});
|
|
||||||
export default Crisp;
|
|
@ -8,10 +8,8 @@ import { ProjectService, ProjectMemberService } from "services/project";
|
|||||||
import { CycleService } from "services/cycle.service";
|
import { CycleService } from "services/cycle.service";
|
||||||
import { ModuleService } from "services/module.service";
|
import { ModuleService } from "services/module.service";
|
||||||
import { ViewService } from "services/view.service";
|
import { ViewService } from "services/view.service";
|
||||||
// hooks
|
|
||||||
import useUserAuth from "hooks/use-user-auth";
|
|
||||||
// types
|
// types
|
||||||
import { IIssueFilterOptions, IProjectMember, IUser, IIssueDisplayFilterOptions, IProjectViewProps } from "types";
|
import { IIssueFilterOptions, IProjectMember, IIssueDisplayFilterOptions, IProjectViewProps } from "types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { CYCLE_DETAILS, MODULE_DETAILS, USER_PROJECT_VIEW, VIEW_DETAILS } from "constants/fetch-keys";
|
import { CYCLE_DETAILS, MODULE_DETAILS, USER_PROJECT_VIEW, VIEW_DETAILS } from "constants/fetch-keys";
|
||||||
|
|
||||||
@ -134,58 +132,22 @@ const saveDataToServer = async (workspaceSlug: string, projectId: string, state:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveCycleFilters = async (
|
const saveCycleFilters = async (workspaceSlug: string, projectId: string, cycleId: string, state: any) => {
|
||||||
workspaceSlug: string,
|
await cycleService.patchCycle(workspaceSlug, projectId, cycleId, {
|
||||||
projectId: string,
|
...state,
|
||||||
cycleId: string,
|
});
|
||||||
state: any,
|
|
||||||
user: IUser | undefined
|
|
||||||
) => {
|
|
||||||
await cycleService.patchCycle(
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
cycleId,
|
|
||||||
{
|
|
||||||
...state,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveModuleFilters = async (
|
const saveModuleFilters = async (workspaceSlug: string, projectId: string, moduleId: string, state: any) => {
|
||||||
workspaceSlug: string,
|
await moduleService.patchModule(workspaceSlug, projectId, moduleId, {
|
||||||
projectId: string,
|
...state,
|
||||||
moduleId: string,
|
});
|
||||||
state: any,
|
|
||||||
user: IUser | undefined
|
|
||||||
) => {
|
|
||||||
await moduleService.patchModule(
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
moduleId,
|
|
||||||
{
|
|
||||||
...state,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveViewFilters = async (
|
const saveViewFilters = async (workspaceSlug: string, projectId: string, viewId: string, state: any) => {
|
||||||
workspaceSlug: string,
|
await viewService.patchView(workspaceSlug, projectId, viewId, {
|
||||||
projectId: string,
|
...state,
|
||||||
viewId: string,
|
});
|
||||||
state: any,
|
|
||||||
user: IUser | undefined
|
|
||||||
) => {
|
|
||||||
await viewService.patchView(
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
viewId,
|
|
||||||
{
|
|
||||||
...state,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setNewDefault = async (workspaceSlug: string, projectId: string, state: any) => {
|
const setNewDefault = async (workspaceSlug: string, projectId: string, state: any) => {
|
||||||
@ -214,8 +176,6 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
|
||||||
|
|
||||||
const { user } = useUserAuth();
|
|
||||||
|
|
||||||
const { data: myViewProps, mutate: mutateMyViewProps } = useSWR(
|
const { data: myViewProps, mutate: mutateMyViewProps } = useSWR(
|
||||||
workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null,
|
workspaceSlug && projectId ? USER_PROJECT_VIEW(projectId as string) : null,
|
||||||
workspaceSlug && projectId
|
workspaceSlug && projectId
|
||||||
@ -342,20 +302,14 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
|||||||
};
|
};
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
saveCycleFilters(
|
saveCycleFilters(workspaceSlug.toString(), projectId.toString(), cycleId.toString(), {
|
||||||
workspaceSlug.toString(),
|
view_props: {
|
||||||
projectId.toString(),
|
filters: {
|
||||||
cycleId.toString(),
|
...state.filters,
|
||||||
{
|
...property,
|
||||||
view_props: {
|
|
||||||
filters: {
|
|
||||||
...state.filters,
|
|
||||||
...property,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
user
|
});
|
||||||
);
|
|
||||||
} else if (moduleId) {
|
} else if (moduleId) {
|
||||||
mutateModuleDetails((prevData: any) => {
|
mutateModuleDetails((prevData: any) => {
|
||||||
if (!prevData) return prevData;
|
if (!prevData) return prevData;
|
||||||
@ -371,20 +325,14 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
|||||||
};
|
};
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
saveModuleFilters(
|
saveModuleFilters(workspaceSlug.toString(), projectId.toString(), moduleId.toString(), {
|
||||||
workspaceSlug.toString(),
|
view_props: {
|
||||||
projectId.toString(),
|
filters: {
|
||||||
moduleId.toString(),
|
...state.filters,
|
||||||
{
|
...property,
|
||||||
view_props: {
|
|
||||||
filters: {
|
|
||||||
...state.filters,
|
|
||||||
...property,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
user
|
});
|
||||||
);
|
|
||||||
} else if (viewId) {
|
} else if (viewId) {
|
||||||
mutateViewDetails((prevData: any) => {
|
mutateViewDetails((prevData: any) => {
|
||||||
if (!prevData) return prevData;
|
if (!prevData) return prevData;
|
||||||
@ -397,18 +345,12 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
|||||||
};
|
};
|
||||||
}, false);
|
}, false);
|
||||||
if (saveToServer)
|
if (saveToServer)
|
||||||
saveViewFilters(
|
saveViewFilters(workspaceSlug as string, projectId as string, viewId as string, {
|
||||||
workspaceSlug as string,
|
query_data: {
|
||||||
projectId as string,
|
...state.filters,
|
||||||
viewId as string,
|
...property,
|
||||||
{
|
|
||||||
query_data: {
|
|
||||||
...state.filters,
|
|
||||||
...property,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
user
|
});
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
mutateMyViewProps((prevData: any) => {
|
mutateMyViewProps((prevData: any) => {
|
||||||
if (!prevData) return prevData;
|
if (!prevData) return prevData;
|
||||||
@ -445,7 +387,6 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
|
|||||||
mutateModuleDetails,
|
mutateModuleDetails,
|
||||||
viewId,
|
viewId,
|
||||||
mutateViewDetails,
|
mutateViewDetails,
|
||||||
user,
|
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
13
web/helpers/event-tracker.helper.ts
Normal file
13
web/helpers/event-tracker.helper.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import posthog from "posthog-js";
|
||||||
|
|
||||||
|
export const trackEvent = (eventName: string, payload: object | [] | null = null) => {
|
||||||
|
try {
|
||||||
|
console.log(eventName);
|
||||||
|
posthog?.capture(eventName, {
|
||||||
|
...payload,
|
||||||
|
});
|
||||||
|
console.log(payload);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
12
web/helpers/user.helper.ts
Normal file
12
web/helpers/user.helper.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export const getUserRole = (role: number) => {
|
||||||
|
switch (role) {
|
||||||
|
case 5:
|
||||||
|
return "GUEST";
|
||||||
|
case 10:
|
||||||
|
return "VIEWER";
|
||||||
|
case 15:
|
||||||
|
return "MEMBER";
|
||||||
|
case 20:
|
||||||
|
return "ADMIN";
|
||||||
|
}
|
||||||
|
};
|
@ -1,5 +1,4 @@
|
|||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
// fetch keys
|
// fetch keys
|
||||||
import { COMMENT_REACTION_LIST } from "constants/fetch-keys";
|
import { COMMENT_REACTION_LIST } from "constants/fetch-keys";
|
||||||
// services
|
// services
|
||||||
@ -52,8 +51,7 @@ const useCommentReaction = (
|
|||||||
workspaceSlug.toString(),
|
workspaceSlug.toString(),
|
||||||
projectId.toString(),
|
projectId.toString(),
|
||||||
commendId.toString(),
|
commendId.toString(),
|
||||||
{ reaction },
|
{ reaction }
|
||||||
user.user
|
|
||||||
);
|
);
|
||||||
|
|
||||||
mutateCommentReactions((prev: any) => [...(prev || []), data]);
|
mutateCommentReactions((prev: any) => [...(prev || []), data]);
|
||||||
@ -77,8 +75,7 @@ const useCommentReaction = (
|
|||||||
workspaceSlug.toString(),
|
workspaceSlug.toString(),
|
||||||
projectId.toString(),
|
projectId.toString(),
|
||||||
commendId.toString(),
|
commendId.toString(),
|
||||||
reaction,
|
reaction
|
||||||
user.user
|
|
||||||
);
|
);
|
||||||
|
|
||||||
mutateCommentReactions();
|
mutateCommentReactions();
|
||||||
|
@ -47,8 +47,7 @@ const useIssueReaction = (
|
|||||||
workspaceSlug.toString(),
|
workspaceSlug.toString(),
|
||||||
projectId.toString(),
|
projectId.toString(),
|
||||||
issueId.toString(),
|
issueId.toString(),
|
||||||
{ reaction },
|
{ reaction }
|
||||||
user.user
|
|
||||||
);
|
);
|
||||||
|
|
||||||
mutateReaction((prev: any) => [...(prev || []), data]);
|
mutateReaction((prev: any) => [...(prev || []), data]);
|
||||||
@ -72,8 +71,7 @@ const useIssueReaction = (
|
|||||||
workspaceSlug.toString(),
|
workspaceSlug.toString(),
|
||||||
projectId.toString(),
|
projectId.toString(),
|
||||||
issueId.toString(),
|
issueId.toString(),
|
||||||
reaction,
|
reaction
|
||||||
user.user
|
|
||||||
);
|
);
|
||||||
|
|
||||||
mutateReaction();
|
mutateReaction();
|
||||||
|
46
web/lib/app-provider.tsx
Normal file
46
web/lib/app-provider.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { FC, ReactNode } from "react";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
import Router from "next/router";
|
||||||
|
import NProgress from "nprogress";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
// mobx store provider
|
||||||
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
|
// dynamic imports
|
||||||
|
const StoreWrapper = dynamic(() => import("lib/wrappers/store-wrapper"), { ssr: false });
|
||||||
|
const PosthogWrapper = dynamic(() => import("lib/wrappers/posthog-wrapper"), { ssr: false });
|
||||||
|
const CrispWrapper = dynamic(() => import("lib/wrappers/crisp-wrapper"), { ssr: false });
|
||||||
|
|
||||||
|
// nprogress
|
||||||
|
NProgress.configure({ showSpinner: false });
|
||||||
|
Router.events.on("routeChangeStart", NProgress.start);
|
||||||
|
Router.events.on("routeChangeError", NProgress.done);
|
||||||
|
Router.events.on("routeChangeComplete", NProgress.done);
|
||||||
|
|
||||||
|
export interface IAppProvider {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AppProvider: FC<IAppProvider> = observer((props) => {
|
||||||
|
const { children } = props;
|
||||||
|
// store
|
||||||
|
const {
|
||||||
|
user: { currentUser, currentWorkspaceRole, currentProjectRole },
|
||||||
|
appConfig: { envConfig },
|
||||||
|
} = useMobxStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StoreWrapper>
|
||||||
|
<CrispWrapper user={currentUser}>
|
||||||
|
<PosthogWrapper
|
||||||
|
user={currentUser}
|
||||||
|
workspaceRole={currentWorkspaceRole}
|
||||||
|
projectRole={currentProjectRole}
|
||||||
|
posthogAPIKey={envConfig?.posthog_api_key || null}
|
||||||
|
posthogHost={envConfig?.posthog_host || null}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</PosthogWrapper>
|
||||||
|
</CrispWrapper>
|
||||||
|
</StoreWrapper>
|
||||||
|
);
|
||||||
|
});
|
195
web/lib/auth.ts
195
web/lib/auth.ts
@ -1,195 +0,0 @@
|
|||||||
// cookies
|
|
||||||
import { convertCookieStringToObject } from "./cookie";
|
|
||||||
// types
|
|
||||||
import type { IProjectMember, IUser, IWorkspace, IWorkspaceMember } from "types";
|
|
||||||
// helper
|
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
|
||||||
|
|
||||||
export const requiredAuth = async (cookie?: string) => {
|
|
||||||
const cookies = convertCookieStringToObject(cookie);
|
|
||||||
const token = cookies?.accessToken;
|
|
||||||
|
|
||||||
if (!token) return null;
|
|
||||||
|
|
||||||
let user: IUser | null = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await fetch(`${API_BASE_URL}/api/users/me/`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => data);
|
|
||||||
|
|
||||||
user = data.user;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
user = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const requiredAdmin = async (workspaceSlug: string, projectId: string, cookie?: string) => {
|
|
||||||
const user = await requiredAuth(cookie);
|
|
||||||
|
|
||||||
if (!user) return null;
|
|
||||||
|
|
||||||
const cookies = convertCookieStringToObject(cookie);
|
|
||||||
const token = cookies?.accessToken;
|
|
||||||
|
|
||||||
let memberDetail: IProjectMember | null = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await fetch(
|
|
||||||
`${API_BASE_URL}/api/workspaces/${workspaceSlug}/projects/${projectId}/project-members/me/`,
|
|
||||||
{
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => data);
|
|
||||||
|
|
||||||
memberDetail = data;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
memberDetail = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return memberDetail || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const requiredWorkspaceAdmin = async (workspaceSlug: string, cookie?: string) => {
|
|
||||||
const user = await requiredAuth(cookie);
|
|
||||||
|
|
||||||
if (!user) return null;
|
|
||||||
|
|
||||||
const cookies = convertCookieStringToObject(cookie);
|
|
||||||
const token = cookies?.accessToken;
|
|
||||||
|
|
||||||
let memberDetail: IWorkspaceMember | null = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await fetch(`${API_BASE_URL}/api/workspaces/${workspaceSlug}/workspace-members/me/`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => data);
|
|
||||||
|
|
||||||
memberDetail = data;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
memberDetail = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return memberDetail || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const homePageRedirect = async (cookie?: string) => {
|
|
||||||
const user = await requiredAuth(cookie);
|
|
||||||
|
|
||||||
if (!user)
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: "/",
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!user.is_onboarded)
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: "/onboarding",
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let workspaces: IWorkspace[] = [];
|
|
||||||
|
|
||||||
const cookies = convertCookieStringToObject(cookie);
|
|
||||||
const token = cookies?.accessToken;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const data = await fetch(`${API_BASE_URL}/api/users/me/workspaces/`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => data);
|
|
||||||
|
|
||||||
workspaces = data;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: "/error",
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const lastActiveWorkspace = workspaces.find((workspace) => workspace.id === user.last_workspace_id);
|
|
||||||
|
|
||||||
if (lastActiveWorkspace) {
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: `/${lastActiveWorkspace.slug}`,
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} else if (workspaces.length > 0) {
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: `/${workspaces[0].slug}`,
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const invitations = await fetch(`${API_BASE_URL}/api/users/me/invitations/workspaces/`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then((res) => res.json())
|
|
||||||
.then((data) => data)
|
|
||||||
.catch((e) => {
|
|
||||||
console.error(e);
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: "/error",
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
if (invitations.length > 0)
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: "/invitations",
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
redirect: {
|
|
||||||
destination: "/create-workspace",
|
|
||||||
permanent: false,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,16 +0,0 @@
|
|||||||
export const convertCookieStringToObject = (cookieHeader: string | undefined) => {
|
|
||||||
const list: any = {};
|
|
||||||
if (!cookieHeader) return list;
|
|
||||||
|
|
||||||
cookieHeader.split(`;`).forEach(function (cookie) {
|
|
||||||
// eslint-disable-next-line prefer-const
|
|
||||||
let [name, ...rest] = cookie.split(`=`);
|
|
||||||
name = name?.trim();
|
|
||||||
if (!name) return;
|
|
||||||
const value = rest.join(`=`).trim();
|
|
||||||
if (!value) return;
|
|
||||||
list[name] = decodeURIComponent(value);
|
|
||||||
});
|
|
||||||
|
|
||||||
return list;
|
|
||||||
};
|
|
40
web/lib/wrappers/crisp-wrapper.tsx
Normal file
40
web/lib/wrappers/crisp-wrapper.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { useEffect, ReactNode, FC } from "react";
|
||||||
|
// hooks
|
||||||
|
import { IUser } from "types";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
$crisp: any;
|
||||||
|
CRISP_WEBSITE_ID: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICrispWrapper {
|
||||||
|
children: ReactNode;
|
||||||
|
user: IUser | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CrispWrapper: FC<ICrispWrapper> = (props) => {
|
||||||
|
const { children, user } = props;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window && user?.email) {
|
||||||
|
window.$crisp = [];
|
||||||
|
window.CRISP_WEBSITE_ID = process.env.NEXT_PUBLIC_CRISP_ID;
|
||||||
|
(function () {
|
||||||
|
var d = document;
|
||||||
|
var s = d.createElement("script");
|
||||||
|
s.src = "https://client.crisp.chat/l.js";
|
||||||
|
s.async = true;
|
||||||
|
d.getElementsByTagName("head")[0].appendChild(s);
|
||||||
|
window.$crisp.push(["set", "user:email", [user.email]]);
|
||||||
|
window.$crisp.push(["do", "chat:hide"]);
|
||||||
|
window.$crisp.push(["do", "chat:close"]);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}, [user?.email]);
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CrispWrapper;
|
72
web/lib/wrappers/posthog-wrapper.tsx
Normal file
72
web/lib/wrappers/posthog-wrapper.tsx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { FC, ReactNode, useEffect } from "react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import posthog from "posthog-js";
|
||||||
|
import { PostHogProvider } from "posthog-js/react";
|
||||||
|
// mobx store provider
|
||||||
|
import { IUser } from "types";
|
||||||
|
// helpers
|
||||||
|
import { getUserRole } from "helpers/user.helper";
|
||||||
|
|
||||||
|
export interface IPosthogWrapper {
|
||||||
|
children: ReactNode;
|
||||||
|
user: IUser | null;
|
||||||
|
workspaceRole: number | undefined;
|
||||||
|
projectRole: number | undefined;
|
||||||
|
posthogAPIKey: string | null;
|
||||||
|
posthogHost: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PosthogWrapper: FC<IPosthogWrapper> = (props) => {
|
||||||
|
const { children, user, workspaceRole, projectRole, posthogAPIKey, posthogHost } = props;
|
||||||
|
// router
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (user) {
|
||||||
|
// Identify sends an event, so you want may want to limit how often you call it
|
||||||
|
posthog?.identify(user.email, {
|
||||||
|
email: user.email,
|
||||||
|
first_name: user.first_name,
|
||||||
|
last_name: user.last_name,
|
||||||
|
id: user.id,
|
||||||
|
workspace_role: workspaceRole ? getUserRole(workspaceRole) : undefined,
|
||||||
|
project_role: projectRole ? getUserRole(projectRole) : undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [user, workspaceRole, projectRole]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (posthogAPIKey && posthogHost) {
|
||||||
|
posthog.init(posthogAPIKey, {
|
||||||
|
api_host: posthogHost || "https://app.posthog.com",
|
||||||
|
// Enable debug mode in development
|
||||||
|
loaded: (posthog) => {
|
||||||
|
if (process.env.NODE_ENV === "development") posthog.debug();
|
||||||
|
},
|
||||||
|
autocapture: false,
|
||||||
|
capture_pageview: false, // Disable automatic pageview capture, as we capture manually
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Track page views
|
||||||
|
const handleRouteChange = () => {
|
||||||
|
posthog?.capture("$pageview");
|
||||||
|
};
|
||||||
|
router.events.on("routeChangeComplete", handleRouteChange);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
router.events.off("routeChangeComplete", handleRouteChange);
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (posthogAPIKey) {
|
||||||
|
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
|
||||||
|
}
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PosthogWrapper;
|
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState, FC } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { useTheme } from "next-themes";
|
import { useTheme } from "next-themes";
|
||||||
@ -8,7 +8,12 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
|||||||
// helpers
|
// helpers
|
||||||
import { applyTheme, unsetCustomCssVariables } from "helpers/theme.helper";
|
import { applyTheme, unsetCustomCssVariables } from "helpers/theme.helper";
|
||||||
|
|
||||||
const MobxStoreInit = observer(() => {
|
interface IStoreWrapper {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StoreWrapper: FC<IStoreWrapper> = observer((props) => {
|
||||||
|
const { children } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, cycleId, moduleId, globalViewId, viewId, inboxId } = router.query;
|
const { workspaceSlug, projectId, cycleId, moduleId, globalViewId, viewId, inboxId } = router.query;
|
||||||
@ -86,7 +91,7 @@ const MobxStoreInit = observer(() => {
|
|||||||
setInboxId,
|
setInboxId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return <></>;
|
return <>{children}</>;
|
||||||
});
|
});
|
||||||
|
|
||||||
export default MobxStoreInit;
|
export default StoreWrapper;
|
@ -41,6 +41,7 @@
|
|||||||
"next-pwa": "^5.6.0",
|
"next-pwa": "^5.6.0",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
|
"posthog-js": "^1.88.4",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-datepicker": "^4.8.0",
|
"react-datepicker": "^4.8.0",
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import React, { Fragment, useEffect, ReactElement } from "react";
|
import React, { Fragment, ReactElement } from "react";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
// mobx store
|
// mobx store
|
||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// services
|
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// layouts
|
// layouts
|
||||||
import { AppLayout } from "layouts/app-layout";
|
import { AppLayout } from "layouts/app-layout";
|
||||||
// components
|
// components
|
||||||
@ -21,40 +18,13 @@ import { ANALYTICS_TABS } from "constants/analytics";
|
|||||||
// type
|
// type
|
||||||
import { NextPageWithLayout } from "types/app";
|
import { NextPageWithLayout } from "types/app";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
const AnalyticsPage: NextPageWithLayout = observer(() => {
|
const AnalyticsPage: NextPageWithLayout = observer(() => {
|
||||||
// router
|
|
||||||
const router = useRouter();
|
|
||||||
const { workspaceSlug } = router.query;
|
|
||||||
// store
|
// store
|
||||||
const {
|
const {
|
||||||
project: { workspaceProjects },
|
project: { workspaceProjects },
|
||||||
user: { currentUser },
|
|
||||||
commandPalette: { toggleCreateProjectModal },
|
commandPalette: { toggleCreateProjectModal },
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
|
|
||||||
const trackAnalyticsEvent = (tab: string) => {
|
|
||||||
if (!currentUser) return;
|
|
||||||
const eventPayload = {
|
|
||||||
workspaceSlug: workspaceSlug?.toString(),
|
|
||||||
};
|
|
||||||
const eventType =
|
|
||||||
tab === "scope_and_demand" ? "WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS" : "WORKSPACE_CUSTOM_ANALYTICS";
|
|
||||||
trackEventService.trackAnalyticsEvent(eventPayload, eventType, currentUser);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!workspaceSlug) return;
|
|
||||||
|
|
||||||
if (currentUser && workspaceSlug)
|
|
||||||
trackEventService.trackAnalyticsEvent(
|
|
||||||
{ workspaceSlug: workspaceSlug?.toString() },
|
|
||||||
"WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS",
|
|
||||||
currentUser
|
|
||||||
);
|
|
||||||
}, [currentUser, workspaceSlug]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{workspaceProjects && workspaceProjects.length > 0 ? (
|
{workspaceProjects && workspaceProjects.length > 0 ? (
|
||||||
@ -69,7 +39,7 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
|
|||||||
selected ? "bg-custom-background-80" : ""
|
selected ? "bg-custom-background-80" : ""
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
onClick={() => trackAnalyticsEvent(tab.key)}
|
onClick={() => {}}
|
||||||
>
|
>
|
||||||
{tab.title}
|
{tab.title}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -5,7 +5,6 @@ import { useForm } from "react-hook-form";
|
|||||||
// services
|
// services
|
||||||
import { IssueService, IssueArchiveService } from "services/issue";
|
import { IssueService, IssueArchiveService } from "services/issue";
|
||||||
// hooks
|
// hooks
|
||||||
import useUserAuth from "hooks/use-user-auth";
|
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// layouts
|
// layouts
|
||||||
import { AppLayout } from "layouts/app-layout";
|
import { AppLayout } from "layouts/app-layout";
|
||||||
@ -45,7 +44,6 @@ const ArchivedIssueDetailsPage: NextPageWithLayout = () => {
|
|||||||
// states
|
// states
|
||||||
const [isRestoring, setIsRestoring] = useState(false);
|
const [isRestoring, setIsRestoring] = useState(false);
|
||||||
// hooks
|
// hooks
|
||||||
const { user } = useUserAuth();
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const { data: issueDetails, mutate: mutateIssueDetails } = useSWR<IIssue | undefined>(
|
const { data: issueDetails, mutate: mutateIssueDetails } = useSWR<IIssue | undefined>(
|
||||||
@ -86,7 +84,7 @@ const ArchivedIssueDetailsPage: NextPageWithLayout = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.patchIssue(workspaceSlug as string, projectId as string, archivedIssueId as string, payload, user)
|
.patchIssue(workspaceSlug as string, projectId as string, archivedIssueId as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutateIssueDetails();
|
mutateIssueDetails();
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(archivedIssueId as string));
|
mutate(PROJECT_ISSUES_ACTIVITY(archivedIssueId as string));
|
||||||
@ -95,7 +93,7 @@ const ArchivedIssueDetailsPage: NextPageWithLayout = () => {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[workspaceSlug, archivedIssueId, projectId, mutateIssueDetails, user]
|
[workspaceSlug, archivedIssueId, projectId, mutateIssueDetails]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -22,6 +22,7 @@ import { NextPageWithLayout } from "types/app";
|
|||||||
import { CYCLE_TAB_LIST, CYCLE_VIEW_LAYOUTS } from "constants/cycle";
|
import { CYCLE_TAB_LIST, CYCLE_VIEW_LAYOUTS } from "constants/cycle";
|
||||||
// lib cookie
|
// lib cookie
|
||||||
import { setLocalStorage, getLocalStorage } from "lib/local-storage";
|
import { setLocalStorage, getLocalStorage } from "lib/local-storage";
|
||||||
|
// TODO: use-local-storage hook instead of lib file.
|
||||||
|
|
||||||
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
||||||
const [createModal, setCreateModal] = useState(false);
|
const [createModal, setCreateModal] = useState(false);
|
||||||
|
@ -4,8 +4,6 @@ import useSWR, { mutate } from "swr";
|
|||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
// services
|
// services
|
||||||
import { IssueService } from "services/issue";
|
import { IssueService } from "services/issue";
|
||||||
// hooks
|
|
||||||
import useUserAuth from "hooks/use-user-auth";
|
|
||||||
// layouts
|
// layouts
|
||||||
import { AppLayout } from "layouts/app-layout";
|
import { AppLayout } from "layouts/app-layout";
|
||||||
// components
|
// components
|
||||||
@ -43,8 +41,6 @@ const IssueDetailsPage: NextPageWithLayout = () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, issueId } = router.query;
|
const { workspaceSlug, projectId, issueId } = router.query;
|
||||||
|
|
||||||
const { user } = useUserAuth();
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: issueDetails,
|
data: issueDetails,
|
||||||
mutate: mutateIssueDetails,
|
mutate: mutateIssueDetails,
|
||||||
@ -85,7 +81,7 @@ const IssueDetailsPage: NextPageWithLayout = () => {
|
|||||||
delete payload.issue_relations;
|
delete payload.issue_relations;
|
||||||
|
|
||||||
await issueService
|
await issueService
|
||||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
mutateIssueDetails();
|
mutateIssueDetails();
|
||||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||||
@ -94,7 +90,7 @@ const IssueDetailsPage: NextPageWithLayout = () => {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[workspaceSlug, issueId, projectId, mutateIssueDetails, user]
|
[workspaceSlug, issueId, projectId, mutateIssueDetails]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -105,18 +105,16 @@ const PageDetailsPage: NextPageWithLayout = () => {
|
|||||||
|
|
||||||
if (!formData.name || formData.name.length === 0 || formData.name === "") return;
|
if (!formData.name || formData.name.length === 0 || formData.name === "") return;
|
||||||
|
|
||||||
await pageService
|
await pageService.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData).then(() => {
|
||||||
.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData, user)
|
mutate<IPage>(
|
||||||
.then(() => {
|
PAGE_DETAILS(pageId as string),
|
||||||
mutate<IPage>(
|
(prevData) => ({
|
||||||
PAGE_DETAILS(pageId as string),
|
...prevData,
|
||||||
(prevData) => ({
|
...formData,
|
||||||
...prevData,
|
}),
|
||||||
...formData,
|
false
|
||||||
}),
|
);
|
||||||
false
|
});
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const partialUpdatePage = async (formData: Partial<IPage>) => {
|
const partialUpdatePage = async (formData: Partial<IPage>) => {
|
||||||
@ -131,11 +129,9 @@ const PageDetailsPage: NextPageWithLayout = () => {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
await pageService
|
await pageService.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData).then(() => {
|
||||||
.patchPage(workspaceSlug as string, projectId as string, pageId as string, formData, user)
|
mutate(PAGE_DETAILS(pageId as string));
|
||||||
.then(() => {
|
});
|
||||||
mutate(PAGE_DETAILS(pageId as string));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddToFavorites = () => {
|
const handleAddToFavorites = () => {
|
||||||
@ -209,16 +205,9 @@ const PageDetailsPage: NextPageWithLayout = () => {
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
pageService.patchPageBlock(
|
pageService.patchPageBlock(workspaceSlug as string, projectId as string, pageId as string, result.draggableId, {
|
||||||
workspaceSlug as string,
|
sort_order: newSortOrder,
|
||||||
projectId as string,
|
});
|
||||||
pageId as string,
|
|
||||||
result.draggableId,
|
|
||||||
{
|
|
||||||
sort_order: newSortOrder,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopyText = () => {
|
const handleCopyText = () => {
|
||||||
|
@ -17,6 +17,7 @@ import { Search } from "lucide-react";
|
|||||||
// types
|
// types
|
||||||
import { NextPageWithLayout } from "types/app";
|
import { NextPageWithLayout } from "types/app";
|
||||||
import { IWorkspaceBulkInviteFormData } from "types";
|
import { IWorkspaceBulkInviteFormData } from "types";
|
||||||
|
import { trackEvent } from "helpers/event-tracker.helper";
|
||||||
|
|
||||||
const WorkspaceMembersSettingsPage: NextPageWithLayout = observer(() => {
|
const WorkspaceMembersSettingsPage: NextPageWithLayout = observer(() => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -35,21 +36,23 @@ const WorkspaceMembersSettingsPage: NextPageWithLayout = observer(() => {
|
|||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
|
|
||||||
return inviteMembersToWorkspace(workspaceSlug.toString(), data)
|
return inviteMembersToWorkspace(workspaceSlug.toString(), data)
|
||||||
.then(async () => {
|
.then(async (res) => {
|
||||||
setInviteModal(false);
|
setInviteModal(false);
|
||||||
|
trackEvent("WORKSPACE_USER_INVITE");
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "success",
|
type: "success",
|
||||||
title: "Success!",
|
title: "Success!",
|
||||||
message: "Invitations sent successfully.",
|
message: "Invitations sent successfully.",
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) =>
|
.catch((err) => {
|
||||||
|
trackEvent("WORKSPACE_USER_INVITE/FAIL");
|
||||||
setToastAlert({
|
setToastAlert({
|
||||||
type: "error",
|
type: "error",
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
message: `${err.error ?? "Something went wrong. Please try again."}`,
|
message: `${err.error ?? "Something went wrong. Please try again."}`,
|
||||||
})
|
});
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { ReactElement } from "react";
|
import { ReactElement } from "react";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import dynamic from "next/dynamic";
|
|
||||||
import Router from "next/router";
|
|
||||||
import { AppProps } from "next/app";
|
import { AppProps } from "next/app";
|
||||||
import { ThemeProvider } from "next-themes";
|
import { ThemeProvider } from "next-themes";
|
||||||
import NProgress from "nprogress";
|
|
||||||
// styles
|
// styles
|
||||||
import "styles/globals.css";
|
import "styles/globals.css";
|
||||||
import "styles/editor.css";
|
import "styles/editor.css";
|
||||||
@ -19,18 +16,10 @@ import { THEMES } from "constants/themes";
|
|||||||
import { SITE_TITLE } from "constants/seo-variables";
|
import { SITE_TITLE } from "constants/seo-variables";
|
||||||
// mobx store provider
|
// mobx store provider
|
||||||
import { MobxStoreProvider } from "lib/mobx/store-provider";
|
import { MobxStoreProvider } from "lib/mobx/store-provider";
|
||||||
import MobxStoreInit from "lib/mobx/store-init";
|
import { AppProvider } from "lib/app-provider";
|
||||||
// types
|
// types
|
||||||
import { NextPageWithLayout } from "types/app";
|
import { NextPageWithLayout } from "types/app";
|
||||||
|
|
||||||
const CrispWithNoSSR = dynamic(() => import("constants/crisp"), { ssr: false });
|
|
||||||
|
|
||||||
// nprogress
|
|
||||||
NProgress.configure({ showSpinner: false });
|
|
||||||
Router.events.on("routeChangeStart", NProgress.start);
|
|
||||||
Router.events.on("routeChangeError", NProgress.done);
|
|
||||||
Router.events.on("routeChangeComplete", NProgress.done);
|
|
||||||
|
|
||||||
type AppPropsWithLayout = AppProps & {
|
type AppPropsWithLayout = AppProps & {
|
||||||
Component: NextPageWithLayout;
|
Component: NextPageWithLayout;
|
||||||
};
|
};
|
||||||
@ -47,9 +36,7 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
|
|||||||
<MobxStoreProvider {...pageProps}>
|
<MobxStoreProvider {...pageProps}>
|
||||||
<ThemeProvider themes={THEMES} defaultTheme="system">
|
<ThemeProvider themes={THEMES} defaultTheme="system">
|
||||||
<ToastContextProvider>
|
<ToastContextProvider>
|
||||||
<CrispWithNoSSR />
|
<AppProvider>{getLayout(<Component {...pageProps} />)}</AppProvider>
|
||||||
<MobxStoreInit />
|
|
||||||
{getLayout(<Component {...pageProps} />)}
|
|
||||||
</ToastContextProvider>
|
</ToastContextProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</MobxStoreProvider>
|
</MobxStoreProvider>
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
|
||||||
// jitsu
|
|
||||||
import { createClient } from "@jitsu/nextjs";
|
|
||||||
|
|
||||||
const jitsuClient = createClient({
|
|
||||||
key: process.env.JITSU_TRACKER_ACCESS_KEY || "",
|
|
||||||
tracking_host: process.env.JITSU_TRACKER_HOST || "",
|
|
||||||
});
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
const { eventName, user, extra } = req.body;
|
|
||||||
|
|
||||||
if (!eventName) {
|
|
||||||
return res.status(400).json({ message: "Bad request" });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user) return res.status(401).json({ message: "Unauthorized" });
|
|
||||||
|
|
||||||
jitsuClient
|
|
||||||
.id({
|
|
||||||
id: user?.id,
|
|
||||||
email: user?.email,
|
|
||||||
first_name: user?.first_name,
|
|
||||||
last_name: user?.last_name,
|
|
||||||
display_name: user?.display_name,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
jitsuClient.track(eventName, {
|
|
||||||
...extra,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
res.status(200).json({ message: "success" });
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
import axios from "axios";
|
|
||||||
import type { NextApiRequest, NextApiResponse } from "next";
|
|
||||||
|
|
||||||
const unsplashKey = process.env.UNSPLASH_ACCESS_KEY;
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
try {
|
|
||||||
const { query, page, per_page = 20 } = req.query;
|
|
||||||
|
|
||||||
const url = query
|
|
||||||
? `https://api.unsplash.com/search/photos/?client_id=${unsplashKey}&query=${query}&page=${page}&per_page=${per_page}`
|
|
||||||
: `https://api.unsplash.com/photos/?client_id=${unsplashKey}&page=${page}&per_page=${per_page}`;
|
|
||||||
|
|
||||||
const response = await axios({
|
|
||||||
method: "GET",
|
|
||||||
url,
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
res.status(200).json(response?.data);
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ message: "Failed to fetch unsplash", error });
|
|
||||||
}
|
|
||||||
}
|
|
@ -36,15 +36,10 @@ const WorkspaceInvitationPage: NextPageWithLayout = () => {
|
|||||||
const handleAccept = () => {
|
const handleAccept = () => {
|
||||||
if (!invitationDetail) return;
|
if (!invitationDetail) return;
|
||||||
workspaceService
|
workspaceService
|
||||||
.joinWorkspace(
|
.joinWorkspace(invitationDetail.workspace.slug, invitationDetail.id, {
|
||||||
invitationDetail.workspace.slug,
|
accepted: true,
|
||||||
invitationDetail.id,
|
email: invitationDetail.email,
|
||||||
{
|
})
|
||||||
accepted: true,
|
|
||||||
email: invitationDetail.email,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (email === user?.email) {
|
if (email === user?.email) {
|
||||||
router.push("/invitations");
|
router.push("/invitations");
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import { IUser, IGptResponse } from "types";
|
import { IGptResponse } from "types";
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class AIService extends APIService {
|
export class AIService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -15,14 +12,10 @@ export class AIService extends APIService {
|
|||||||
async createGptTask(
|
async createGptTask(
|
||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
data: { prompt: string; task: string },
|
data: { prompt: string; task: string }
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IGptResponse> {
|
): Promise<IGptResponse> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/ai-assistant/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/ai-assistant/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackAskGptEvent(response?.data, "ASK_GPT", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import type { CycleDateCheckData, IUser, ICycle, IIssue } from "types";
|
import type { CycleDateCheckData, ICycle, IIssue } from "types";
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class CycleService extends APIService {
|
export class CycleService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createCycle(workspaceSlug: string, projectId: string, data: any, user: any): Promise<any> {
|
async createCycle(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackCycleEvent(response?.data, "CYCLE_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -71,29 +65,17 @@ export class CycleService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchCycle(
|
async patchCycle(workspaceSlug: string, projectId: string, cycleId: string, data: Partial<ICycle>): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
cycleId: string,
|
|
||||||
data: Partial<ICycle>,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
if (user) trackEventService.trackCycleEvent(response?.data, "CYCLE_UPDATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteCycle(workspaceSlug: string, projectId: string, cycleId: string, user: IUser | undefined): Promise<any> {
|
async deleteCycle(workspaceSlug: string, projectId: string, cycleId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackCycleEvent(response?.data, "CYCLE_DELETE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
import type { IInboxIssue, IInbox, TInboxStatus, IUser, IInboxQueryParams } from "types";
|
import type { IInboxIssue, IInbox, TInboxStatus, IInboxQueryParams } from "types";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class InboxService extends APIService {
|
export class InboxService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -70,16 +67,12 @@ export class InboxService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
inboxId: string,
|
inboxId: string,
|
||||||
inboxIssueId: string,
|
inboxIssueId: string
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/${inboxIssueId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/${inboxIssueId}/`
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
if (user) trackEventService.trackInboxEvent(response?.data, "INBOX_ISSUE_DELETE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -90,25 +83,13 @@ export class InboxService extends APIService {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
inboxId: string,
|
inboxId: string,
|
||||||
inboxIssueId: string,
|
inboxIssueId: string,
|
||||||
data: TInboxStatus,
|
data: TInboxStatus
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IInboxIssue> {
|
): Promise<IInboxIssue> {
|
||||||
return this.patch(
|
return this.patch(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/${inboxIssueId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/${inboxIssueId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
const action =
|
|
||||||
data.status === -1
|
|
||||||
? "INBOX_ISSUE_REJECTED"
|
|
||||||
: data.status === 0
|
|
||||||
? "INBOX_ISSUE_SNOOZED"
|
|
||||||
: data.status === 1
|
|
||||||
? "INBOX_ISSUE_ACCEPTED"
|
|
||||||
: "INBOX_ISSUE_DUPLICATED";
|
|
||||||
trackEventService.trackInboxEvent(response?.data, action, user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -119,34 +100,21 @@ export class InboxService extends APIService {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
inboxId: string,
|
inboxId: string,
|
||||||
inboxIssueId: string,
|
inboxIssueId: string,
|
||||||
data: { issue: Partial<IInboxIssue> },
|
data: { issue: Partial<IInboxIssue> }
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.patch(
|
return this.patch(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/${inboxIssueId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/${inboxIssueId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
if (user) trackEventService.trackInboxEvent(response?.data, "INBOX_ISSUE_UPDATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createInboxIssue(
|
async createInboxIssue(workspaceSlug: string, projectId: string, inboxId: string, data: any): Promise<IInboxIssue> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
inboxId: string,
|
|
||||||
data: any,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IInboxIssue> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/inboxes/${inboxId}/inbox-issues/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
if (user) trackEventService.trackInboxEvent(response?.data, "INBOX_ISSUE_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
import { IUser, IGithubRepoInfo, IGithubServiceImportFormData } from "types";
|
import { IGithubRepoInfo, IGithubServiceImportFormData } from "types";
|
||||||
|
|
||||||
const integrationServiceType: string = "github";
|
const integrationServiceType: string = "github";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class GithubIntegrationService extends APIService {
|
export class GithubIntegrationService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -32,16 +29,9 @@ export class GithubIntegrationService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createGithubServiceImport(
|
async createGithubServiceImport(workspaceSlug: string, data: IGithubServiceImportFormData): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
data: IGithubServiceImportFormData,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/${integrationServiceType}/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/${integrationServiceType}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackImporterEvent(response?.data, "GITHUB_IMPORTER_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import { IAppIntegration, IUser, IImporterService, IWorkspaceIntegration, IExportServiceResponse } from "types";
|
import { IAppIntegration, IImporterService, IWorkspaceIntegration, IExportServiceResponse } from "types";
|
||||||
// helper
|
// helper
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class IntegrationService extends APIService {
|
export class IntegrationService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -60,18 +57,9 @@ export class IntegrationService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteImporterService(
|
async deleteImporterService(workspaceSlug: string, service: string, importerId: string): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
service: string,
|
|
||||||
importerId: string,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/importers/${service}/${importerId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/importers/${service}/${importerId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
const eventName = service === "github" ? "GITHUB_IMPORTER_DELETE" : "JIRA_IMPORTER_DELETE";
|
|
||||||
trackEventService.trackImporterEvent(response?.data, eventName, user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
import { IJiraMetadata, IJiraResponse, IJiraImporterForm, IUser } from "types";
|
import { IJiraMetadata, IJiraResponse, IJiraImporterForm } from "types";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class JiraImporterService extends APIService {
|
export class JiraImporterService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -21,16 +18,9 @@ export class JiraImporterService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createJiraImporter(
|
async createJiraImporter(workspaceSlug: string, data: IJiraImporterForm): Promise<IJiraResponse> {
|
||||||
workspaceSlug: string,
|
|
||||||
data: IJiraImporterForm,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IJiraResponse> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/jira/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/importers/jira/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackImporterEvent(response?.data, "JIRA_IMPORTER_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// type
|
// type
|
||||||
import type { IUser, IIssue, IIssueActivity, ISubIssueResponse, IIssueDisplayProperties } from "types";
|
import type { IIssue, IIssueActivity, ISubIssueResponse, IIssueDisplayProperties } from "types";
|
||||||
// helper
|
// helper
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class IssueService extends APIService {
|
export class IssueService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createIssue(workspaceSlug: string, projectId: string, data: any, user: IUser | undefined): Promise<any> {
|
async createIssue(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueEvent(response.data, "ISSUE_CREATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -68,26 +62,10 @@ export class IssueService extends APIService {
|
|||||||
cycleId: string,
|
cycleId: string,
|
||||||
data: {
|
data: {
|
||||||
issues: string[];
|
issues: string[];
|
||||||
},
|
}
|
||||||
user: IUser | undefined
|
|
||||||
) {
|
) {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueMovedToCycleOrModuleEvent(
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
workspaceName: response?.data?.[0]?.issue_detail?.workspace_detail?.name,
|
|
||||||
projectId,
|
|
||||||
projectIdentifier: response?.data?.[0]?.issue_detail?.project_detail?.identifier,
|
|
||||||
projectName: response?.data?.[0]?.issue_detail?.project_detail?.name,
|
|
||||||
issueId: response?.data?.[0]?.issue_detail?.id,
|
|
||||||
cycleId,
|
|
||||||
},
|
|
||||||
response.data.length > 1 ? "ISSUE_MOVED_TO_CYCLE_IN_BULK" : "ISSUE_MOVED_TO_CYCLE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -107,7 +85,6 @@ export class IssueService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
issueId: string,
|
issueId: string,
|
||||||
user: IUser,
|
|
||||||
data: {
|
data: {
|
||||||
related_list: Array<{
|
related_list: Array<{
|
||||||
relation_type: "duplicate" | "relates_to" | "blocked_by";
|
relation_type: "duplicate" | "relates_to" | "blocked_by";
|
||||||
@ -117,29 +94,17 @@ export class IssueService extends APIService {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-relation/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-relation/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueRelationEvent(response.data, "ISSUE_RELATION_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteIssueRelation(
|
async deleteIssueRelation(workspaceSlug: string, projectId: string, issueId: string, relationId: string) {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
issueId: string,
|
|
||||||
relationId: string,
|
|
||||||
user: IUser
|
|
||||||
) {
|
|
||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-relation/${relationId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-relation/${relationId}/`
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueRelationEvent(response.data, "ISSUE_RELATION_DELETE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
@ -167,40 +132,25 @@ export class IssueService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchIssue(
|
async patchIssue(workspaceSlug: string, projectId: string, issueId: string, data: Partial<IIssue>): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
issueId: string,
|
|
||||||
data: Partial<IIssue>,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueEvent(response.data, "ISSUE_UPDATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteIssue(workspaceSlug: string, projectId: string, issuesId: string, user: IUser | undefined): Promise<any> {
|
async deleteIssue(workspaceSlug: string, projectId: string, issuesId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issuesId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issuesId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueEvent({ issuesId }, "ISSUE_DELETE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async bulkDeleteIssues(workspaceSlug: string, projectId: string, data: any, user: IUser | undefined): Promise<any> {
|
async bulkDeleteIssues(workspaceSlug: string, projectId: string, data: any): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-delete-issues/`, data)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/bulk-delete-issues/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueBulkDeleteEvent(data, user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import { IIssueComment, IUser } from "types";
|
import { IIssueComment } from "types";
|
||||||
// helper
|
// helper
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class IssueCommentService extends APIService {
|
export class IssueCommentService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -24,14 +21,10 @@ export class IssueCommentService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
issueId: string,
|
issueId: string,
|
||||||
data: Partial<IIssueComment>,
|
data: Partial<IIssueComment>
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueCommentEvent(response.data, "ISSUE_COMMENT_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -42,43 +35,23 @@ export class IssueCommentService extends APIService {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
issueId: string,
|
issueId: string,
|
||||||
commentId: string,
|
commentId: string,
|
||||||
data: Partial<IIssueComment>,
|
data: Partial<IIssueComment>
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.patch(
|
return this.patch(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueCommentEvent(response.data, "ISSUE_COMMENT_UPDATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteIssueComment(
|
async deleteIssueComment(workspaceSlug: string, projectId: string, issueId: string, commentId: string): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
issueId: string,
|
|
||||||
commentId: string,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/comments/${commentId}/`
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueCommentEvent(
|
|
||||||
{
|
|
||||||
issueId,
|
|
||||||
commentId,
|
|
||||||
},
|
|
||||||
"ISSUE_COMMENT_DELETE",
|
|
||||||
user
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import { IIssueLabel, IUser } from "types";
|
import { IIssueLabel } from "types";
|
||||||
|
|
||||||
const trackEventServices = new TrackEventService();
|
|
||||||
|
|
||||||
export class IssueLabelService extends APIService {
|
export class IssueLabelService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -28,83 +25,25 @@ export class IssueLabelService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createIssueLabel(
|
async createIssueLabel(workspaceSlug: string, projectId: string, data: any): Promise<IIssueLabel> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
data: any,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IIssueLabel> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/`, data)
|
||||||
.then((response: { data: IIssueLabel; [key: string]: any }) => {
|
.then((response) => response?.data)
|
||||||
trackEventServices.trackIssueLabelEvent(
|
|
||||||
{
|
|
||||||
workSpaceId: response?.data?.workspace_detail?.id,
|
|
||||||
workSpaceName: response?.data?.workspace_detail?.name,
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
projectIdentifier: response?.data?.project_detail?.identifier,
|
|
||||||
projectName: response?.data?.project_detail?.name,
|
|
||||||
labelId: response?.data?.id,
|
|
||||||
color: response?.data?.color,
|
|
||||||
},
|
|
||||||
"ISSUE_LABEL_CREATE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchIssueLabel(
|
async patchIssueLabel(workspaceSlug: string, projectId: string, labelId: string, data: any): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
labelId: string,
|
|
||||||
data: any,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventServices.trackIssueLabelEvent(
|
|
||||||
{
|
|
||||||
workSpaceId: response?.data?.workspace_detail?.id,
|
|
||||||
workSpaceName: response?.data?.workspace_detail?.name,
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
projectIdentifier: response?.data?.project_detail?.identifier,
|
|
||||||
projectName: response?.data?.project_detail?.name,
|
|
||||||
labelId: response?.data?.id,
|
|
||||||
color: response?.data?.color,
|
|
||||||
},
|
|
||||||
"ISSUE_LABEL_UPDATE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteIssueLabel(
|
async deleteIssueLabel(workspaceSlug: string, projectId: string, labelId: string): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
labelId: string,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-labels/${labelId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventServices.trackIssueLabelEvent(
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
},
|
|
||||||
"ISSUE_LABEL_DELETE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import type { IUser, IssueReaction, IssueCommentReaction, IssueReactionForm, IssueCommentReactionForm } from "types";
|
import type { IssueReaction, IssueCommentReaction, IssueReactionForm, IssueCommentReactionForm } from "types";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class IssueReactionService extends APIService {
|
export class IssueReactionService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -16,14 +13,10 @@ export class IssueReactionService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
issueId: string,
|
issueId: string,
|
||||||
data: IssueReactionForm,
|
data: IssueReactionForm
|
||||||
user?: IUser
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/reactions/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/reactions/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackReactionEvent(response?.data, "ISSUE_REACTION_CREATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -37,20 +30,11 @@ export class IssueReactionService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteIssueReaction(
|
async deleteIssueReaction(workspaceSlug: string, projectId: string, issueId: string, reaction: string): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
issueId: string,
|
|
||||||
reaction: string,
|
|
||||||
user?: IUser
|
|
||||||
): Promise<any> {
|
|
||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/reactions/${reaction}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/reactions/${reaction}/`
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackReactionEvent(response?.data, "ISSUE_REACTION_DELETE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -60,14 +44,10 @@ export class IssueReactionService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
commentId: string,
|
commentId: string,
|
||||||
data: IssueCommentReactionForm,
|
data: IssueCommentReactionForm
|
||||||
user?: IUser
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/comments/${commentId}/reactions/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/comments/${commentId}/reactions/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackReactionEvent(response?.data, "ISSUE_COMMENT_REACTION_CREATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -89,16 +69,12 @@ export class IssueReactionService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
commentId: string,
|
commentId: string,
|
||||||
reaction: string,
|
reaction: string
|
||||||
user?: IUser
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/comments/${commentId}/reactions/${reaction}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/comments/${commentId}/reactions/${reaction}/`
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackReactionEvent(response?.data, "ISSUE_COMMENT_REACTION_DELETE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import type { IModule, IIssue, IUser } from "types";
|
import type { IModule, IIssue } from "types";
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class ModuleService extends APIService {
|
export class ModuleService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -20,29 +17,17 @@ export class ModuleService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createModule(workspaceSlug: string, projectId: string, data: any, user: any): Promise<IModule> {
|
async createModule(workspaceSlug: string, projectId: string, data: any): Promise<IModule> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackModuleEvent(response?.data, "MODULE_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateModule(
|
async updateModule(workspaceSlug: string, projectId: string, moduleId: string, data: any): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
moduleId: string,
|
|
||||||
data: any,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`, data)
|
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackModuleEvent(response?.data, "MODULE_UPDATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -60,25 +45,18 @@ export class ModuleService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
moduleId: string,
|
moduleId: string,
|
||||||
data: Partial<IModule>,
|
data: Partial<IModule>
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IModule> {
|
): Promise<IModule> {
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
if (user) trackEventService.trackModuleEvent(response?.data, "MODULE_UPDATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteModule(workspaceSlug: string, projectId: string, moduleId: string, user: any): Promise<any> {
|
async deleteModule(workspaceSlug: string, projectId: string, moduleId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackModuleEvent(response?.data, "MODULE_DELETE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -116,26 +94,10 @@ export class ModuleService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
moduleId: string,
|
moduleId: string,
|
||||||
data: { issues: string[] },
|
data: { issues: string[] }
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-issues/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-issues/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueMovedToCycleOrModuleEvent(
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
workspaceName: response?.data?.[0]?.issue_detail?.workspace_detail?.name,
|
|
||||||
projectId,
|
|
||||||
projectIdentifier: response?.data?.[0]?.issue_detail?.project_detail?.identifier,
|
|
||||||
projectName: response?.data?.[0]?.issue_detail?.project_detail?.name,
|
|
||||||
issueId: response?.data?.[0]?.issue_detail?.id,
|
|
||||||
moduleId,
|
|
||||||
},
|
|
||||||
response?.data?.length > 1 ? "ISSUE_MOVED_TO_MODULE_IN_BULK" : "ISSUE_MOVED_TO_MODULE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,56 +1,33 @@
|
|||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import { IPage, IPageBlock, RecentPagesResponse, IIssue, IUser } from "types";
|
import { IPage, IPageBlock, RecentPagesResponse, IIssue } from "types";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class PageService extends APIService {
|
export class PageService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createPage(
|
async createPage(workspaceSlug: string, projectId: string, data: Partial<IPage>): Promise<IPage> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
data: Partial<IPage>,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IPage> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackPageEvent(response?.data, "PAGE_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchPage(
|
async patchPage(workspaceSlug: string, projectId: string, pageId: string, data: Partial<IPage>): Promise<IPage> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
pageId: string,
|
|
||||||
data: Partial<IPage>,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IPage> {
|
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackPageEvent(response?.data, "PAGE_UPDATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deletePage(workspaceSlug: string, projectId: string, pageId: string, user: IUser | undefined): Promise<any> {
|
async deletePage(workspaceSlug: string, projectId: string, pageId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackPageEvent(response?.data, "PAGE_DELETE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -118,14 +95,10 @@ export class PageService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
pageId: string,
|
pageId: string,
|
||||||
data: Partial<IPageBlock>,
|
data: Partial<IPageBlock>
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IPageBlock> {
|
): Promise<IPageBlock> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackPageBlockEvent(response?.data, "PAGE_BLOCK_CREATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -151,36 +124,23 @@ export class PageService extends APIService {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
pageId: string,
|
pageId: string,
|
||||||
pageBlockId: string,
|
pageBlockId: string,
|
||||||
data: Partial<IPageBlock>,
|
data: Partial<IPageBlock>
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IPage> {
|
): Promise<IPage> {
|
||||||
return this.patch(
|
return this.patch(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${pageBlockId}/`,
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${pageBlockId}/`,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackPageBlockEvent(response?.data, "PAGE_BLOCK_UPDATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deletePageBlock(
|
async deletePageBlock(workspaceSlug: string, projectId: string, pageId: string, pageBlockId: string): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
pageId: string,
|
|
||||||
pageBlockId: string,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.delete(
|
return this.delete(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${pageBlockId}/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${pageBlockId}/`
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackPageBlockEvent(response?.data, "PAGE_BLOCK_DELETE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -198,16 +158,12 @@ export class PageService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
pageId: string,
|
pageId: string,
|
||||||
blockId: string,
|
blockId: string
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IIssue> {
|
): Promise<IIssue> {
|
||||||
return this.post(
|
return this.post(
|
||||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${blockId}/issues/`
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/${pageId}/page-blocks/${blockId}/issues/`
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackPageBlockEvent(response?.data, "PAGE_BLOCK_CONVERTED_TO_ISSUE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,29 +1,18 @@
|
|||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import type { IUser, IEstimate, IEstimateFormData } from "types";
|
import type { IEstimate, IEstimateFormData } from "types";
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class ProjectEstimateService extends APIService {
|
export class ProjectEstimateService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createEstimate(
|
async createEstimate(workspaceSlug: string, projectId: string, data: IEstimateFormData): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
data: IEstimateFormData,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueEstimateEvent(response?.data, "ESTIMATE_CREATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
@ -33,14 +22,10 @@ export class ProjectEstimateService extends APIService {
|
|||||||
workspaceSlug: string,
|
workspaceSlug: string,
|
||||||
projectId: string,
|
projectId: string,
|
||||||
estimateId: string,
|
estimateId: string,
|
||||||
data: IEstimateFormData,
|
data: IEstimateFormData
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueEstimateEvent(response?.data, "ESTIMATE_UPDATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -62,17 +47,9 @@ export class ProjectEstimateService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteEstimate(
|
async deleteEstimate(workspaceSlug: string, projectId: string, estimateId: string): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
estimateId: string,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/estimates/${estimateId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackIssueEstimateEvent(response?.data, "ESTIMATE_DELETE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
|
||||||
import { IUser } from "types";
|
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class ProjectExportService extends APIService {
|
export class ProjectExportService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -17,20 +12,10 @@ export class ProjectExportService extends APIService {
|
|||||||
data: {
|
data: {
|
||||||
provider: string;
|
provider: string;
|
||||||
project: string[];
|
project: string[];
|
||||||
},
|
}
|
||||||
user: IUser
|
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/export-issues/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/export-issues/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackExporterEvent(
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
},
|
|
||||||
"CSV_EXPORTER_CREATE",
|
|
||||||
user
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import type { IUser, IProjectBulkAddFormData, IProjectMember, IProjectMemberInvitation } from "types";
|
import type { IProjectBulkAddFormData, IProjectMember, IProjectMemberInvitation } from "types";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class ProjectMemberService extends APIService {
|
export class ProjectMemberService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -20,27 +17,9 @@ export class ProjectMemberService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async bulkAddMembersToProject(
|
async bulkAddMembersToProject(workspaceSlug: string, projectId: string, data: IProjectBulkAddFormData): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
data: IProjectBulkAddFormData,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackProjectEvent(
|
|
||||||
{
|
|
||||||
workspaceId: response?.data?.workspace?.id,
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
projectName: response?.data?.project?.name,
|
|
||||||
memberEmail: response?.data?.member?.email,
|
|
||||||
},
|
|
||||||
"PROJECT_MEMBER_INVITE",
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
import type { IUser, IState } from "types";
|
import type { IState } from "types";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class ProjectStateService extends APIService {
|
export class ProjectStateService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createState(workspaceSlug: string, projectId: string, data: any, user: IUser | undefined): Promise<IState> {
|
async createState(workspaceSlug: string, projectId: string, data: any): Promise<IState> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackStateEvent(response?.data, "STATE_CREATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
@ -48,46 +42,25 @@ export class ProjectStateService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateState(
|
async updateState(workspaceSlug: string, projectId: string, stateId: string, data: IState): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
stateId: string,
|
|
||||||
data: IState,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`, data)
|
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackStateEvent(response?.data, "STATE_UPDATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchState(
|
async patchState(workspaceSlug: string, projectId: string, stateId: string, data: Partial<IState>): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
stateId: string,
|
|
||||||
data: Partial<IState>,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackStateEvent(response?.data, "STATE_UPDATE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteState(workspaceSlug: string, projectId: string, stateId: string, user: IUser | undefined): Promise<any> {
|
async deleteState(workspaceSlug: string, projectId: string, stateId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/states/${stateId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackStateEvent(response?.data, "STATE_DELETE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import type {
|
import type {
|
||||||
GithubRepositoriesResponse,
|
GithubRepositoriesResponse,
|
||||||
@ -12,19 +11,14 @@ import type {
|
|||||||
TProjectIssuesSearchParams,
|
TProjectIssuesSearchParams,
|
||||||
} from "types";
|
} from "types";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class ProjectService extends APIService {
|
export class ProjectService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createProject(workspaceSlug: string, data: Partial<IProject>, user: any): Promise<IProject> {
|
async createProject(workspaceSlug: string, data: Partial<IProject>): Promise<IProject> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackProjectEvent(response.data, "CREATE_PROJECT", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
});
|
});
|
||||||
@ -58,23 +52,17 @@ export class ProjectService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateProject(workspaceSlug: string, projectId: string, data: Partial<IProject>, user: any): Promise<IProject> {
|
async updateProject(workspaceSlug: string, projectId: string, data: Partial<IProject>): Promise<IProject> {
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackProjectEvent(response.data, "UPDATE_PROJECT", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteProject(workspaceSlug: string, projectId: string, user: any | undefined): Promise<any> {
|
async deleteProject(workspaceSlug: string, projectId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackProjectEvent({ projectId }, "DELETE_PROJECT", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
@ -88,20 +76,9 @@ export class ProjectService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async leaveProject(workspaceSlug: string, projectId: string, user: any): Promise<any> {
|
async leaveProject(workspaceSlug: string, projectId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/leave/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/leave/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackProjectEvent(
|
|
||||||
"PROJECT_MEMBER_LEAVE",
|
|
||||||
{
|
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
...response?.data,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,850 +0,0 @@
|
|||||||
// services
|
|
||||||
import { APIService } from "services/api.service";
|
|
||||||
|
|
||||||
const trackEvent = process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
|
|
||||||
|
|
||||||
// types
|
|
||||||
import type {
|
|
||||||
IUser,
|
|
||||||
ICycle,
|
|
||||||
IEstimate,
|
|
||||||
IGptResponse,
|
|
||||||
IIssue,
|
|
||||||
IIssueComment,
|
|
||||||
IModule,
|
|
||||||
IPage,
|
|
||||||
IPageBlock,
|
|
||||||
IProject,
|
|
||||||
IState,
|
|
||||||
IProjectView,
|
|
||||||
IWorkspace,
|
|
||||||
IssueCommentReaction,
|
|
||||||
IssueReaction,
|
|
||||||
} from "types";
|
|
||||||
|
|
||||||
type WorkspaceEventType =
|
|
||||||
| "CREATE_WORKSPACE"
|
|
||||||
| "UPDATE_WORKSPACE"
|
|
||||||
| "DELETE_WORKSPACE"
|
|
||||||
| "WORKSPACE_USER_INVITE"
|
|
||||||
| "WORKSPACE_USER_INVITE_ACCEPT"
|
|
||||||
| "WORKSPACE_USER_BULK_INVITE_ACCEPT";
|
|
||||||
|
|
||||||
type ProjectEventType =
|
|
||||||
| "CREATE_PROJECT"
|
|
||||||
| "UPDATE_PROJECT"
|
|
||||||
| "DELETE_PROJECT"
|
|
||||||
| "PROJECT_MEMBER_INVITE"
|
|
||||||
| "PROJECT_MEMBER_LEAVE";
|
|
||||||
|
|
||||||
type IssueEventType = "ISSUE_CREATE" | "ISSUE_UPDATE" | "ISSUE_DELETE";
|
|
||||||
|
|
||||||
type CycleEventType = "CYCLE_CREATE" | "CYCLE_UPDATE" | "CYCLE_DELETE";
|
|
||||||
|
|
||||||
type StateEventType = "STATE_CREATE" | "STATE_UPDATE" | "STATE_DELETE";
|
|
||||||
|
|
||||||
type ModuleEventType = "MODULE_CREATE" | "MODULE_UPDATE" | "MODULE_DELETE";
|
|
||||||
|
|
||||||
type PagesEventType = "PAGE_CREATE" | "PAGE_UPDATE" | "PAGE_DELETE";
|
|
||||||
|
|
||||||
type ViewEventType = "VIEW_CREATE" | "VIEW_UPDATE" | "VIEW_DELETE";
|
|
||||||
|
|
||||||
type IssueCommentEventType = "ISSUE_COMMENT_CREATE" | "ISSUE_COMMENT_UPDATE" | "ISSUE_COMMENT_DELETE";
|
|
||||||
|
|
||||||
type Toggle = "TOGGLE_CYCLE" | "TOGGLE_MODULE" | "TOGGLE_VIEW" | "TOGGLE_PAGES" | "TOGGLE_STATE" | "TOGGLE_INBOX";
|
|
||||||
|
|
||||||
export type MiscellaneousEventType = `${Toggle}_ON` | `${Toggle}_OFF`;
|
|
||||||
|
|
||||||
type IntegrationEventType = "ADD_WORKSPACE_INTEGRATION" | "REMOVE_WORKSPACE_INTEGRATION";
|
|
||||||
|
|
||||||
type GitHubSyncEventType = "GITHUB_REPO_SYNC";
|
|
||||||
|
|
||||||
type PageBlocksEventType =
|
|
||||||
| "PAGE_BLOCK_CREATE"
|
|
||||||
| "PAGE_BLOCK_UPDATE"
|
|
||||||
| "PAGE_BLOCK_DELETE"
|
|
||||||
| "PAGE_BLOCK_CONVERTED_TO_ISSUE";
|
|
||||||
|
|
||||||
type IssueLabelEventType = "ISSUE_LABEL_CREATE" | "ISSUE_LABEL_UPDATE" | "ISSUE_LABEL_DELETE";
|
|
||||||
|
|
||||||
type GptEventType = "ASK_GPT" | "USE_GPT_RESPONSE_IN_ISSUE" | "USE_GPT_RESPONSE_IN_PAGE_BLOCK";
|
|
||||||
|
|
||||||
type IssueEstimateEventType = "ESTIMATE_CREATE" | "ESTIMATE_UPDATE" | "ESTIMATE_DELETE";
|
|
||||||
|
|
||||||
type InboxEventType =
|
|
||||||
| "INBOX_CREATE"
|
|
||||||
| "INBOX_UPDATE"
|
|
||||||
| "INBOX_DELETE"
|
|
||||||
| "INBOX_ISSUE_CREATE"
|
|
||||||
| "INBOX_ISSUE_UPDATE"
|
|
||||||
| "INBOX_ISSUE_DELETE"
|
|
||||||
| "INBOX_ISSUE_DUPLICATED"
|
|
||||||
| "INBOX_ISSUE_ACCEPTED"
|
|
||||||
| "INBOX_ISSUE_SNOOZED"
|
|
||||||
| "INBOX_ISSUE_REJECTED";
|
|
||||||
|
|
||||||
type ImporterEventType =
|
|
||||||
| "GITHUB_IMPORTER_CREATE"
|
|
||||||
| "GITHUB_IMPORTER_DELETE"
|
|
||||||
| "JIRA_IMPORTER_CREATE"
|
|
||||||
| "JIRA_IMPORTER_DELETE";
|
|
||||||
|
|
||||||
type ExporterEventType = "CSV_EXPORTER_CREATE";
|
|
||||||
|
|
||||||
type AnalyticsEventType =
|
|
||||||
| "WORKSPACE_SCOPE_AND_DEMAND_ANALYTICS"
|
|
||||||
| "WORKSPACE_CUSTOM_ANALYTICS"
|
|
||||||
| "WORKSPACE_ANALYTICS_EXPORT"
|
|
||||||
| "PROJECT_SCOPE_AND_DEMAND_ANALYTICS"
|
|
||||||
| "PROJECT_CUSTOM_ANALYTICS"
|
|
||||||
| "PROJECT_ANALYTICS_EXPORT"
|
|
||||||
| "CYCLE_SCOPE_AND_DEMAND_ANALYTICS"
|
|
||||||
| "CYCLE_CUSTOM_ANALYTICS"
|
|
||||||
| "CYCLE_ANALYTICS_EXPORT"
|
|
||||||
| "MODULE_SCOPE_AND_DEMAND_ANALYTICS"
|
|
||||||
| "MODULE_CUSTOM_ANALYTICS"
|
|
||||||
| "MODULE_ANALYTICS_EXPORT";
|
|
||||||
|
|
||||||
type ReactionEventType =
|
|
||||||
| "ISSUE_REACTION_CREATE"
|
|
||||||
| "ISSUE_COMMENT_REACTION_CREATE"
|
|
||||||
| "ISSUE_REACTION_DELETE"
|
|
||||||
| "ISSUE_COMMENT_REACTION_DELETE";
|
|
||||||
|
|
||||||
export class TrackEventService extends APIService {
|
|
||||||
constructor() {
|
|
||||||
super("/");
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackWorkspaceEvent(data: IWorkspace | any, eventName: WorkspaceEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (
|
|
||||||
eventName !== "DELETE_WORKSPACE" &&
|
|
||||||
eventName !== "WORKSPACE_USER_INVITE" &&
|
|
||||||
eventName !== "WORKSPACE_USER_INVITE_ACCEPT" &&
|
|
||||||
eventName !== "WORKSPACE_USER_BULK_INVITE_ACCEPT"
|
|
||||||
)
|
|
||||||
payload = {
|
|
||||||
workspaceId: data.id,
|
|
||||||
workspaceSlug: data.slug,
|
|
||||||
workspaceName: data.name,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackProjectEvent(data: Partial<IProject> | any, eventName: ProjectEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "DELETE_PROJECT" && eventName !== "PROJECT_MEMBER_INVITE" && eventName !== "PROJECT_MEMBER_LEAVE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.id,
|
|
||||||
projectName: data?.name,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackUserOnboardingCompleteEvent(data: any, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName: "USER_ONBOARDING_COMPLETE",
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackUserTourCompleteEvent(data: any, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName: "USER_TOUR_COMPLETE",
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueEvent(data: IIssue | any, eventName: IssueEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "ISSUE_DELETE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
issueId: data?.id,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueMarkedAsDoneEvent(data: any, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName: "ISSUES_MARKED_AS_DONE",
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssuePartialPropertyUpdateEvent(
|
|
||||||
data: any,
|
|
||||||
propertyName:
|
|
||||||
| "ISSUE_PROPERTY_UPDATE_PRIORITY"
|
|
||||||
| "ISSUE_PROPERTY_UPDATE_STATE"
|
|
||||||
| "ISSUE_PROPERTY_UPDATE_ASSIGNEE"
|
|
||||||
| "ISSUE_PROPERTY_UPDATE_DUE_DATE"
|
|
||||||
| "ISSUE_PROPERTY_UPDATE_ESTIMATE",
|
|
||||||
user: IUser
|
|
||||||
): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName: propertyName,
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueCommentEvent(
|
|
||||||
data: Partial<IIssueComment> | any,
|
|
||||||
eventName: IssueCommentEventType,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "ISSUE_COMMENT_DELETE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
issueId: data?.issue,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueRelationEvent(
|
|
||||||
data: any,
|
|
||||||
eventName: "ISSUE_RELATION_CREATE" | "ISSUE_RELATION_DELETE",
|
|
||||||
user: IUser
|
|
||||||
): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: data,
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueMovedToCycleOrModuleEvent(
|
|
||||||
data: any,
|
|
||||||
eventName:
|
|
||||||
| "ISSUE_MOVED_TO_CYCLE"
|
|
||||||
| "ISSUE_MOVED_TO_MODULE"
|
|
||||||
| "ISSUE_MOVED_TO_CYCLE_IN_BULK"
|
|
||||||
| "ISSUE_MOVED_TO_MODULE_IN_BULK",
|
|
||||||
user: IUser
|
|
||||||
): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueBulkDeleteEvent(data: any, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName: "ISSUE_BULK_DELETE",
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueLabelEvent(data: any, eventName: IssueLabelEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackStateEvent(data: IState | any, eventName: StateEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "STATE_DELETE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
stateId: data.id,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackCycleEvent(data: ICycle | any, eventName: CycleEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "CYCLE_DELETE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
cycleId: data.id,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackModuleEvent(data: IModule | any, eventName: ModuleEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "MODULE_DELETE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
moduleId: data.id,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackPageEvent(data: Partial<IPage> | any, eventName: PagesEventType, user: IUser | undefined): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "PAGE_DELETE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
pageId: data.id,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackPageBlockEvent(
|
|
||||||
data: Partial<IPageBlock> | IIssue,
|
|
||||||
eventName: PageBlocksEventType,
|
|
||||||
user: IUser
|
|
||||||
): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "PAGE_BLOCK_DELETE" && eventName !== "PAGE_BLOCK_CONVERTED_TO_ISSUE")
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
pageId: (data as IPageBlock)?.page,
|
|
||||||
pageBlockId: data.id,
|
|
||||||
};
|
|
||||||
else if (eventName === "PAGE_BLOCK_CONVERTED_TO_ISSUE") {
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
issueId: data?.id,
|
|
||||||
};
|
|
||||||
} else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackAskGptEvent(data: IGptResponse, eventName: GptEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
count: data?.count,
|
|
||||||
};
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackUseGPTResponseEvent(data: IIssue | IPageBlock, eventName: GptEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
|
|
||||||
if (eventName === "USE_GPT_RESPONSE_IN_ISSUE") {
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
issueId: data.id,
|
|
||||||
};
|
|
||||||
} else if (eventName === "USE_GPT_RESPONSE_IN_PAGE_BLOCK") {
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
pageId: (data as IPageBlock)?.page,
|
|
||||||
pageBlockId: data.id,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackViewEvent(data: IProjectView, eventName: ViewEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName === "VIEW_DELETE") payload = data;
|
|
||||||
else
|
|
||||||
payload = {
|
|
||||||
labels: Boolean(data.query_data.labels),
|
|
||||||
assignees: Boolean(data.query_data.assignees),
|
|
||||||
priority: Boolean(data.query_data.priority),
|
|
||||||
state: Boolean(data.query_data.state),
|
|
||||||
created_by: Boolean(data.query_data.created_by),
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackMiscellaneousEvent(data: any, eventName: MiscellaneousEventType, user: IUser | undefined): Promise<any> {
|
|
||||||
if (!trackEvent || !user) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackAppIntegrationEvent(data: any, eventName: IntegrationEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackGitHubSyncEvent(data: any, eventName: GitHubSyncEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...data,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackIssueEstimateEvent(
|
|
||||||
data: { estimate: IEstimate },
|
|
||||||
eventName: IssueEstimateEventType,
|
|
||||||
user: IUser
|
|
||||||
): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName === "ESTIMATE_DELETE") payload = data;
|
|
||||||
else
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.estimate?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.estimate?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.estimate?.workspace_detail?.slug,
|
|
||||||
projectId: data?.estimate?.project_detail?.id,
|
|
||||||
projectName: data?.estimate?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.estimate?.project_detail?.identifier,
|
|
||||||
estimateId: data.estimate?.id,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackImporterEvent(data: any, eventName: ImporterEventType, user: IUser | undefined): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName === "GITHUB_IMPORTER_DELETE" || eventName === "JIRA_IMPORTER_DELETE") payload = data;
|
|
||||||
else
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.workspace_detail?.slug,
|
|
||||||
projectId: data?.project_detail?.id,
|
|
||||||
projectName: data?.project_detail?.name,
|
|
||||||
projectIdentifier: data?.project_detail?.identifier,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackAnalyticsEvent(data: any, eventName: AnalyticsEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
const payload = { ...data };
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: payload,
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackExporterEvent(data: any, eventName: ExporterEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
const payload = { ...data };
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add types to the data
|
|
||||||
async trackInboxEvent(data: any, eventName: InboxEventType, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName !== "INBOX_DELETE")
|
|
||||||
payload = {
|
|
||||||
issue: data?.issue?.id,
|
|
||||||
inbox: data?.id,
|
|
||||||
workspaceId: data?.issue?.workspace_detail?.id,
|
|
||||||
workspaceName: data?.issue?.workspace_detail?.name,
|
|
||||||
workspaceSlug: data?.issue?.workspace_detail?.slug,
|
|
||||||
projectId: data?.issue?.project_detail?.id,
|
|
||||||
projectName: data?.issue?.project_detail?.name,
|
|
||||||
};
|
|
||||||
else payload = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: {
|
|
||||||
...payload,
|
|
||||||
},
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackReactionEvent(
|
|
||||||
data: IssueReaction | IssueCommentReaction,
|
|
||||||
eventName: ReactionEventType,
|
|
||||||
user: IUser
|
|
||||||
): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
let payload: any;
|
|
||||||
if (eventName === "ISSUE_REACTION_DELETE" || eventName === "ISSUE_COMMENT_REACTION_DELETE") payload = data;
|
|
||||||
else
|
|
||||||
payload = {
|
|
||||||
workspaceId: data?.workspace,
|
|
||||||
projectId: data?.project,
|
|
||||||
reaction: data?.reaction,
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: payload,
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async trackProjectPublishSettingsEvent(data: any, eventName: string, user: IUser): Promise<any> {
|
|
||||||
if (!trackEvent) return;
|
|
||||||
|
|
||||||
const payload: any = data;
|
|
||||||
|
|
||||||
return this.request({
|
|
||||||
url: "/api/track-event",
|
|
||||||
method: "POST",
|
|
||||||
data: {
|
|
||||||
eventName,
|
|
||||||
extra: payload,
|
|
||||||
user: user,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import type {
|
import type {
|
||||||
IIssue,
|
IIssue,
|
||||||
@ -15,8 +14,6 @@ import type {
|
|||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class UserService extends APIService {
|
export class UserService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -79,32 +76,21 @@ export class UserService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUserOnBoard({ userRole }: any, user: IUser | undefined): Promise<any> {
|
async updateUserOnBoard(): Promise<any> {
|
||||||
return this.patch("/api/users/me/onboard/", {
|
return this.patch("/api/users/me/onboard/", {
|
||||||
is_onboarded: true,
|
is_onboarded: true,
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackUserOnboardingCompleteEvent(
|
|
||||||
{
|
|
||||||
user_role: userRole ?? "None",
|
|
||||||
},
|
|
||||||
user as IUser
|
|
||||||
);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateUserTourCompleted(user: IUser): Promise<any> {
|
async updateUserTourCompleted(): Promise<any> {
|
||||||
return this.patch("/api/users/me/tour-completed/", {
|
return this.patch("/api/users/me/tour-completed/", {
|
||||||
is_tour_completed: true,
|
is_tour_completed: true,
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackUserTourCompleteEvent({ user_role: user.role ?? "None" }, user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,51 +1,33 @@
|
|||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// types
|
// types
|
||||||
import { IProjectView } from "types/views";
|
import { IProjectView } from "types/views";
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class ViewService extends APIService {
|
export class ViewService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createView(workspaceSlug: string, projectId: string, data: Partial<IProjectView>, user: any): Promise<any> {
|
async createView(workspaceSlug: string, projectId: string, data: Partial<IProjectView>): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackViewEvent(response?.data, "VIEW_CREATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchView(
|
async patchView(workspaceSlug: string, projectId: string, viewId: string, data: Partial<IProjectView>): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
projectId: string,
|
|
||||||
viewId: string,
|
|
||||||
data: Partial<IProjectView>,
|
|
||||||
user: any
|
|
||||||
): Promise<any> {
|
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackViewEvent(response?.data, "VIEW_UPDATE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteView(workspaceSlug: string, projectId: string, viewId: string, user: any): Promise<any> {
|
async deleteView(workspaceSlug: string, projectId: string, viewId: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackViewEvent(response?.data, "VIEW_DELETE", user);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// services
|
// services
|
||||||
import { APIService } from "services/api.service";
|
import { APIService } from "services/api.service";
|
||||||
import { TrackEventService } from "services/track_event.service";
|
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "helpers/common.helper";
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
@ -12,7 +11,6 @@ import {
|
|||||||
ILastActiveWorkspaceDetails,
|
ILastActiveWorkspaceDetails,
|
||||||
IWorkspaceSearchResults,
|
IWorkspaceSearchResults,
|
||||||
IProductUpdateResponse,
|
IProductUpdateResponse,
|
||||||
IUser,
|
|
||||||
IWorkspaceBulkInviteFormData,
|
IWorkspaceBulkInviteFormData,
|
||||||
IWorkspaceViewProps,
|
IWorkspaceViewProps,
|
||||||
} from "types";
|
} from "types";
|
||||||
@ -20,8 +18,6 @@ import { IWorkspaceView } from "types/workspace-views";
|
|||||||
// store
|
// store
|
||||||
import { IIssueGroupWithSubGroupsStructure, IIssueGroupedStructure, IIssueUnGroupedStructure } from "store/issue";
|
import { IIssueGroupWithSubGroupsStructure, IIssueGroupedStructure, IIssueUnGroupedStructure } from "store/issue";
|
||||||
|
|
||||||
const trackEventService = new TrackEventService();
|
|
||||||
|
|
||||||
export class WorkspaceService extends APIService {
|
export class WorkspaceService extends APIService {
|
||||||
constructor() {
|
constructor() {
|
||||||
super(API_BASE_URL);
|
super(API_BASE_URL);
|
||||||
@ -43,66 +39,43 @@ export class WorkspaceService extends APIService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async createWorkspace(data: Partial<IWorkspace>, user: IUser | undefined): Promise<IWorkspace> {
|
async createWorkspace(data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||||
return this.post("/api/workspaces/", data)
|
return this.post("/api/workspaces/", data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackWorkspaceEvent(response.data, "CREATE_WORKSPACE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateWorkspace(
|
async updateWorkspace(workspaceSlug: string, data: Partial<IWorkspace>): Promise<IWorkspace> {
|
||||||
workspaceSlug: string,
|
|
||||||
data: Partial<IWorkspace>,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<IWorkspace> {
|
|
||||||
return this.patch(`/api/workspaces/${workspaceSlug}/`, data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackWorkspaceEvent(response.data, "UPDATE_WORKSPACE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteWorkspace(workspaceSlug: string, user: IUser | undefined): Promise<any> {
|
async deleteWorkspace(workspaceSlug: string): Promise<any> {
|
||||||
return this.delete(`/api/workspaces/${workspaceSlug}/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/`)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackWorkspaceEvent({ workspaceSlug }, "DELETE_WORKSPACE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async inviteWorkspace(
|
async inviteWorkspace(workspaceSlug: string, data: IWorkspaceBulkInviteFormData): Promise<any> {
|
||||||
workspaceSlug: string,
|
|
||||||
data: IWorkspaceBulkInviteFormData,
|
|
||||||
user: IUser | undefined
|
|
||||||
): Promise<any> {
|
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/invite/`, data)
|
return this.post(`/api/workspaces/${workspaceSlug}/invite/`, data)
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackWorkspaceEvent(response.data, "WORKSPACE_USER_INVITE", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async joinWorkspace(workspaceSlug: string, invitationId: string, data: any, user: IUser | undefined): Promise<any> {
|
async joinWorkspace(workspaceSlug: string, invitationId: string, data: any): Promise<any> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/join/`, data, {
|
return this.post(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/join/`, data, {
|
||||||
headers: {},
|
headers: {},
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => response?.data)
|
||||||
trackEventService.trackWorkspaceEvent(response.data, "WORKSPACE_USER_INVITE_ACCEPT", user as IUser);
|
|
||||||
return response?.data;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
});
|
});
|
||||||
|
@ -324,17 +324,9 @@ export class CycleIssueStore implements ICycleIssueStore {
|
|||||||
|
|
||||||
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
||||||
try {
|
try {
|
||||||
const user = this.rootStore.user.currentUser ?? undefined;
|
await this.issueService.addIssueToCycle(workspaceSlug, projectId, cycleId, {
|
||||||
|
issues: issueIds,
|
||||||
await this.issueService.addIssueToCycle(
|
});
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
cycleId,
|
|
||||||
{
|
|
||||||
issues: issueIds,
|
|
||||||
},
|
|
||||||
user
|
|
||||||
);
|
|
||||||
|
|
||||||
this.fetchIssues(workspaceSlug, projectId, cycleId);
|
this.fetchIssues(workspaceSlug, projectId, cycleId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -133,9 +133,7 @@ export class CycleIssueFilterStore implements ICycleIssueFilterStore {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const user = this.rootStore.user.currentUser ?? undefined;
|
await this.cycleService.patchCycle(workspaceSlug, projectId, cycleId, payload);
|
||||||
|
|
||||||
await this.cycleService.patchCycle(workspaceSlug, projectId, cycleId, payload, user);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.fetchCycleFilters(workspaceSlug, projectId, cycleId);
|
this.fetchCycleFilters(workspaceSlug, projectId, cycleId);
|
||||||
|
|
||||||
|
@ -248,12 +248,7 @@ export class CycleStore implements ICycleStore {
|
|||||||
|
|
||||||
createCycle = async (workspaceSlug: string, projectId: string, data: Partial<ICycle>) => {
|
createCycle = async (workspaceSlug: string, projectId: string, data: Partial<ICycle>) => {
|
||||||
try {
|
try {
|
||||||
const response = await this.cycleService.createCycle(
|
const response = await this.cycleService.createCycle(workspaceSlug, projectId, data);
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
data,
|
|
||||||
this.rootStore.user.currentUser
|
|
||||||
);
|
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.cycle_details = {
|
this.cycle_details = {
|
||||||
@ -274,7 +269,7 @@ export class CycleStore implements ICycleStore {
|
|||||||
|
|
||||||
patchCycle = async (workspaceSlug: string, projectId: string, cycleId: string, data: Partial<ICycle>) => {
|
patchCycle = async (workspaceSlug: string, projectId: string, cycleId: string, data: Partial<ICycle>) => {
|
||||||
try {
|
try {
|
||||||
const _response = await this.cycleService.patchCycle(workspaceSlug, projectId, cycleId, data, undefined);
|
const _response = await this.cycleService.patchCycle(workspaceSlug, projectId, cycleId, data);
|
||||||
|
|
||||||
const _cycleDetails = {
|
const _cycleDetails = {
|
||||||
...this.cycle_details,
|
...this.cycle_details,
|
||||||
@ -297,7 +292,7 @@ export class CycleStore implements ICycleStore {
|
|||||||
|
|
||||||
removeCycle = async (workspaceSlug: string, projectId: string, cycleId: string) => {
|
removeCycle = async (workspaceSlug: string, projectId: string, cycleId: string) => {
|
||||||
try {
|
try {
|
||||||
const _response = await this.cycleService.deleteCycle(workspaceSlug, projectId, cycleId, undefined);
|
const _response = await this.cycleService.deleteCycle(workspaceSlug, projectId, cycleId);
|
||||||
|
|
||||||
const _currentView = this.cycleView === "active" ? "current" : this.cycleView;
|
const _currentView = this.cycleView === "active" ? "current" : this.cycleView;
|
||||||
this.fetchCycles(workspaceSlug, projectId, _currentView);
|
this.fetchCycles(workspaceSlug, projectId, _currentView);
|
||||||
|
@ -121,13 +121,7 @@ export class InboxIssueDetailsStore implements IInboxIssueDetailsStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.inboxService.createInboxIssue(
|
const response = await this.inboxService.createInboxIssue(workspaceSlug, projectId, inboxId, payload);
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
inboxId,
|
|
||||||
payload,
|
|
||||||
this.rootStore.user.currentUser ?? undefined
|
|
||||||
);
|
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.issueDetails = {
|
this.issueDetails = {
|
||||||
@ -175,14 +169,7 @@ export class InboxIssueDetailsStore implements IInboxIssueDetailsStore {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.inboxService.patchInboxIssue(
|
await this.inboxService.patchInboxIssue(workspaceSlug, projectId, inboxId, issueId, { issue: data });
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
inboxId,
|
|
||||||
issueId,
|
|
||||||
{ issue: data },
|
|
||||||
this.rootStore.user.currentUser ?? undefined
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
@ -224,14 +211,7 @@ export class InboxIssueDetailsStore implements IInboxIssueDetailsStore {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.inboxService.markInboxStatus(
|
await this.inboxService.markInboxStatus(workspaceSlug, projectId, inboxId, issueId, data);
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
inboxId,
|
|
||||||
issueId,
|
|
||||||
data,
|
|
||||||
this.rootStore.user.currentUser ?? undefined
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
@ -259,13 +239,7 @@ export class InboxIssueDetailsStore implements IInboxIssueDetailsStore {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.inboxService.deleteInboxIssue(
|
await this.inboxService.deleteInboxIssue(workspaceSlug, projectId, inboxId, issueId);
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
inboxId,
|
|
||||||
issueId,
|
|
||||||
this.rootStore.user.currentUser ?? undefined
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
|
@ -251,12 +251,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.issueService.createIssue(
|
const response = await this.issueService.createIssue(workspaceSlug, projectId, data);
|
||||||
workspaceSlug,
|
|
||||||
projectId,
|
|
||||||
data,
|
|
||||||
this.rootStore.user.currentUser!
|
|
||||||
);
|
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
@ -283,9 +278,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
this.error = null;
|
this.error = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
const user = this.rootStore.user.currentUser ?? undefined;
|
const response = await this.issueService.createIssue(workspaceSlug, projectId, data);
|
||||||
|
|
||||||
const response = await this.issueService.createIssue(workspaceSlug, projectId, data, user);
|
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
@ -323,7 +316,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
|
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
const response = await this.issueService.patchIssue(workspaceSlug, projectId, issueId, data, user);
|
const response = await this.issueService.patchIssue(workspaceSlug, projectId, issueId, data);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
@ -365,7 +358,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
|
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
|
|
||||||
const response = await this.issueService.deleteIssue(workspaceSlug, projectId, issueId, user);
|
const response = await this.issueService.deleteIssue(workspaceSlug, projectId, issueId);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = false;
|
this.loader = false;
|
||||||
@ -521,8 +514,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
workspaceSlug,
|
workspaceSlug,
|
||||||
projectId,
|
projectId,
|
||||||
issueId,
|
issueId,
|
||||||
data,
|
data
|
||||||
undefined
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const _issueComments = {
|
const _issueComments = {
|
||||||
@ -551,8 +543,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
projectId,
|
projectId,
|
||||||
issueId,
|
issueId,
|
||||||
commentId,
|
commentId,
|
||||||
data,
|
data
|
||||||
undefined
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const _issueComments = {
|
const _issueComments = {
|
||||||
@ -577,7 +568,7 @@ export class IssueDetailStore implements IIssueDetailStore {
|
|||||||
[issueId]: this.issue_comments[issueId].filter((comment: any) => comment.id != commentId),
|
[issueId]: this.issue_comments[issueId].filter((comment: any) => comment.id != commentId),
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.issueCommentService.deleteIssueComment(workspaceSlug, projectId, issueId, commentId, undefined);
|
await this.issueCommentService.deleteIssueComment(workspaceSlug, projectId, issueId, commentId);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.issue_comments = _issueComments;
|
this.issue_comments = _issueComments;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user