Merge branch 'preview' of gurusainath:makeplane/plane into revamp-estimates

This commit is contained in:
guru_sainath 2024-05-25 09:11:46 +05:30
commit a3c9d5639e
29 changed files with 197 additions and 112 deletions

View File

@ -19,14 +19,14 @@ const InstanceAIPage = observer(() => {
return (
<>
<PageHeader title="Artificial Intelligence - God Mode" />
<div className="relative container mx-auto w-full h-full p-8 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 pb-3 space-y-1 flex-shrink-0">
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<div className="text-xl font-medium text-custom-text-100">AI features for all your workspaces</div>
<div className="text-sm font-normal text-custom-text-300">
Configure your AI API credentials so Plane AI features are turned on for all your workspaces.
</div>
</div>
<div className="flex-grow overflow-hidden overflow-y-auto">
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
{formattedConfig ? (
<InstanceAIForm config={formattedConfig} />
) : (

View File

@ -64,8 +64,8 @@ const InstanceGithubAuthenticationPage = observer(() => {
return (
<>
<PageHeader title="Authentication - God Mode" />
<div className="relative container mx-auto w-full h-full p-8 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 pb-3 space-y-1 flex-shrink-0">
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<AuthenticationMethodCard
name="Github"
description="Allow members to login or sign up to plane with their Github accounts."
@ -93,7 +93,7 @@ const InstanceGithubAuthenticationPage = observer(() => {
withBorder={false}
/>
</div>
<div className="flex-grow overflow-hidden overflow-y-auto">
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md p-4">
{formattedConfig ? (
<InstanceGithubConfigForm config={formattedConfig} />
) : (

View File

@ -58,8 +58,8 @@ const InstanceGoogleAuthenticationPage = observer(() => {
return (
<>
<PageHeader title="Authentication - God Mode" />
<div className="relative container mx-auto w-full h-full p-8 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 pb-3 space-y-1 flex-shrink-0">
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<AuthenticationMethodCard
name="Google"
description="Allow members to login or sign up to plane with their Google
@ -81,7 +81,7 @@ const InstanceGoogleAuthenticationPage = observer(() => {
withBorder={false}
/>
</div>
<div className="flex-grow overflow-hidden overflow-y-auto">
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md p-4">
{formattedConfig ? (
<InstanceGoogleConfigForm config={formattedConfig} />
) : (

View File

@ -119,14 +119,14 @@ const InstanceAuthenticationPage = observer(() => {
return (
<>
<PageHeader title="Authentication - God Mode" />
<div className="relative container mx-auto w-full h-full p-8 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 pb-3 space-y-1 flex-shrink-0">
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<div className="text-xl font-medium text-custom-text-100">Manage authentication for your instance</div>
<div className="text-sm font-normal text-custom-text-300">
Configure authentication modes for your team and restrict sign ups to be invite only.
</div>
</div>
<div className="flex-grow overflow-hidden overflow-y-auto">
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
{formattedConfig ? (
<div className="space-y-3">
<div className="text-lg font-medium">Authentication modes</div>

View File

@ -19,8 +19,8 @@ const InstanceEmailPage = observer(() => {
return (
<>
<PageHeader title="Email - God Mode" />
<div className="relative container mx-auto w-full h-full p-8 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 pb-3 space-y-1 flex-shrink-0">
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<div className="text-xl font-medium text-custom-text-100">Secure emails from your own instance</div>
<div className="text-sm font-normal text-custom-text-300">
Plane can send useful emails to you and your users from your own instance without talking to the Internet.
@ -30,7 +30,7 @@ const InstanceEmailPage = observer(() => {
</div>
</div>
</div>
<div className="flex-grow overflow-hidden overflow-y-auto">
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
{formattedConfig ? (
<InstanceEmailForm config={formattedConfig} />
) : (

View File

@ -51,7 +51,7 @@ export const SendTestEmailModal: FC<Props> = (props) => {
setSendEmailStep(ESendEmailSteps.SUCCESS);
})
.catch((error) => {
setError(error?.message || "Failed to send email");
setError(error?.error || "Failed to send email");
setSendEmailStep(ESendEmailSteps.FAILED);
})
.finally(() => {

View File

@ -10,15 +10,15 @@ function GeneralPage() {
console.log("instance", instance);
return (
<>
<div className="relative container mx-auto w-full h-full p-8 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 pb-3 space-y-1 flex-shrink-0">
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<div className="text-xl font-medium text-custom-text-100">General settings</div>
<div className="text-sm font-normal text-custom-text-300">
Change the name of your instance and instance admin e-mail addresses. Enable or disable telemetry in your
instance.
</div>
</div>
<div className="flex-grow overflow-hidden overflow-y-auto">
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
{instance && instanceAdmins && (
<GeneralConfigurationForm instance={instance} instanceAdmins={instanceAdmins} />
)}

View File

@ -332,42 +332,90 @@ body {
}
/* scrollbar style */
::-webkit-scrollbar {
display: none;
@-moz-document url-prefix() {
* {
scrollbar-width: none;
}
.vertical-scrollbar,
.horizontal-scrollbar {
scrollbar-width: initial;
scrollbar-color: rgba(96, 100, 108, 0.1) transparent;
}
.vertical-scrollbar:hover,
.horizontal-scrollbar:hover {
scrollbar-color: rgba(96, 100, 108, 0.25) transparent;
}
.vertical-scrollbar:active,
.horizontal-scrollbar:active {
scrollbar-color: rgba(96, 100, 108, 0.7) transparent;
}
}
.horizontal-scroll-enable {
overflow-x: scroll;
.vertical-scrollbar {
overflow-y: auto;
}
.horizontal-scroll-enable::-webkit-scrollbar {
.horizontal-scrollbar {
overflow-x: auto;
}
.vertical-scrollbar::-webkit-scrollbar,
.horizontal-scrollbar::-webkit-scrollbar {
display: block;
height: 7px;
width: 0;
}
.vertical-scrollbar::-webkit-scrollbar-track,
.horizontal-scrollbar::-webkit-scrollbar-track {
background-color: transparent;
border-radius: 9999px;
}
.vertical-scrollbar::-webkit-scrollbar-thumb,
.horizontal-scrollbar::-webkit-scrollbar-thumb {
background-clip: padding-box;
background-color: rgba(96, 100, 108, 0.1);
border-radius: 9999px;
}
.vertical-scrollbar:hover::-webkit-scrollbar-thumb,
.horizontal-scrollbar:hover::-webkit-scrollbar-thumb {
background-color: rgba(96, 100, 108, 0.25);
}
.vertical-scrollbar::-webkit-scrollbar-thumb:hover,
.horizontal-scrollbar::-webkit-scrollbar-thumb:hover {
background-color: rgba(96, 100, 108, 0.5);
}
.vertical-scrollbar::-webkit-scrollbar-thumb:active,
.horizontal-scrollbar::-webkit-scrollbar-thumb:active {
background-color: rgba(96, 100, 108, 0.7);
}
.vertical-scrollbar::-webkit-scrollbar-corner,
.horizontal-scrollbar::-webkit-scrollbar-corner {
background-color: transparent;
}
.vertical-scrollbar-margin-top-md::-webkit-scrollbar-track {
margin-top: 44px;
}
.horizontal-scroll-enable::-webkit-scrollbar-track {
height: 7px;
background-color: rgba(var(--color-background-100));
/* scrollbar sm size */
.scrollbar-sm::-webkit-scrollbar {
height: 12px;
width: 12px;
}
.horizontal-scroll-enable::-webkit-scrollbar-thumb {
border-radius: 5px;
background-color: rgba(var(--color-scrollbar));
.scrollbar-sm::-webkit-scrollbar-thumb {
border: 3px solid rgba(0, 0, 0, 0);
}
.vertical-scroll-enable::-webkit-scrollbar {
display: block;
width: 5px;
/* scrollbar md size */
.scrollbar-md::-webkit-scrollbar {
height: 14px;
width: 14px;
}
.vertical-scroll-enable::-webkit-scrollbar-track {
width: 5px;
.scrollbar-md::-webkit-scrollbar-thumb {
border: 3px solid rgba(0, 0, 0, 0);
}
/* scrollbar lg size */
.vertical-scroll-enable::-webkit-scrollbar-thumb {
border-radius: 5px;
background-color: rgba(var(--color-background-90));
.scrollbar-lg::-webkit-scrollbar {
height: 16px;
width: 16px;
}
.scrollbar-lg::-webkit-scrollbar-thumb {
border: 4px solid rgba(0, 0, 0, 0);
}
/* end scrollbar style */

View File

@ -19,14 +19,14 @@ const InstanceImagePage = observer(() => {
return (
<>
<PageHeader title="Image - God Mode" />
<div className="relative container mx-auto w-full h-full p-8 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 pb-3 space-y-1 flex-shrink-0">
<div className="relative container mx-auto w-full h-full p-4 py-4 space-y-6 flex flex-col">
<div className="border-b border-custom-border-100 mx-4 py-4 space-y-1 flex-shrink-0">
<div className="text-xl font-medium text-custom-text-100">Third-party image libraries</div>
<div className="text-sm font-normal text-custom-text-300">
Let your users search and choose images from third-party libraries
</div>
</div>
<div className="flex-grow overflow-hidden overflow-y-auto">
<div className="flex-grow overflow-hidden overflow-y-scroll vertical-scrollbar scrollbar-md px-4">
{formattedConfig ? (
<InstanceImageConfigForm config={formattedConfig} />
) : (

View File

@ -38,7 +38,7 @@ export const HelpSection: FC = observer(() => {
// refs
const helpOptionsRef = useRef<HTMLDivElement | null>(null);
const redirectionLink = encodeURI(WEB_BASE_URL + "/create-workspace");
const redirectionLink = encodeURI(WEB_BASE_URL + "/");
return (
<div

View File

@ -56,7 +56,7 @@ export const SidebarMenu = observer(() => {
};
return (
<div className="flex h-full w-full flex-col gap-2.5 overflow-y-auto px-4 py-4">
<div className="flex h-full w-full flex-col gap-2.5 overflow-y-scroll vertical-scrollbar scrollbar-sm px-4 py-4">
{INSTANCE_ADMIN_LINKS.map((item, index) => {
const isActive = item.href === pathName || pathName.includes(item.href);
return (

View File

@ -158,6 +158,7 @@ export const InstanceSetupForm: FC = (props) => {
onError={() => setIsSubmitting(false)}
>
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
<input type="hidden" name="is_telemetry_enabled" value={formData.is_telemetry_enabled ? "True" : "False"} />
<div className="flex flex-col sm:flex-row items-center gap-4">
<div className="w-full space-y-1">
@ -319,8 +320,6 @@ export const InstanceSetupForm: FC = (props) => {
<div>
<Checkbox
id="is_telemetry_enabled"
name="is_telemetry_enabled"
value={formData.is_telemetry_enabled ? "True" : "False"}
onChange={() => handleFormChange("is_telemetry_enabled", !formData.is_telemetry_enabled)}
checked={formData.is_telemetry_enabled}
/>

View File

@ -7,9 +7,9 @@ import { useTheme as nextUseTheme } from "next-themes";
// ui
import { Button, getButtonStyling } from "@plane/ui";
// helpers
import { resolveGeneralTheme } from "helpers/common.helper";
import { WEB_BASE_URL, resolveGeneralTheme } from "helpers/common.helper";
// hooks
import { useInstance, useTheme } from "@/hooks/store";
import { useTheme } from "@/hooks/store";
// icons
import TakeoffIconLight from "/public/logos/takeoff-icon-light.svg";
import TakeoffIconDark from "/public/logos/takeoff-icon-dark.svg";
@ -17,11 +17,10 @@ import TakeoffIconDark from "/public/logos/takeoff-icon-dark.svg";
export const NewUserPopup: React.FC = observer(() => {
// hooks
const { isNewUserPopup, toggleNewUserPopup } = useTheme();
const { config } = useInstance();
// theme
const { resolvedTheme } = nextUseTheme();
const redirectionLink = `${config?.app_base_url ? `${config?.app_base_url}/create-workspace` : `/god-mode/`}`;
const redirectionLink = encodeURI(WEB_BASE_URL + "/create-workspace");
if (!isNewUserPopup) return <></>;
return (

View File

@ -17,6 +17,7 @@ AUTHENTICATION_ERROR_CODES = {
"INVALID_EMAIL_SIGN_UP": 5045,
"INVALID_EMAIL_MAGIC_SIGN_UP": 5050,
"MAGIC_SIGN_UP_EMAIL_CODE_REQUIRED": 5055,
"EMAIL_PASSWORD_AUTHENTICATION_DISABLED": 5056,
# Sign In
"USER_DOES_NOT_EXIST": 5060,
"AUTHENTICATION_FAILED_SIGN_IN": 5065,

View File

@ -41,8 +41,10 @@ class EmailProvider(CredentialAdapter):
if ENABLE_EMAIL_PASSWORD == "0":
raise AuthenticationException(
error_code=AUTHENTICATION_ERROR_CODES["ENABLE_EMAIL_PASSWORD"],
error_message="ENABLE_EMAIL_PASSWORD",
error_code=AUTHENTICATION_ERROR_CODES[
"EMAIL_PASSWORD_AUTHENTICATION_DISABLED"
],
error_message="EMAIL_PASSWORD_AUTHENTICATION_DISABLED",
)
def set_user_data(self):

View File

@ -148,7 +148,7 @@ class InstanceEndpoint(BaseAPIView):
data["app_base_url"] = settings.APP_BASE_URL
instance_data = serializer.data
instance_data["workspaces_exist"] = Workspace.objects.count() > 1
instance_data["workspaces_exist"] = Workspace.objects.count() >= 1
response_data = {"config": data, "instance": instance_data}
return Response(response_data, status=status.HTTP_200_OK)

View File

@ -68,7 +68,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id, nestingLevel: nestingLevel });
const issue = issuesMap[issueId];
const subIssuesCount = issue.sub_issues_count;
const subIssuesCount = issue?.sub_issues_count ?? 0;
const { isMobile } = usePlatformOS();

View File

@ -63,7 +63,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
const currentLayout = `${activeLayout} layout`;
// derived values
const stateDetails = getStateById(issue.state_id);
const subIssueCount = issue.sub_issues_count;
const subIssueCount = issue?.sub_issues_count ?? 0;
const issueOperations = useMemo(
() => ({

View File

@ -19,7 +19,7 @@ export const SpreadsheetSubIssueColumn: React.FC<Props> = observer((props: Props
// hooks
const { workspaceSlug } = useAppRouter();
// derived values
const subIssueCount = issue.sub_issues_count;
const subIssueCount = issue?.sub_issues_count ?? 0;
const redirectToIssueDetail = () => {
router.push({

View File

@ -203,7 +203,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
};
const disableUserActions = !canEditProperties(issueDetail.project_id);
const subIssuesCount = issueDetail.sub_issues_count;
const subIssuesCount = issueDetail?.sub_issues_count ?? 0;
return (
<>

View File

@ -61,7 +61,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
undefined;
const subIssueHelpers = subIssueHelpersByIssueId(parentIssueId);
const subIssueCount = issue?.sub_issues_count || 0;
const subIssueCount = issue?.sub_issues_count ?? 0;
const handleIssuePeekOverview = (issue: TIssue) =>
workspaceSlug &&

View File

@ -59,9 +59,8 @@ const calculateShades = (hexValue: string): TShades => {
return shades as TShades;
};
export const applyTheme = (palette: string, isDarkPalette: boolean) => {
export const applyTheme = (palette: string, isDarkPalette: boolean, dom: HTMLElement | null) => {
if (!palette) return;
const dom = document?.querySelector<HTMLElement>("[data-theme='custom']");
// palette: [bg, text, primary, sidebarBg, sidebarText]
const values: string[] = palette.split(",");
values.push(isDarkPalette ? "dark" : "light");

View File

@ -22,7 +22,7 @@ const StoreWrapper: FC<TStoreWrapper> = observer((props) => {
const { sidebarCollapsed, toggleSidebar } = useAppTheme();
const { data: userProfile } = useUserProfile();
// states
const [dom, setDom] = useState<undefined | HTMLElement>();
const [dom, setDom] = useState<HTMLElement | null>(null);
/**
* Sidebar collapsed fetching from local storage
@ -38,19 +38,40 @@ const StoreWrapper: FC<TStoreWrapper> = observer((props) => {
* Setting up the theme of the user by fetching it from local storage
*/
useEffect(() => {
if (!userProfile?.theme?.theme) return;
if (window) setDom(() => window.document?.querySelector<HTMLElement>("[data-theme='custom']") || undefined);
setTheme(userProfile?.theme?.theme || "system");
if (userProfile?.theme?.theme === "custom" && userProfile?.theme?.palette && dom)
if (!userProfile?.theme?.theme) return;
if (userProfile?.theme?.theme === "custom" && userProfile?.theme?.palette) {
applyTheme(
userProfile?.theme?.palette !== ",,,,"
? userProfile?.theme?.palette
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
false
false,
dom
);
else unsetCustomCssVariables();
}, [userProfile, userProfile?.theme?.theme, userProfile?.theme?.palette, setTheme, dom]);
} else unsetCustomCssVariables();
}, [userProfile, userProfile?.theme, userProfile?.theme?.palette, setTheme, dom]);
useEffect(() => {
if (dom) return;
const observer = new MutationObserver((mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === "childList") {
const customThemeElement = window.document?.querySelector<HTMLElement>("[data-theme='custom']");
if (customThemeElement) {
setDom(customThemeElement);
observer.disconnect();
break;
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
return () => observer.disconnect();
}, [dom]);
useEffect(() => {
if (!router.query) return;

View File

@ -69,6 +69,10 @@ const nextConfig = {
const ADMIN_BASE_URL = process.env.NEXT_PUBLIC_ADMIN_BASE_URL || "";
const ADMIN_BASE_PATH = process.env.NEXT_PUBLIC_ADMIN_BASE_PATH || "";
const GOD_MODE_BASE_URL = ADMIN_BASE_URL + ADMIN_BASE_PATH;
rewrites.push({
source: "/god-mode",
destination: `${GOD_MODE_BASE_URL}/`,
})
rewrites.push({
source: "/god-mode/:path*",
destination: `${GOD_MODE_BASE_URL}/:path*`,

View File

@ -293,24 +293,26 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
const response = await this.createIssue(workspaceSlug, projectId, data, cycleId);
if (data.module_ids && data.module_ids.length > 0)
const quickAddIssueIndex = this.issues[cycleId].findIndex((_issueId) => _issueId === data.id);
if (quickAddIssueIndex >= 0) {
runInAction(() => {
this.issues[cycleId].splice(quickAddIssueIndex, 1);
this.rootIssueStore.issues.removeIssue(data.id);
});
}
if (data.module_ids && data.module_ids.length > 0) {
await this.rootStore.moduleIssues.changeModulesInIssue(
workspaceSlug,
projectId,
response.id,
data.module_ids,
[]
);
)
}
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
const quickAddIssueIndex = this.issues[cycleId].findIndex((_issueId) => _issueId === data.id);
if (quickAddIssueIndex >= 0)
runInAction(() => {
this.issues[cycleId].splice(quickAddIssueIndex, 1);
this.rootIssueStore.issues.removeIssue(data.id);
});
return response;
} catch (error) {
if (cycleId) this.fetchIssues(workspaceSlug, projectId, "mutation", cycleId);

View File

@ -111,8 +111,8 @@ export class IssueStore implements IIssueStore {
// store handlers from issue detail
// parent
if (issue && issue?.parent && issue?.parent?.id) {
const parentIssue = await this.issueService.retrieve(workspaceSlug, projectId, issue?.parent?.id);
if (issue && issue?.parent && issue?.parent?.id && issue?.parent?.project_id) {
const parentIssue = await this.issueService.retrieve(workspaceSlug, issue.parent.project_id, issue?.parent?.id);
this.rootIssueDetailStore.rootIssueStore.issues.addIssue([parentIssue]);
}
// assignees

View File

@ -294,17 +294,19 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
const response = await this.createIssue(workspaceSlug, projectId, data, moduleId);
if (data.cycle_id && data.cycle_id !== "")
await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]);
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
const quickAddIssueIndex = this.issues[moduleId].findIndex((_issueId) => _issueId === data.id);
if (quickAddIssueIndex >= 0)
if (quickAddIssueIndex >= 0) {
runInAction(() => {
this.issues[moduleId].splice(quickAddIssueIndex, 1);
this.rootIssueStore.issues.removeIssue(data.id);
});
}
if (data.cycle_id && data.cycle_id !== "") {
await this.rootStore.cycleIssues.addCycleToIssue(workspaceSlug, projectId, data.cycle_id, response.id)
}
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
return response;
} catch (error) {

View File

@ -239,24 +239,27 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI
const response = await this.createIssue(workspaceSlug, projectId, data, viewId);
if (data.cycle_id && data.cycle_id !== "")
await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]);
const quickAddIssueIndex = this.issues[viewId].findIndex((_issueId) => _issueId === data.id);
if (quickAddIssueIndex >= 0) {
runInAction(() => {
this.issues[viewId].splice(quickAddIssueIndex, 1);
this.rootIssueStore.issues.removeIssue(data.id);
});
}
if (data.module_ids && data.module_ids.length > 0)
if (data.cycle_id && data.cycle_id !== "") {
await this.rootStore.cycleIssues.addCycleToIssue(workspaceSlug, projectId, data.cycle_id, response.id)
}
if (data.module_ids && data.module_ids.length > 0) {
await this.rootStore.moduleIssues.changeModulesInIssue(
workspaceSlug,
projectId,
response.id,
data.module_ids,
[]
);
const quickAddIssueIndex = this.issues[viewId].findIndex((_issueId) => _issueId === data.id);
if (quickAddIssueIndex >= 0)
runInAction(() => {
this.issues[viewId].splice(quickAddIssueIndex, 1);
this.rootIssueStore.issues.removeIssue(data.id);
});
)
}
return response;
} catch (error) {

View File

@ -243,24 +243,29 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
const response = await this.createIssue(workspaceSlug, projectId, data);
if (data.cycle_id && data.cycle_id !== "")
await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]);
const quickAddIssueIndex = this.issues[projectId].findIndex((_issueId) => _issueId === data.id);
if (quickAddIssueIndex >= 0) {
runInAction(() => {
this.issues[projectId].splice(quickAddIssueIndex, 1);
this.rootStore.issues.removeIssue(data.id);
});
}
if (data.module_ids && data.module_ids.length > 0)
//TODO: error handling needs to be improved for rare cases
if (data.cycle_id && data.cycle_id !== "") {
await this.rootStore.cycleIssues.addCycleToIssue(workspaceSlug, projectId, data.cycle_id, response.id)
}
if (data.module_ids && data.module_ids.length > 0) {
await this.rootStore.moduleIssues.changeModulesInIssue(
workspaceSlug,
projectId,
response.id,
data.module_ids,
[]
);
const quickAddIssueIndex = this.issues[projectId].findIndex((_issueId) => _issueId === data.id);
if (quickAddIssueIndex >= 0)
runInAction(() => {
this.issues[projectId].splice(quickAddIssueIndex, 1);
this.rootStore.issues.removeIssue(data.id);
});
)
}
return response;
} catch (error) {
this.fetchIssues(workspaceSlug, projectId, "mutation");