diff --git a/apps/web/app/[locale]/auth/passcode/page.tsx b/apps/web/app/[locale]/auth/passcode/page.tsx index a5d31bd7c..5e59954e2 100644 --- a/apps/web/app/[locale]/auth/passcode/page.tsx +++ b/apps/web/app/[locale]/auth/passcode/page.tsx @@ -4,16 +4,7 @@ import { getAccessTokenCookie, getActiveUserIdCookie } from '@app/helpers'; import { TAuthenticationPasscode, useAuthenticationPasscode } from '@app/hooks'; import { IClassName } from '@app/interfaces'; import { clsxm } from '@app/utils'; -import { - AuthCodeInputField, - Avatar, - BackButton, - Button, - Card, - InputField, - SpinnerLoader, - Text -} from 'lib/components'; +import { AuthCodeInputField, Avatar, BackButton, Button, Card, InputField, SpinnerLoader, Text } from 'lib/components'; import { CircleIcon, TickCircleIconV2 } from 'lib/components/svgs'; import { AuthLayout } from 'lib/layout'; import { useTranslations } from 'next-intl'; @@ -24,393 +15,355 @@ import { FormEvent, useCallback, useEffect, useState } from 'react'; import stc from 'string-to-color'; function AuthPasscode() { - const form = useAuthenticationPasscode(); - const t = useTranslations(); - const router = useRouter(); - - useEffect(() => { - const userId = getActiveUserIdCookie(); - if (userId) { - router.replace('/'); - } - }, [router]); - - return ( - - {t('pages.authLogin.HEADING_WORKSPACE_LINE1')} -
- {t('pages.authLogin.HEADING_WORKSPACE_LINE2')} - - ) : ( - t('pages.authLogin.HEADING_DESCRIPTION') - ) - } - > -
-
- {form.authScreen.screen === 'email' && ( - - )} - {form.authScreen.screen === 'passcode' && ( - - )} - - {form.authScreen.screen === 'workspace' && ( - - )} -
-
-
- ); + const form = useAuthenticationPasscode(); + const t = useTranslations(); + const router = useRouter(); + + useEffect(() => { + const userId = getActiveUserIdCookie(); + if (userId) { + router.replace('/'); + } + }, [router]); + + return ( + + {t('pages.authLogin.HEADING_WORKSPACE_LINE1')} +
+ {t('pages.authLogin.HEADING_WORKSPACE_LINE2')} + + ) : ( + t('pages.authLogin.HEADING_DESCRIPTION') + ) + } + > +
+
+ {form.authScreen.screen === 'email' && } + {form.authScreen.screen === 'passcode' && ( + + )} + + {form.authScreen.screen === 'workspace' && ( + + )} +
+
+
+ ); } export default AuthPasscode; -function EmailScreen({ - form, - className -}: { form: TAuthenticationPasscode } & IClassName) { - const t = useTranslations(); - - const handleSendCode = useCallback( - (e: FormEvent) => { - e.preventDefault(); - - form.sendAuthCodeHandler().then(() => { - form.authScreen.setScreen('passcode'); - }); - }, - [form] - ); - - return ( -
- -
- - {t('pages.auth.ENTER_EMAIL')} - - - {/* Email input */} - - -
- {/* Send code */} -
-
- {t('common.DONT_HAVE_ACCOUNT')} - - {t('common.REGISTER')} - -
-
- - -
-
-
-
- ); +function EmailScreen({ form, className }: { form: TAuthenticationPasscode } & IClassName) { + const t = useTranslations(); + + const handleSendCode = useCallback( + (e: FormEvent) => { + e.preventDefault(); + + form.sendAuthCodeHandler().then(() => { + form.authScreen.setScreen('passcode'); + }); + }, + [form] + ); + + return ( +
+ +
+ + {t('pages.auth.ENTER_EMAIL')} + + + {/* Email input */} + + +
+ {/* Send code */} +
+
+ {t('common.DONT_HAVE_ACCOUNT')} + + {t('common.REGISTER')} + +
+
+ + +
+
+
+
+ ); } -function PasscodeScreen({ - form, - className -}: { form: TAuthenticationPasscode } & IClassName) { - const t = useTranslations(); - - return ( -
- -
- - {t('pages.auth.LOGIN')} - - - {/* Auth code input */} -
- - {t('pages.auth.INPUT_INVITE_CODE')} - - - { - form.setFormValues((v) => ({ ...v, code })); - }} - hintType={ - form.errors['code'] || form.errors['email'] - ? 'error' - : form.authenticated - ? 'success' - : undefined - } - autoFocus={form.authScreen.screen === 'passcode'} - /> - {(form.errors['code'] || form.errors['email']) && ( - - {form.errors['code'] || form.errors['email']} - - )} -
- -
- {/* Send code */} -
-
- - {t('pages.auth.UNRECEIVED_CODE')} - - - {!form.sendCodeLoading && ( - - )} - {form.sendCodeLoading && ( - - )} -
- -
- { - form.authScreen.setScreen('email'); - form.setErrors({}); - }} - /> -
-
- - -
-
-
-
- ); +function PasscodeScreen({ form, className }: { form: TAuthenticationPasscode } & IClassName) { + const t = useTranslations(); + + return ( +
+ +
+ + {t('pages.auth.LOGIN')} + + + {/* Auth code input */} +
+ {t('pages.auth.INPUT_INVITE_CODE')} + + { + form.setFormValues((v) => ({ ...v, code })); + }} + hintType={ + form.errors['code'] || form.errors['email'] + ? 'error' + : form.authenticated + ? 'success' + : undefined + } + autoFocus={form.authScreen.screen === 'passcode'} + /> + {(form.errors['code'] || form.errors['email']) && ( + + {form.errors['code'] || form.errors['email']} + + )} +
+ +
+ {/* Send code */} +
+
+ + {t('pages.auth.UNRECEIVED_CODE')} + + + {!form.sendCodeLoading && ( + + )} + {form.sendCodeLoading && } +
+ +
+ { + form.authScreen.setScreen('email'); + form.setErrors({}); + }} + /> +
+
+ + +
+
+
+
+ ); } -function WorkSpaceScreen({ - form, - className -}: { form: TAuthenticationPasscode } & IClassName) { - const t = useTranslations(); - - const [selectedWorkspace, setSelectedWorkspace] = useState(0); - const [selectedTeam, setSelectedTeam] = useState(''); - const router = useRouter(); - - const signInToWorkspace = useCallback( - (e: any) => { - if (typeof selectedWorkspace !== 'undefined') { - form.handleWorkspaceSubmit( - e, - form.workspaces[selectedWorkspace].token, - selectedTeam - ); - } - }, - [selectedWorkspace, selectedTeam, form] - ); - - useEffect(() => { - if (form.workspaces.length === 1) { - setSelectedWorkspace(0); - } - - const currentTeams = form.workspaces[0]?.current_teams; - - if ( - form.workspaces.length === 1 && - currentTeams?.length === 1 - ) { - setSelectedTeam(currentTeams[0].team_id); - } - if ( - form.workspaces.length === 1 && - (currentTeams?.length || 0) <= 1 - ) { - setTimeout(() => { - document.getElementById('continue-to-workspace')?.click(); - }, 100); - } - }, [form.workspaces]); - - useEffect(() => { - if (form.authScreen.screen === 'workspace') { - const accessToken = getAccessTokenCookie(); - if (accessToken && accessToken.length > 100) { - router.refresh(); - } - } - }, [form.authScreen, router]); - - return ( -
- -
- - {t('pages.auth.SELECT_WORKSPACE')} - - -
- {form.workspaces.map((worksace, index) => ( -
-
-
- {worksace.user.tenant.name} - { - setSelectedWorkspace(index); - if ( - selectedTeam && - !worksace.current_teams - .map((team) => team.team_id) - .includes(selectedTeam) - ) { - setSelectedTeam(worksace.current_teams[0].team_id); - } - }} - > - {selectedWorkspace === index ? ( - - ) : ( - - )} - -
- - {/*
*/} -
- {worksace.current_teams.map((team) => ( -
- - -
- - {team.team_name} - - ({team.team_member_count}) -
-
- { - setSelectedTeam(team.team_id); - if (selectedWorkspace !== index) { - setSelectedWorkspace(index); - } - }} - > - {selectedTeam === team.team_id ? ( - - ) : ( - - )} - -
- ))} -
-
-
- ))} -
- -
-
-
- { - form.authScreen.setScreen('email'); - form.setErrors({}); - }} - /> -
-
- - -
-
-
-
- ); +function WorkSpaceScreen({ form, className }: { form: TAuthenticationPasscode } & IClassName) { + const t = useTranslations(); + + const [selectedWorkspace, setSelectedWorkspace] = useState(0); + const [selectedTeam, setSelectedTeam] = useState(''); + const router = useRouter(); + + const signInToWorkspace = useCallback( + (e: any) => { + if (typeof selectedWorkspace !== 'undefined') { + form.handleWorkspaceSubmit(e, form.workspaces[selectedWorkspace].token, selectedTeam); + } + }, + [selectedWorkspace, selectedTeam, form] + ); + + useEffect(() => { + if (form.workspaces.length === 1) { + setSelectedWorkspace(0); + } + + const currentTeams = form.workspaces[0]?.current_teams; + + if (form.workspaces.length === 1 && currentTeams?.length === 1) { + setSelectedTeam(currentTeams[0].team_id); + } + if (form.workspaces.length === 1 && (currentTeams?.length || 0) <= 1) { + setTimeout(() => { + document.getElementById('continue-to-workspace')?.click(); + }, 100); + } + }, [form.workspaces]); + + useEffect(() => { + if (form.authScreen.screen === 'workspace') { + const accessToken = getAccessTokenCookie(); + if (accessToken && accessToken.length > 100) { + router.refresh(); + } + } + }, [form.authScreen, router]); + + console.log(form); + + return ( +
+ +
+ + {t('pages.auth.SELECT_WORKSPACE')} + + +
+ {form.workspaces?.map((worksace, index) => ( +
+
+
+ {worksace.user.tenant.name} + { + setSelectedWorkspace(index); + if ( + selectedTeam && + !worksace.current_teams + ?.map((team) => team.team_id) + .includes(selectedTeam) + ) { + setSelectedTeam(worksace.current_teams[0].team_id); + } + }} + > + {selectedWorkspace === index ? ( + + ) : ( + + )} + +
+ + {/*
*/} +
+ {worksace.current_teams?.map((team) => ( +
+ + +
+ + {team.team_name} + + ({team.team_member_count}) +
+
+ { + setSelectedTeam(team.team_id); + if (selectedWorkspace !== index) { + setSelectedWorkspace(index); + } + }} + > + {selectedTeam === team.team_id ? ( + + ) : ( + + )} + +
+ ))} +
+
+
+ ))} +
+ +
+
+
+ { + form.authScreen.setScreen('email'); + form.setErrors({}); + }} + /> +
+
+ + +
+
+
+
+ ); } diff --git a/apps/web/app/[locale]/integration/github/page.tsx b/apps/web/app/[locale]/integration/github/page.tsx index 6fa2a0290..328856e60 100644 --- a/apps/web/app/[locale]/integration/github/page.tsx +++ b/apps/web/app/[locale]/integration/github/page.tsx @@ -18,19 +18,10 @@ const GitHub = () => { const installing = useRef(false); - const { installGitHub, getRepositories } = useGitHubIntegration(); - // const { loading: integrationLoading } = useIntegration(); + const { installGitHub, getRepositories } = useGitHubIntegration(); const { getIntegrationTenant, loading: integrationTenantLoading, integrationTenant } = useIntegrationTenant(); - const { loading: loadingIntegrationTypes, integrationTypes, getIntegrationTypes } = useIntegrationTypes(); - - // const params = { - // state: 'http://localhost:3001/integration/github' - // } as { [x: string]: string }; - - // const queries = new URLSearchParams(params || {}); - // const url = `https://github.com/apps/badal-ever-testing-probot/installations/new?${queries.toString()}`; - + const handleInstallGitHub = useCallback(() => { installing.current = true; diff --git a/apps/web/app/api/auth/_signin-workspace/route.ts b/apps/web/app/api/auth/_signin-workspace/route.ts index 5a4eafb5f..f60af0416 100644 --- a/apps/web/app/api/auth/_signin-workspace/route.ts +++ b/apps/web/app/api/auth/_signin-workspace/route.ts @@ -129,8 +129,7 @@ export async function POST(req: Request) { noTeamPopup: true, userId }, - req, - res + { req, res } ); return NextResponse.json({ team, loginResponse }); } @@ -173,8 +172,7 @@ export async function POST(req: Request) { noTeamPopup: true, userId }, - req, - res + { req, res } ); return NextResponse.json({ loginResponse: data }); diff --git a/apps/web/app/api/auth/login/route.ts b/apps/web/app/api/auth/login/route.ts index 79e954e79..6b9a4392e 100644 --- a/apps/web/app/api/auth/login/route.ts +++ b/apps/web/app/api/auth/login/route.ts @@ -145,8 +145,7 @@ export async function POST(req: Request) { noTeamPopup: true, userId }, - req, - res + { req, res } ); return NextResponse.json({ team, loginResponse }); diff --git a/apps/web/app/api/auth/register/route.ts b/apps/web/app/api/auth/register/route.ts index ad0efada8..c5ae81330 100644 --- a/apps/web/app/api/auth/register/route.ts +++ b/apps/web/app/api/auth/register/route.ts @@ -137,8 +137,7 @@ export async function POST(req: Request) { languageId: 'en', // TODO: not sure what should be here userId: user.id }, - req, - res + { req, res } ); return NextResponse.json({ loginRes, team, employee }); diff --git a/apps/web/app/api/auth/signin-email-confirm/route.ts b/apps/web/app/api/auth/signin-email-confirm/route.ts index c7ed9cba7..2ff5a7a6c 100644 --- a/apps/web/app/api/auth/signin-email-confirm/route.ts +++ b/apps/web/app/api/auth/signin-email-confirm/route.ts @@ -19,7 +19,7 @@ export async function POST(req: Request) { const { errors, valid: formValid } = authFormValidate(['email', 'code'], body as any); if (!formValid) { - return NextResponse.json({ errors }); + return NextResponse.json({ errors }, { status: 400 }); } // Accept Invite Flow Start @@ -55,22 +55,31 @@ export async function POST(req: Request) { acceptInviteRes.response.status === 400 || (acceptInviteRes?.data as any).response?.statusCode ) { - return NextResponse.json({ - errors: { - email: 'Authentication code or email address invalid' - } - }); + return NextResponse.json( + { + errors: { + email: 'Authentication code or email address invalid' + } + }, + { status: 400 } + ); } + loginResponse = acceptInviteRes.data; if (!loginResponse) { - return NextResponse.json({ - errors: { - email: 'Authentication code or email address invalid' - } - }); + return NextResponse.json( + { + errors: { + email: 'Authentication code or email address invalid' + } + }, + { status: 400 } + ); } } + + // Login from Invitation if (loginResponse) { console.log('loginResponse>>>', loginResponse); @@ -85,12 +94,16 @@ export async function POST(req: Request) { const organization = organizations?.items[0]; if (!organization) { - return NextResponse.json({ - errors: { - email: 'Your account is not yet ready to be used on the Ever Teams Platform' - } - }); + return NextResponse.json( + { + errors: { + email: 'Your account is not yet ready to be used on the Ever Teams Platform' + } + }, + { status: 400 } + ); } + const { data: teams } = await getAllOrganizationTeamRequest( { tenantId, organizationId: organization.organizationId }, access_token @@ -100,6 +113,7 @@ export async function POST(req: Request) { if (!team) { setNoTeamPopupShowCookie(true); } + setAuthCookies( { access_token: loginResponse.token, @@ -113,13 +127,13 @@ export async function POST(req: Request) { noTeamPopup: true, userId }, - req, - res + { req, res } ); + return NextResponse.json({ team, loginResponse }); } - // Accept Invite Flow End + // Accept Invite Flow End const { data } = await signInEmailConfirmRequest({ code: body.code, email: body.email diff --git a/apps/web/app/helpers/cookies/index.ts b/apps/web/app/helpers/cookies/index.ts index 50521861c..431e42694 100644 --- a/apps/web/app/helpers/cookies/index.ts +++ b/apps/web/app/helpers/cookies/index.ts @@ -77,7 +77,7 @@ export const getLargeStringFromCookies = (COOKIE_NAME: string, ctx?: NextCtx) => return chunks.join(''); }; -export function setAuthCookies(datas: DataParams, req: any, res: any) { +export function setAuthCookies(datas: DataParams, ctx?: NextCtx) { const { refresh_token, access_token, @@ -95,18 +95,18 @@ export function setAuthCookies(datas: DataParams, req: any, res: any) { // Handle Large Access Token // Cookie can support upto 4096 characters only! if (access_token.length <= 4096) { - setCookie(TOKEN_COOKIE_NAME, access_token, { res, req }, true); // cross site cookie + setCookie(TOKEN_COOKIE_NAME, access_token, ctx, true); // cross site cookie } else { - setLargeStringInCookies(TOKEN_COOKIE_NAME, access_token, req, res, true); // cross site cookie + setLargeStringInCookies(TOKEN_COOKIE_NAME, access_token, ctx?.req, ctx?.res, true); // cross site cookie } - setCookie(REFRESH_TOKEN_COOKIE_NAME, refresh_token.token, { res, req }, true); // cross site cookie - setCookie(ACTIVE_TEAM_COOKIE_NAME, teamId, { res, req }); - setCookie(TENANT_ID_COOKIE_NAME, tenantId, { res, req }); - setCookie(ORGANIZATION_ID_COOKIE_NAME, organizationId, { res, req }); - setCookie(ACTIVE_LANGUAGE_COOKIE_NAME, languageId, { res, req }); - setCookie(NO_TEAM_POPUP_SHOW_COOKIE_NAME, noTeamPopup, { res, req }); - setCookie(ACTIVE_USER_ID_COOKIE_NAME, userId, { res, req }); + setCookie(REFRESH_TOKEN_COOKIE_NAME, refresh_token.token, ctx, true); // cross site cookie + setCookie(ACTIVE_TEAM_COOKIE_NAME, teamId, ctx); + setCookie(TENANT_ID_COOKIE_NAME, tenantId, ctx); + setCookie(ORGANIZATION_ID_COOKIE_NAME, organizationId, ctx); + setCookie(ACTIVE_LANGUAGE_COOKIE_NAME, languageId, ctx); + setCookie(NO_TEAM_POPUP_SHOW_COOKIE_NAME, noTeamPopup, ctx); + setCookie(ACTIVE_USER_ID_COOKIE_NAME, userId, ctx); } export function cookiesKeys() { @@ -144,94 +144,86 @@ export function getAccessTokenCookie(ctx?: NextCtx) { return getLargeStringFromCookies(TOKEN_COOKIE_NAME, ctx); // Total chunks cookie not found. } - return getCookie(TOKEN_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(TOKEN_COOKIE_NAME, ctx) as string; } export function getTotalChunksCookie(COOKIE_NAME: string, ctx?: NextCtx) { - return getCookie(`${COOKIE_NAME}_totalChunks`, { - ...(ctx || {}) - }) as string; + return getCookie(`${COOKIE_NAME}_totalChunks`, ctx) as string; } // Refresh Token export function getRefreshTokenCookie(ctx?: NextCtx) { - return getCookie(REFRESH_TOKEN_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(REFRESH_TOKEN_COOKIE_NAME, ctx) as string; } export function setAccessTokenCookie(accessToken: string, ctx?: NextCtx) { - return setCookie(TOKEN_COOKIE_NAME, accessToken, { ...(ctx || {}) }, true); // cross site cookie + return setCookie(TOKEN_COOKIE_NAME, accessToken, ctx, true); // cross site cookie } // Active team id export function getActiveTeamIdCookie(ctx?: NextCtx) { - return getCookie(ACTIVE_TEAM_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(ACTIVE_TEAM_COOKIE_NAME, ctx) as string; } export function setActiveTeamIdCookie(teamIds: string, ctx?: NextCtx) { - return setCookie(ACTIVE_TEAM_COOKIE_NAME, teamIds, { ...(ctx || {}) }); + return setCookie(ACTIVE_TEAM_COOKIE_NAME, teamIds, ctx); } // Active Project id export function getActiveProjectIdCookie(ctx?: NextCtx) { - return getCookie(ACTIVE_PROJECT_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(ACTIVE_PROJECT_COOKIE_NAME, ctx) as string; } export function setActiveProjectIdCookie(teamIds: string, ctx?: NextCtx) { - return setCookie(ACTIVE_PROJECT_COOKIE_NAME, teamIds, { ...(ctx || {}) }); + return setCookie(ACTIVE_PROJECT_COOKIE_NAME, teamIds, ctx); } // Organization Id export function getOrganizationIdCookie(ctx?: NextCtx) { - return getCookie(ORGANIZATION_ID_COOKIE_NAME, { ...ctx }) as string; + return getCookie(ORGANIZATION_ID_COOKIE_NAME, ctx) as string; } export function setOrganizationIdCookie(orgId: string, ctx?: NextCtx) { - return setCookie(ORGANIZATION_ID_COOKIE_NAME, orgId, { ...(ctx || {}) }); + return setCookie(ORGANIZATION_ID_COOKIE_NAME, orgId, ctx); } // Tenant Id export function getTenantIdCookie(ctx?: NextCtx) { - return getCookie(TENANT_ID_COOKIE_NAME, { ...ctx }) as string; + return getCookie(TENANT_ID_COOKIE_NAME, ctx) as string; } // Active tasks export function getActiveTaskIdCookie(ctx?: NextCtx) { - return getCookie(ACTIVE_TASK_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(ACTIVE_TASK_COOKIE_NAME, ctx) as string; } export function setActiveTaskIdCookie(taskId: string, ctx?: NextCtx) { - return setCookie(ACTIVE_TASK_COOKIE_NAME, taskId, { ...(ctx || {}) }); + return setCookie(ACTIVE_TASK_COOKIE_NAME, taskId, ctx); } // Active userId export function getActiveUserIdCookie(ctx?: NextCtx) { - return getCookie(ACTIVE_USER_ID_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(ACTIVE_USER_ID_COOKIE_NAME, ctx) as string; } export function setActiveUserIdCookie(userId: string, ctx?: NextCtx) { - return setCookie(ACTIVE_USER_ID_COOKIE_NAME, userId, { ...(ctx || {}) }); + return setCookie(ACTIVE_USER_ID_COOKIE_NAME, userId, ctx); } export function getNoTeamPopupShowCookie(ctx?: NextCtx) { - return !!getCookie(NO_TEAM_POPUP_SHOW_COOKIE_NAME, { - ...(ctx || {}) - }); + return !!getCookie(NO_TEAM_POPUP_SHOW_COOKIE_NAME, ctx); } export function setNoTeamPopupShowCookie(show: boolean, ctx?: NextCtx) { - return setCookie(NO_TEAM_POPUP_SHOW_COOKIE_NAME, show, { ...(ctx || {}) }); + return setCookie(NO_TEAM_POPUP_SHOW_COOKIE_NAME, show, ctx); } export function setActiveUserTaskCookie(data: { taskId: string; userId: string }, ctx?: NextCtx) { - return setCookie(ACTIVE_USER_TASK_COOKIE_NAME, JSON.stringify(data), { - ...(ctx || {}) - }); + return setCookie(ACTIVE_USER_TASK_COOKIE_NAME, JSON.stringify(data), ctx); } export function getActiveUserTaskCookie(ctx?: NextCtx) { - const data = getCookie(ACTIVE_USER_TASK_COOKIE_NAME, { - ...(ctx || {}) - }); + const data = getCookie(ACTIVE_USER_TASK_COOKIE_NAME, ctx); try { return JSON.parse(data as string) as { taskId: string; userId: string }; @@ -244,27 +236,25 @@ export function getActiveUserTaskCookie(ctx?: NextCtx) { // Active language id export function getActiveLanguageIdCookie(ctx?: NextCtx) { - return getCookie(ACTIVE_LANGUAGE_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(ACTIVE_LANGUAGE_COOKIE_NAME, ctx) as string; } export function setActiveLanguageIdCookie(languageIds: string, ctx?: NextCtx) { - return setCookie(ACTIVE_LANGUAGE_COOKIE_NAME, languageIds, { - ...(ctx || {}) - }); + return setCookie(ACTIVE_LANGUAGE_COOKIE_NAME, languageIds, ctx); } // Timezone export function setActiveTimezoneCookie(timezone: string, ctx?: NextCtx) { - return setCookie(ACTIVE_TIMEZONE_COOKIE_NAME, timezone, { ...(ctx || {}) }); + return setCookie(ACTIVE_TIMEZONE_COOKIE_NAME, timezone, ctx); } export function getActiveTimezoneIdCookie(ctx?: NextCtx) { - return getCookie(ACTIVE_TIMEZONE_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(ACTIVE_TIMEZONE_COOKIE_NAME, ctx) as string; } // Jitsi export function setMeetJwtSessionCookie(token: string, ctx?: NextCtx) { - return setCookie(MEET_JWT_TOKEN_COOKIE_NAME, token, { ...(ctx || {}) }); + return setCookie(MEET_JWT_TOKEN_COOKIE_NAME, token, ctx); } export function getMeetJwtSessionCookie(ctx?: NextCtx) { - return getCookie(MEET_JWT_TOKEN_COOKIE_NAME, { ...(ctx || {}) }) as string; + return getCookie(MEET_JWT_TOKEN_COOKIE_NAME, ctx) as string; } diff --git a/apps/web/app/hooks/auth/useAuthenticationPasscode.ts b/apps/web/app/hooks/auth/useAuthenticationPasscode.ts index 013904f93..9071e399d 100644 --- a/apps/web/app/hooks/auth/useAuthenticationPasscode.ts +++ b/apps/web/app/hooks/auth/useAuthenticationPasscode.ts @@ -1,7 +1,7 @@ 'use client'; import { authFormValidate } from '@app/helpers/validations'; -import { ISigninEmailConfirmWorkspaces } from '@app/interfaces'; +import { ISigninEmailConfirmResponse, ISigninEmailConfirmWorkspaces } from '@app/interfaces'; import { sendAuthCodeAPI, signInEmailAPI, @@ -9,11 +9,10 @@ import { signInWithEmailAndCodeAPI, signInWorkspaceAPI } from '@app/services/client/api'; -import { AxiosError } from 'axios'; +import { AxiosError, isAxiosError } from 'axios'; import { usePathname, useSearchParams } from 'next/navigation'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useQuery } from '../useQuery'; -import { useTranslations } from 'next-intl'; type AuthCodeRef = { focus: () => void; @@ -40,8 +39,6 @@ export function useAuthenticationPasscode() { return query?.get('code'); }, [query]); - const t = useTranslations(); - const loginFromQuery = useRef(false); const inputCodeRef = useRef(null); const [screen, setScreen] = useState<'email' | 'passcode' | 'workspace'>('email'); @@ -76,17 +73,22 @@ export function useAuthenticationPasscode() { const verifySignInEmailConfirmRequest = async ({ email, code }: { email: string; code: string }) => { signInEmailConfirmQueryCall(email, code) .then((res) => { - if (res.data?.workspaces && res.data.workspaces.length) { - setWorkspaces(res.data.workspaces); + const data = res.data as ISigninEmailConfirmResponse; + if (!data.workspaces) { + return; + } + + if (data?.workspaces && data.workspaces.length) { + setWorkspaces(data.workspaces); setScreen('workspace'); } // If user tries to login from public Team Page as an Already a Member // Redirect to the current team automatically - if (pathname === '/team/[teamId]/[profileLink]' && res.data.workspaces.length) { + if (pathname === '/team/[teamId]/[profileLink]' && data.workspaces.length) { if (queryTeamId) { - const currentWorkspace = res.data.workspaces.find((workspace) => + const currentWorkspace = data.workspaces.find((workspace) => workspace.current_teams.map((item) => item.team_id).includes(queryTeamId as string) ); @@ -98,13 +100,17 @@ export function useAuthenticationPasscode() { } } - if (res.data?.status !== 200 && res.data?.status !== 201) { - setErrors({ code: t('pages.auth.INVALID_INVITE_CODE_MESSAGE') }); - } + // if (res.data?.status !== 200 && res.data?.status !== 201) { + // setErrors({ code: t('pages.auth.INVALID_INVITE_CODE_MESSAGE') }); + // } }) - .catch((err: AxiosError) => { - if (err.response?.status === 400) { - setErrors((err.response?.data as any)?.errors || {}); + .catch((err: AxiosError<{ errors: Record }, any> | { errors: Record }) => { + if (isAxiosError(err)) { + if (err.response?.status === 400) { + setErrors(err.response.data?.errors || {}); + } + } else { + setErrors(err.errors || {}); } }); }; diff --git a/apps/web/app/interfaces/IOrganizationTeam.ts b/apps/web/app/interfaces/IOrganizationTeam.ts index d55ecc790..b609dd051 100644 --- a/apps/web/app/interfaces/IOrganizationTeam.ts +++ b/apps/web/app/interfaces/IOrganizationTeam.ts @@ -23,6 +23,12 @@ export interface IOrganizationTeamCreate { export type IOrganizationTeamUpdate = IOrganizationTeamCreate & { id: string }; +export type ITeamRequestParams = { + organizationId: string; + tenantId: string; + relations?: string[]; +}; + export interface IOrganizationTeam { tenantId: string; organizationId: string; diff --git a/apps/web/app/services/client/api/activity/activity.ts b/apps/web/app/services/client/api/activity/activity.ts index 755b37019..d78f8440d 100644 --- a/apps/web/app/services/client/api/activity/activity.ts +++ b/apps/web/app/services/client/api/activity/activity.ts @@ -1,6 +1,7 @@ import { get } from '@app/services/client/axios'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; import { ITimerApps } from '@app/interfaces/timer/ITimerApp'; +import qs from 'qs'; export async function getTimerDailyRequestAPI({ tenantId, @@ -36,11 +37,10 @@ export async function getTimerDailyRequestAPI({ }; if (type) params['types[0]'] = type; if (title) params['title[0]'] = title; - const query = new URLSearchParams(params); + const query = qs.stringify(params); console.log('QUERY', query); - const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/timesheet/activity/daily?${query.toString()}` - : `/timer/daily?${query.toString()}`; + + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/timesheet/activity/daily?${query}` : `/timer/daily?${query}`; return get(endpoint); } diff --git a/apps/web/app/services/client/api/activity/index.ts b/apps/web/app/services/client/api/activity/index.ts index eacc92516..fc4748d50 100644 --- a/apps/web/app/services/client/api/activity/index.ts +++ b/apps/web/app/services/client/api/activity/index.ts @@ -1,6 +1,7 @@ import { ITaskTimesheet } from '@app/interfaces'; import { get } from '@app/services/client/axios'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; +import qs from 'qs'; export async function getTaskTimesheetRequestAPI({ taskId, @@ -28,10 +29,9 @@ export async function getTaskTimesheetRequestAPI({ defaultRange, unitOfTime }; - const query = new URLSearchParams(params); - const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/timesheet/activity?${query.toString()}` - : `/timer/timesheet?${query.toString()}`; + const query = qs.stringify(params); + + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/timesheet/activity?${query}` : `/timer/timesheet?${query}`; return get(endpoint); } diff --git a/apps/web/app/services/client/api/activity/time-slots.ts b/apps/web/app/services/client/api/activity/time-slots.ts index a09eb7318..261bd5392 100644 --- a/apps/web/app/services/client/api/activity/time-slots.ts +++ b/apps/web/app/services/client/api/activity/time-slots.ts @@ -1,6 +1,7 @@ import { get } from '@app/services/client/axios'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; import { ITimerSlotDataRequest } from '@app/interfaces/timer/ITimerSlot'; +import qs from 'qs'; export async function getTimerLogsRequestAPI({ tenantId, @@ -22,10 +23,12 @@ export async function getTimerLogsRequestAPI({ todayEnd: todayEnd.toISOString(), todayStart: todayStart.toISOString() }; - const query = new URLSearchParams(params); + + const query = qs.stringify(params); + const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/timesheet/statistics/time-slots?${query.toString()}` - : `/timer/slots?${query.toString()}`; + ? `/timesheet/statistics/time-slots?${query}` + : `/timer/slots?${query}`; return get(endpoint); } @@ -47,10 +50,10 @@ export async function deleteTimerLogsRequestAPI({ tenantId: tenantId, organizationId: organizationId }; - const query = new URLSearchParams(params); + const query = qs.stringify(params); const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/timesheet/statistics/time-slots?${query.toString()}${idParams}` - : `/timer/slots?${query.toString()}${idParams}`; + ? `/timesheet/statistics/time-slots?${query}${idParams}` + : `/timer/slots?${query}${idParams}`; return get(endpoint); } diff --git a/apps/web/app/services/client/api/auth.ts b/apps/web/app/services/client/api/auth.ts index 6576e4bf7..2bbe7d683 100644 --- a/apps/web/app/services/client/api/auth.ts +++ b/apps/web/app/services/client/api/auth.ts @@ -1,4 +1,4 @@ -import { getRefreshTokenCookie } from '@app/helpers/cookies'; +import { getRefreshTokenCookie, getTenantIdCookie, setAccessTokenCookie } from '@app/helpers/cookies'; import { ISuccessResponse, IUser } from '@app/interfaces'; import { ILoginResponse, IRegisterDataAPI, ISigninEmailConfirmResponse } from '@app/interfaces/IAuthentication'; import api, { get, post } from '../axios'; @@ -6,38 +6,13 @@ import { APP_LOGO_URL, APP_NAME, APP_SIGNATURE, + GAUZY_API_BASE_SERVER_URL, + INVITE_CALLBACK_PATH, VERIFY_EMAIL_CALLBACK_PATH, VERIFY_EMAIL_CALLBACK_URL } from '@app/constants'; - -export const signInWithEmailAndCodeAPI = (email: string, code: string) => { - return api.post(`/auth/login`, { - email, - code - }); -}; - -export const refreshTokenAPI = () => { - return api.post(`/auth/refresh`, { - refresh_token: getRefreshTokenCookie() - }); -}; - -export const registerUserTeamAPI = (data: IRegisterDataAPI) => { - return api.post('/auth/register', data); -}; - -export const sendAuthCodeAPI = (email: string) => { - return api.post<{ status: number; message: string }>(`/auth/send-code`, { - email - }); -}; - -export const signInEmailAPI = (email: string) => { - return api.post<{ status: number; message: string }>(`/auth/signin-email`, { - email - }); -}; +import qs from 'qs'; +import { signInEmailConfirmGauzy } from './auth/invite-accept'; export const getAuthenticatedUserDataAPI = () => { const params = {} as { [x: string]: string }; @@ -47,30 +22,50 @@ export const getAuthenticatedUserDataAPI = () => { params[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(params); + const query = qs.stringify(params); - return get(`/user/me?${query.toString()}`); + return get(`/user/me?${query}`); }; -export const verifyUserEmailByCodeAPI = (code: string) => { - return api.post(`/auth/verify/code`, { code }); -}; -export const signInEmailConfirmAPI = (email: string, code: string) => { - return api.post(`/auth/signin-email-confirm`, { +export async function refreshTokenAPI() { + const refresh_token = getRefreshTokenCookie(); + + if (GAUZY_API_BASE_SERVER_URL.value) { + const { data } = await post<{ token: string }>('/auth/refresh-token', { + refresh_token + }); + + setAccessTokenCookie(data.token); + + return getAuthenticatedUserDataAPI(); + } + + return api.post(`/auth/refresh`, { + refresh_token + }); +} + +export const signInWithEmailAndCodeAPI = (email: string, code: string) => { + return api.post(`/auth/login`, { email, code }); }; -export const signInWorkspaceAPI = (email: string, token: string, selectedTeam: string) => { - return api.post(`/auth/signin-workspace`, { + +export const sendAuthCodeAPI = (email: string) => { + const callbackUrl = `${location.origin}${INVITE_CALLBACK_PATH}`; + + return post<{ status: number; message: string }>(`/auth/send-code`, { email, - token, - teamId: selectedTeam + callbackUrl }); }; -export const verifyUserEmailByTokenAPI = (email: string, token: string) => { - return api.post(`/auth/verify/token`, { email, token }); +export const verifyUserEmailByCodeAPI = (code: string, email: string) => { + const tenantId = getTenantIdCookie(); + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? '/auth/email/verify/code' : `/auth/verify/code`; + + return post(endpoint, { code, tenantId, email }); }; export const resentVerifyUserLinkAPI = (user: IUser) => { @@ -90,3 +85,43 @@ export const resentVerifyUserLinkAPI = (user: IUser) => { return post(`/auth/verify/resend-link`, body); }; + +export const signInEmailAPI = (email: string) => { + const callbackUrl = `${location.origin}${INVITE_CALLBACK_PATH}`; + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? '/auth/signin.email' : `/auth/signin-email`; + + return post<{ status: number; message: string }>(endpoint, { + email, + appMagicSignUrl: callbackUrl, + appName: APP_NAME + }); +}; + +export const verifyUserEmailByTokenAPI = (email: string, token: string) => { + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? '/auth/email/verify' : `/auth/verify/token`; + + return post(endpoint, { email, token }); +}; + +export async function signInEmailConfirmAPI(email: string, code: string) { + if (GAUZY_API_BASE_SERVER_URL.value) { + return signInEmailConfirmGauzy(email, code); + } + + return api.post('/auth/signin-email-confirm', { + email, + code + }); +} + +export const registerUserTeamAPI = (data: IRegisterDataAPI) => { + return api.post('/auth/register', data); +}; + +export const signInWorkspaceAPI = (email: string, token: string, selectedTeam: string) => { + return api.post(`/auth/signin-workspace`, { + email, + token, + teamId: selectedTeam + }); +}; diff --git a/apps/web/app/services/client/api/auth/invite-accept.ts b/apps/web/app/services/client/api/auth/invite-accept.ts new file mode 100644 index 000000000..328671847 --- /dev/null +++ b/apps/web/app/services/client/api/auth/invite-accept.ts @@ -0,0 +1,179 @@ +import { + ILoginResponse, + IInviteVerifyCode, + IInviteVerified, + IUserOrganization, + PaginationResponse, + ITeamRequestParams, + TimerSource, + IOrganizationTeamList, + ISigninEmailConfirmResponse +} from '@app/interfaces'; +import { AcceptInviteParams } from '@app/services/server/requests'; +import { get, post } from '../../axios'; +import { authFormValidate, generateToken, setAuthCookies, setNoTeamPopupShowCookie } from '@app/helpers'; +import qs from 'qs'; +import { AxiosResponse } from 'axios'; + +export function acceptInviteAPI(params: AcceptInviteParams) { + return post('/invite/accept', params) + .then((res) => res.data) + .catch(() => void 0); +} + +export function verifyInviteCodeAPI(params: IInviteVerifyCode) { + return post('/invite/validate-by-code', params).then((res) => res.data); +} + +export function getUserOrganizationsRequest(params: { tenantId: string; userId: string; token: string }) { + const query = JSON.stringify({ + relations: [], + findInput: { + userId: params.userId, + tenantId: params.tenantId + } + }); + + return get>(`/user-organization?data=${encodeURIComponent(query)}`, { + tenantId: params.tenantId, + headers: { + Authorization: `Bearer ${params.token}` + } + }); +} + +export function getAllOrganizationTeamAPI(params: ITeamRequestParams, bearer_token: string) { + const relations = params.relations || [ + 'members', + 'members.role', + 'members.employee', + 'members.employee.user', + 'createdBy', + 'createdBy.employee', + 'projects', + 'projects.repository' + ]; + + const searchQueries = { + 'where[organizationId]': params.organizationId, + 'where[tenantId]': params.tenantId, + source: TimerSource.TEAMS, + withLaskWorkedTask: 'true' + } as { [x: string]: string }; + + relations.forEach((rl, i) => { + searchQueries[`relations[${i}]`] = rl; + }); + + const query = qs.stringify(params); + + return get>(`/organization-team?${query}`, { + tenantId: params.tenantId, + headers: { + Authorization: `Bearer ${bearer_token}` + } + }); +} + +export const signInEmailConfirmAPI = (data: { code: string; email: string }) => { + const { code, email } = data; + return post('/auth/signin.email/confirm?includeTeams=true', { code, email }); +}; + +/** + * + * @param email + * @param code + * @returns + */ +export async function signInEmailConfirmGauzy(email: string, code: string) { + let loginResponse: ILoginResponse | null = null; + const inviteReq = await verifyInviteCodeAPI({ email, code }); + + const { errors, valid: formValid } = authFormValidate(['email', 'code'], { email, code } as any); + + if (!formValid) { + return Promise.reject({ errors }); + } + + if (inviteReq && inviteReq.fullName) { + const password = generateToken(8); + const names = inviteReq.fullName.split(' '); + + const acceptInviteRes = await acceptInviteAPI({ + code, + email, + password, + user: { + firstName: names[0], + lastName: names[1] || '', + email + } + }); + + if (!acceptInviteRes) { + return Promise.reject({ + errors: { + email: 'Authentication code or email address invalid' + } + }); + } + + loginResponse = acceptInviteRes; + } + + if (loginResponse) { + /** + * Get the first team from first organization + */ + const tenantId = loginResponse.user?.tenantId || ''; + const access_token = loginResponse.token; + const userId = loginResponse.user?.id; + + const { data: organizations } = await getUserOrganizationsRequest({ tenantId, userId, token: access_token }); + const organization = organizations?.items[0]; + + if (!organization) { + return Promise.reject({ + errors: { + email: 'Your account is not yet ready to be used on the Ever Teams Platform' + } + }); + } + + const { data: teams } = await getAllOrganizationTeamAPI( + { tenantId, organizationId: organization.organizationId }, + access_token + ); + + const team = teams.items[0]; + if (!team) { + setNoTeamPopupShowCookie(true); + } + + setAuthCookies({ + access_token: loginResponse.token, + refresh_token: { + token: loginResponse.refresh_token + }, + teamId: team?.id, + tenantId, + organizationId: organization?.organizationId, + languageId: 'en', // TODO: not sure what should be here + noTeamPopup: true, + userId + }); + + const response: AxiosResponse<{ loginResponse: ILoginResponse; team: IOrganizationTeamList }> = { + data: { team, loginResponse }, + status: 200, + statusText: '', + headers: {}, + config: {} as any + }; + + return Promise.resolve(response); + } + + return signInEmailConfirmAPI({ email, code }); +} diff --git a/apps/web/app/services/client/api/employee.ts b/apps/web/app/services/client/api/employee.ts index 2fc9a333a..ca9f0529b 100644 --- a/apps/web/app/services/client/api/employee.ts +++ b/apps/web/app/services/client/api/employee.ts @@ -1,6 +1,7 @@ import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; import { IWorkingEmployee, PaginationResponse } from '@app/interfaces'; import { get } from '../axios'; +import qs from 'qs'; export async function getWorkingEmployeesAPI(tenantId: string, organizationId: string) { const params = { @@ -8,9 +9,9 @@ export async function getWorkingEmployeesAPI(tenantId: string, organizationId: s 'where[organizationId]': organizationId, 'relations[0]': 'user' }; - const query = new URLSearchParams(params); + const query = qs.stringify(params); - const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/employee/pagination?${query.toString()}` : '/employee/working'; + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/employee/pagination?${query}` : '/employee/working'; return get>(endpoint, { tenantId }); } diff --git a/apps/web/app/services/client/api/integrations/github.ts b/apps/web/app/services/client/api/integrations/github.ts index f6856257a..f8ab6d3e5 100644 --- a/apps/web/app/services/client/api/integrations/github.ts +++ b/apps/web/app/services/client/api/integrations/github.ts @@ -2,6 +2,7 @@ import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; import { getOrganizationIdCookie, getTenantIdCookie } from '@app/helpers'; import { IGithubMetadata, IGithubRepositories } from '@app/interfaces'; import { get, post } from '../../axios'; +import qs from 'qs'; // TODO export function installGitHubIntegrationAPI(body: any) { @@ -14,26 +15,26 @@ export function oAuthEndpointAuthorizationAPI(body: any) { } export function getGithubIntegrationMetadataAPI(integrationId: string) { - const query = new URLSearchParams({ + const query = qs.stringify({ tenantId: getTenantIdCookie(), organizationId: getOrganizationIdCookie() }); const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/integration/github/${integrationId}/metadata${query.toString()}` + ? `/integration/github/${integrationId}/metadata${query}` : `/integration/github/metadata?integrationId=${integrationId}`; return get(endpoint); } export function getGithubIntegrationRepositoriesAPI(integrationId: string) { - const query = new URLSearchParams({ + const query = qs.stringify({ tenantId: getTenantIdCookie(), organizationId: getOrganizationIdCookie() }); const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/integration/github/${integrationId}/repositories${query.toString()}` + ? `/integration/github/${integrationId}/repositories${query}` : `/integration/github/repositories?integrationId=${integrationId}`; return get(endpoint); diff --git a/apps/web/app/services/client/api/integrations/integration-tenant.ts b/apps/web/app/services/client/api/integrations/integration-tenant.ts index 34150ae48..f9765bf4a 100644 --- a/apps/web/app/services/client/api/integrations/integration-tenant.ts +++ b/apps/web/app/services/client/api/integrations/integration-tenant.ts @@ -2,19 +2,20 @@ import { IIntegrationTenant, PaginationResponse, DeleteResponse } from '@app/int import { deleteApi, get } from '../../axios'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; import { getOrganizationIdCookie, getTenantIdCookie } from '@app/helpers'; +import qs from 'qs'; export function getIntegrationTenantAPI(name: string) { const organizationId = getOrganizationIdCookie(); const tenantId = getTenantIdCookie(); - const query = new URLSearchParams({ + const query = qs.stringify({ 'where[organizationId]': organizationId, 'where[tenantId]': tenantId, 'where[name]': name }); const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/integration-tenant?${query.toString()}` + ? `/integration-tenant?${query}` : `/integration-tenant/remember/state?name=${name}`; return get>(endpoint); diff --git a/apps/web/app/services/client/api/invite.ts b/apps/web/app/services/client/api/invite.ts index cb2fec2d1..e23da8111 100644 --- a/apps/web/app/services/client/api/invite.ts +++ b/apps/web/app/services/client/api/invite.ts @@ -3,6 +3,7 @@ import { IInvitation, MyInvitationActionEnum, IInviteCreate, IMyInvitations } fr import { GAUZY_API_BASE_SERVER_URL, INVITE_CALLBACK_PATH, INVITE_CALLBACK_URL } from '@app/constants'; import { deleteApi, get, post, put } from '../axios'; import { getOrganizationIdCookie, getTenantIdCookie } from '@app/helpers'; +import qs from 'qs'; interface IIInviteRequest { email: string; @@ -44,7 +45,7 @@ export async function inviteByEmailsAPI(data: IIInviteRequest, tenantId: string) } export async function getTeamInvitationsAPI(tenantId: string, organizationId: string, role: string, teamId: string) { - const query = new URLSearchParams({ + const query = qs.stringify({ 'where[tenantId]': tenantId, 'where[organizationId]': organizationId, 'where[role][name]': role, @@ -52,7 +53,7 @@ export async function getTeamInvitationsAPI(tenantId: string, organizationId: st 'where[status]': 'INVITED' }); - const endpoint = `/invite?${query.toString()}`; + const endpoint = `/invite?${query}`; return get>(endpoint, { tenantId }); } diff --git a/apps/web/app/services/client/api/organization-team.ts b/apps/web/app/services/client/api/organization-team.ts index 3bbe1b66a..ab01b1e3e 100644 --- a/apps/web/app/services/client/api/organization-team.ts +++ b/apps/web/app/services/client/api/organization-team.ts @@ -14,6 +14,7 @@ import api, { deleteApi, get, post, put } from '../axios'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; import { getOrganizationIdCookie, getTenantIdCookie } from '@app/helpers'; import { createOrganizationProjectAPI } from './projects'; +import qs from 'qs'; export async function getOrganizationTeamsAPI(organizationId: string, tenantId: string) { const relations = [ @@ -37,8 +38,8 @@ export async function getOrganizationTeamsAPI(organizationId: string, tenantId: relations.forEach((rl, i) => { params[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(params); - const endpoint = `/organization-team?${query.toString()}`; + const query = qs.stringify(params); + const endpoint = `/organization-team?${query}`; return get>(endpoint, { tenantId }); } @@ -102,9 +103,9 @@ export async function getOrganizationTeamAPI(teamId: string, organizationId: str params[`relations[${i}]`] = rl; }); - const queries = new URLSearchParams(params); + const queries = qs.stringify(params); - const endpoint = `/organization-team/${teamId}?${queries.toString()}`; + const endpoint = `/organization-team/${teamId}?${queries}`; return get(endpoint); } diff --git a/apps/web/app/services/client/api/public-organization-team.ts b/apps/web/app/services/client/api/public-organization-team.ts index dc77a87a5..a23d4c9ab 100644 --- a/apps/web/app/services/client/api/public-organization-team.ts +++ b/apps/web/app/services/client/api/public-organization-team.ts @@ -2,6 +2,7 @@ import { IDataResponse } from '@app/interfaces'; import { get } from '../axios'; import moment from 'moment'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; +import qs from 'qs'; export function getPublicOrganizationTeamsAPI(profile_link: string, team_id: string) { const relations = [ @@ -25,10 +26,10 @@ export function getPublicOrganizationTeamsAPI(profile_link: string, team_id: str params[`relations[${i}]`] = rl; }); - const queries = new URLSearchParams(params || {}); + const queries = qs.stringify(params || {}); const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/public/team/${profile_link}/${team_id}?${queries.toString()}` + ? `/public/team/${profile_link}/${team_id}?${queries}` : `/public/team/${profile_link}/${team_id}?type=team`; return get(endpoint); @@ -47,10 +48,10 @@ export function getPublicOrganizationTeamsMiscDataAPI(profile_link: string, team params[`relations[${i}]`] = rl; }); - const queries = new URLSearchParams(params || {}); + const queries = qs.stringify(params || {}); const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/public/team/${profile_link}/${team_id}?${queries.toString()}` + ? `/public/team/${profile_link}/${team_id}?${queries}` : `/public/team/${profile_link}/${team_id}?type=misc`; return get(endpoint); diff --git a/apps/web/app/services/client/api/request-to-join-team.ts b/apps/web/app/services/client/api/request-to-join-team.ts index 3cc34c10b..0032c6c42 100644 --- a/apps/web/app/services/client/api/request-to-join-team.ts +++ b/apps/web/app/services/client/api/request-to-join-team.ts @@ -9,17 +9,18 @@ import { } from '@app/interfaces'; import { get, post, put } from '../axios'; import { getOrganizationIdCookie, getTenantIdCookie } from '@app/helpers'; +import qs from 'qs'; export function getRequestToJoinAPI() { const organizationId = getOrganizationIdCookie(); const tenantId = getTenantIdCookie(); - const query = new URLSearchParams({ + const query = qs.stringify({ 'where[organizationId]': organizationId, 'where[tenantId]': tenantId }); - return get>(`/organization-team-join?${query.toString()}`); + return get>(`/organization-team-join?${query}`); } export function requestToJoinAPI(data: IRequestToJoinCreate) { diff --git a/apps/web/app/services/client/api/role-permissions.ts b/apps/web/app/services/client/api/role-permissions.ts index 127d8f0ad..18e432023 100644 --- a/apps/web/app/services/client/api/role-permissions.ts +++ b/apps/web/app/services/client/api/role-permissions.ts @@ -1,6 +1,7 @@ import { IRolePermissions, PaginationResponse } from '@app/interfaces/'; import { get, put } from '../axios'; import { getTenantIdCookie } from '@app/helpers'; +import qs from 'qs'; export function getRolePermissionAPI(id: string) { const tenantId = getTenantIdCookie(); @@ -13,9 +14,9 @@ export function getRolePermissionAPI(id: string) { } }) }; - const query = new URLSearchParams(params); + const query = qs.stringify(params); - return get>(`/role-permissions/${id}?${query.toString()}`); + return get>(`/role-permissions/${id}?${query}`); } export function updateRolePermissionAPI(data: IRolePermissions) { diff --git a/apps/web/app/services/client/api/tasks.ts b/apps/web/app/services/client/api/tasks.ts index ec9b1e961..e9a524197 100644 --- a/apps/web/app/services/client/api/tasks.ts +++ b/apps/web/app/services/client/api/tasks.ts @@ -12,6 +12,7 @@ import { } from '@app/helpers'; import { IUser } from '@app/interfaces'; import { TTasksTimesheetStatisticsParams } from '@app/services/server/requests'; +import qs from 'qs'; export function getTasksByIdAPI(taskId: string) { const organizationId = getOrganizationIdCookie(); @@ -43,9 +44,9 @@ export function getTasksByIdAPI(taskId: string) { obj[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(obj); + const query = qs.stringify(obj); - const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/tasks/${taskId}?${query.toString()}` : `/tasks/${taskId}`; + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/tasks/${taskId}?${query}` : `/tasks/${taskId}`; return get(endpoint); } @@ -78,8 +79,8 @@ export async function getTeamTasksAPI(organizationId: string, tenantId: string, obj[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(obj); - const endpoint = `/tasks/team?${query.toString()}`; + const query = qs.stringify(obj); + const endpoint = `/tasks/team?${query}`; return get>(endpoint, { tenantId }); } @@ -161,21 +162,21 @@ export async function tasksTimesheetStatisticsAPI( // ...(activeTaskId ? { 'taskIds[0]': activeTaskId } : {}), ...employeesParams }; - const globalQueries = new URLSearchParams({ + const globalQueries = qs.stringify({ ...commonParams, defaultRange: 'false' }); - const globalData = await get(`/timesheet/statistics/tasks?${globalQueries.toString()}`, { + const globalData = await get(`/timesheet/statistics/tasks?${globalQueries}`, { tenantId }); - const todayQueries = new URLSearchParams({ + const todayQueries = qs.stringify({ ...commonParams, defaultRange: 'true', unitOfTime: 'day' }); - const todayData = await get(`/timesheet/statistics/tasks?${todayQueries.toString()}`, { + const todayData = await get(`/timesheet/statistics/tasks?${todayQueries}`, { tenantId }); @@ -211,16 +212,16 @@ export async function activeTaskTimesheetStatisticsAPI( ...(activeTaskId ? { 'taskIds[0]': activeTaskId } : {}), ...employeesParams }; - const globalQueries = new URLSearchParams({ + const globalQueries = qs.stringify({ ...commonParams, defaultRange: 'false' }); - const globalData = await get(`/timesheet/statistics/tasks?${globalQueries.toString()}`, { + const globalData = await get(`/timesheet/statistics/tasks?${globalQueries}`, { tenantId }); - const todayQueries = new URLSearchParams({ ...commonParams, defaultRange: 'true', unitOfTime: 'day' }); - const todayData = await get(`/timesheet/statistics/tasks?${todayQueries.toString()}`, { + const todayQueries = qs.stringify({ ...commonParams, defaultRange: 'true', unitOfTime: 'day' }); + const todayData = await get(`/timesheet/statistics/tasks?${todayQueries}`, { tenantId }); @@ -251,7 +252,7 @@ export function allTaskTimesheetStatisticsAPI() { const { employeeIds, ...rest } = params; - const queries = new URLSearchParams({ + const queries = qs.stringify({ ...rest, ...employeeIds.reduce( (acc, v, i) => { diff --git a/apps/web/app/services/client/api/timer.ts b/apps/web/app/services/client/api/timer.ts index 405720e1f..840f0e3a1 100644 --- a/apps/web/app/services/client/api/timer.ts +++ b/apps/web/app/services/client/api/timer.ts @@ -3,10 +3,11 @@ import api, { get, post } from '../axios'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; import { getActiveTaskIdCookie, getActiveTeamIdCookie, getOrganizationIdCookie, getTenantIdCookie } from '@app/helpers'; import { IUser } from '@app/interfaces'; +import qs from 'qs'; export async function getTimerStatusAPI(tenantId: string, organizationId: string) { - const params = new URLSearchParams({ tenantId, organizationId }); - const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/timesheet/timer/status?${params.toString()}` : '/timer/status'; + const params = qs.stringify({ tenantId, organizationId }); + const endpoint = GAUZY_API_BASE_SERVER_URL.value ? `/timesheet/timer/status?${params}` : '/timer/status'; return get(endpoint); } @@ -88,7 +89,7 @@ export async function syncTimerAPI(source: TimerSource, user: IUser | undefined) const tenantId = getTenantIdCookie(); if (GAUZY_API_BASE_SERVER_URL.value) { - await post('/timesheet/timer/stop', { + await post('/timesheet/time-slot', { tenantId, organizationId, logType: 'TRACKED', @@ -96,6 +97,8 @@ export async function syncTimerAPI(source: TimerSource, user: IUser | undefined) employeeId: user?.employee.id, duration: 5 }); + + return getTimerStatusAPI(tenantId, organizationId); } return api.post('/timer/sync', { diff --git a/apps/web/app/services/client/api/timer/timer-status.ts b/apps/web/app/services/client/api/timer/timer-status.ts index 63ab1693a..67231f485 100644 --- a/apps/web/app/services/client/api/timer/timer-status.ts +++ b/apps/web/app/services/client/api/timer/timer-status.ts @@ -1,6 +1,7 @@ import { ITimerStatus } from '@app/interfaces'; import { get } from '../../axios'; import { GAUZY_API_BASE_SERVER_URL } from '@app/constants'; +import qs from 'qs'; export async function getTaskStatusList( tenantId: string, @@ -19,10 +20,10 @@ export async function getTaskStatusList( employeeId: employeeId }; if (organizationTeamId) params.organizationTeamId = organizationTeamId; - const query = new URLSearchParams(params); + const query = qs.stringify(params); const endpoint = GAUZY_API_BASE_SERVER_URL.value - ? `/timesheet/timer/status?${query.toString()}` + ? `/timesheet/timer/status?${query}` : `/timer/status?tenantId=${tenantId}&organizationId=${organizationId}&organizationTeamId=${organizationTeamId}&employeeId=${employeeId}`; return get(endpoint, { tenantId }); diff --git a/apps/web/app/services/server/requests/auth.ts b/apps/web/app/services/server/requests/auth.ts index 9e32cd8be..708e39875 100644 --- a/apps/web/app/services/server/requests/auth.ts +++ b/apps/web/app/services/server/requests/auth.ts @@ -1,8 +1,9 @@ import { VERIFY_EMAIL_CALLBACK_URL, APP_NAME, APP_SIGNATURE, APP_LOGO_URL } from '@app/constants'; import { ISuccessResponse } from '@app/interfaces'; -import { ILoginResponse, IRegisterDataRequest } from '@app/interfaces/IAuthentication'; +import { ILoginResponse, IRegisterDataRequest, ISigninEmailConfirmResponse } from '@app/interfaces/IAuthentication'; import { IUser } from '@app/interfaces/IUserData'; import { serverFetch } from '../fetch'; +import qs from 'qs'; const registerDefaultValue = { appName: APP_NAME, @@ -39,15 +40,17 @@ export function signInEmailRequest(email: string, callbackUrl: string) { body: { email, appMagicSignUrl: callbackUrl, appName: APP_NAME } }); } + export const signInEmailConfirmRequest = (data: { code: string; email: string }) => { const { code, email } = data; - return serverFetch({ + return serverFetch({ path: '/auth/signin.email/confirm?includeTeams=true', method: 'POST', body: { code, email } }); }; + export function signInWorkspaceRequest(email: string, token: string) { return serverFetch({ path: '/auth/signin.workspace', @@ -99,10 +102,10 @@ export const currentAuthenticatedUserRequest = ({ params[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(params); + const query = qs.stringify(params); return serverFetch({ - path: `/user/me?${query.toString()}`, + path: `/user/me?${query}`, method: 'GET', bearer_token }); diff --git a/apps/web/app/services/server/requests/employee.ts b/apps/web/app/services/server/requests/employee.ts index b1cb42037..30e65f9f9 100644 --- a/apps/web/app/services/server/requests/employee.ts +++ b/apps/web/app/services/server/requests/employee.ts @@ -1,6 +1,7 @@ import { PaginationResponse } from '@app/interfaces'; import { ICreateEmployee, IEmployee, IWorkingEmployee } from '@app/interfaces/IEmployee'; import { serverFetch } from '../fetch'; +import qs from 'qs'; export function createEmployeeFromUser(data: ICreateEmployee, bearer_token: string) { return serverFetch({ @@ -18,9 +19,11 @@ export function getOrganizationEmployees(bearer_token: string, tenantId: string, 'where[organizationId]': organizationId, 'relations[0]': 'user' }; - const query = new URLSearchParams(params); + + const query = qs.stringify(params); + return serverFetch>({ - path: `/employee/pagination?${query.toString()}`, + path: `/employee/pagination?${query}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/integrations/github.ts b/apps/web/app/services/server/requests/integrations/github.ts index 08688d252..9bf6c01f0 100644 --- a/apps/web/app/services/server/requests/integrations/github.ts +++ b/apps/web/app/services/server/requests/integrations/github.ts @@ -1,5 +1,6 @@ import { IGithubMetadata, IGithubRepositories, IProjectRepository } from '@app/interfaces'; import { serverFetch } from '../../fetch'; +import qs from 'qs'; export function installGitHubIntegration( data: { @@ -41,12 +42,12 @@ export function getGithubIntegrationMetadataRequest( }, bearer_token: string ) { - const query = new URLSearchParams({ + const query = qs.stringify({ tenantId, organizationId }); return serverFetch({ - path: `/integration/github/${integrationId}/metadata?${query.toString()}`, + path: `/integration/github/${integrationId}/metadata?${query}`, method: 'GET', bearer_token, tenantId: tenantId @@ -65,12 +66,12 @@ export function getGithubIntegrationRepositoriesRequest( }, bearer_token: string ) { - const query = new URLSearchParams({ + const query = qs.stringify({ tenantId, organizationId }); return serverFetch({ - path: `/integration/github/${integrationId}/repositories?${query.toString()}`, + path: `/integration/github/${integrationId}/repositories?${query}`, method: 'GET', bearer_token, tenantId: tenantId diff --git a/apps/web/app/services/server/requests/integrations/index.ts b/apps/web/app/services/server/requests/integrations/index.ts index e55b28354..b2756b4db 100644 --- a/apps/web/app/services/server/requests/integrations/index.ts +++ b/apps/web/app/services/server/requests/integrations/index.ts @@ -1,5 +1,6 @@ import { IIntegration } from '@app/interfaces'; import { serverFetch } from '../../fetch'; +import qs from 'qs'; /** * Get integration @@ -20,7 +21,7 @@ export function getIntegrationRequest( }, bearer_token: string ) { - const query = new URLSearchParams({ + const query = qs.stringify({ filters: JSON.stringify({ searchQuery, integrationTypeId @@ -28,7 +29,7 @@ export function getIntegrationRequest( }); return serverFetch({ - path: `/integration?${query.toString()}`, + path: `/integration?${query}`, method: 'GET', bearer_token, tenantId: tenantId diff --git a/apps/web/app/services/server/requests/integrations/integration-tenant.ts b/apps/web/app/services/server/requests/integrations/integration-tenant.ts index 446e78651..92baac8e2 100644 --- a/apps/web/app/services/server/requests/integrations/integration-tenant.ts +++ b/apps/web/app/services/server/requests/integrations/integration-tenant.ts @@ -1,5 +1,6 @@ import { IIntegrationTenant } from '@app/interfaces'; import { serverFetch } from '../../fetch'; +import qs from 'qs'; /** * Get integration tenant request @@ -12,13 +13,13 @@ export function getIntegrationTenantRequest( { tenantId, organizationId, name }: { tenantId: string; organizationId: string; name: string }, bearer_token: string ) { - const query = new URLSearchParams({ + const query = qs.stringify({ 'where[organizationId]': organizationId, 'where[tenantId]': tenantId, 'where[name]': name }); return serverFetch({ - path: `/integration-tenant?${query.toString()}`, + path: `/integration-tenant?${query}`, method: 'GET', bearer_token, tenantId: tenantId diff --git a/apps/web/app/services/server/requests/invite.ts b/apps/web/app/services/server/requests/invite.ts index 15bb43366..59e21c26c 100644 --- a/apps/web/app/services/server/requests/invite.ts +++ b/apps/web/app/services/server/requests/invite.ts @@ -8,6 +8,7 @@ import { MyInvitationActionEnum } from '@app/interfaces/IInvite'; import { serverFetch } from '../fetch'; +import qs from 'qs'; /** * Invite user using email request @@ -70,15 +71,16 @@ export function getTeamInvitationsRequest( { teamId, tenantId, organizationId, role }: ITeamInvitationsRequest, bearer_token: string ) { - const query = new URLSearchParams({ + const query = qs.stringify({ 'where[tenantId]': tenantId, 'where[organizationId]': organizationId, 'where[role][name]': role, 'where[teams][id][0]': teamId, 'where[status]': 'INVITED' }); + return serverFetch>({ - path: `/invite?${query.toString()}`, + path: `/invite?${query}`, method: 'GET', bearer_token, tenantId: tenantId diff --git a/apps/web/app/services/server/requests/organization-team.ts b/apps/web/app/services/server/requests/organization-team.ts index b473e7104..b4040e9ff 100644 --- a/apps/web/app/services/server/requests/organization-team.ts +++ b/apps/web/app/services/server/requests/organization-team.ts @@ -5,11 +5,13 @@ import { IOrganizationTeamCreate, IOrganizationTeamList, IOrganizationTeamUpdate, - IOrganizationTeamWithMStatus -} from '@app/interfaces/IOrganizationTeam'; + IOrganizationTeamWithMStatus, + ITeamRequestParams +} from '@app/interfaces'; import moment from 'moment'; import { serverFetch } from '../fetch'; import { createOrganizationProjectRequest } from './project'; +import qs from 'qs'; export async function createOrganizationTeamRequest(datas: IOrganizationTeamCreate, bearer_token: string) { // Create project @@ -86,7 +88,7 @@ export function getOrganizationTeamRequest( 'projects', 'projects.repository' ] - }: TeamRequestParams & { teamId: string }, + }: ITeamRequestParams & { teamId: string }, bearer_token: string ) { const params = { @@ -103,7 +105,8 @@ export function getOrganizationTeamRequest( params[`relations[${i}]`] = rl; }); - const queries = new URLSearchParams(params); + const queries = qs.stringify(params); + return serverFetch({ path: `/organization-team/${teamId}?${queries.toString()}`, method: 'GET', @@ -112,12 +115,6 @@ export function getOrganizationTeamRequest( }); } -type TeamRequestParams = { - organizationId: string; - tenantId: string; - relations?: string[]; -}; - export function getAllOrganizationTeamRequest( { organizationId, @@ -132,7 +129,7 @@ export function getAllOrganizationTeamRequest( 'projects', 'projects.repository' ] - }: TeamRequestParams, + }: ITeamRequestParams, bearer_token: string ) { const params = { @@ -146,10 +143,10 @@ export function getAllOrganizationTeamRequest( params[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(params); + const query = qs.stringify(params); return serverFetch>({ - path: `/organization-team?${query.toString()}`, + path: `/organization-team?${query}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/organization.ts b/apps/web/app/services/server/requests/organization.ts index f9da83237..4ff22b50a 100644 --- a/apps/web/app/services/server/requests/organization.ts +++ b/apps/web/app/services/server/requests/organization.ts @@ -15,16 +15,16 @@ export function getUserOrganizationsRequest( { tenantId, userId }: { tenantId: string; userId: string }, bearer_token: string ) { - const query = new URLSearchParams({ - relations: new URLSearchParams([]).toString(), - findInput: new URLSearchParams({ + const query = JSON.stringify({ + relations: [], + findInput: { userId, tenantId - }).toString() + } }); return serverFetch>({ - path: `/user-organization?data=${query.toString()}`, + path: `/user-organization?data=${encodeURIComponent(query)}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/public-organization-team.ts b/apps/web/app/services/server/requests/public-organization-team.ts index 34e19af89..e53088927 100644 --- a/apps/web/app/services/server/requests/public-organization-team.ts +++ b/apps/web/app/services/server/requests/public-organization-team.ts @@ -1,6 +1,7 @@ import { IOrganizationTeamWithMStatus } from '@app/interfaces'; import moment from 'moment'; import { serverFetch } from '../fetch'; +import qs from 'qs'; export function getPublicOrganizationTeamRequest({ profileLink, @@ -30,7 +31,8 @@ export function getPublicOrganizationTeamRequest({ params[`relations[${i}]`] = rl; }); - const queries = new URLSearchParams(params || {}); + const queries = qs.stringify(params || {}); + return serverFetch({ path: `/public/team/${profileLink}/${teamId}?${queries.toString()}`, method: 'GET' @@ -56,7 +58,8 @@ export function getPublicOrganizationTeamMiscDataRequest({ params[`relations[${i}]`] = rl; }); - const queries = new URLSearchParams(params || {}); + const queries = qs.stringify(params || {}); + return serverFetch({ path: `/public/team/${profileLink}/${teamId}?${queries.toString()}`, method: 'GET' diff --git a/apps/web/app/services/server/requests/request-to-join-team.ts b/apps/web/app/services/server/requests/request-to-join-team.ts index 31b250e1d..cff87e5a2 100644 --- a/apps/web/app/services/server/requests/request-to-join-team.ts +++ b/apps/web/app/services/server/requests/request-to-join-team.ts @@ -8,6 +8,7 @@ import { IRequestToJoinActionEnum } from '@app/interfaces'; import { serverFetch } from '../fetch'; +import qs from 'qs'; /** * Request to Join Team request @@ -70,10 +71,10 @@ export function getRequestToJoinRequest({ 'where[organizationId]': organizationId, 'where[tenantId]': tenantId } as { [x: string]: string }; - const query = new URLSearchParams(params); + const query = qs.stringify(params); return serverFetch>({ - path: `/organization-team-join?${query.toString()}`, + path: `/organization-team-join?${query}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/role-permissions.ts b/apps/web/app/services/server/requests/role-permissions.ts index 98872e9d2..f90704b1d 100644 --- a/apps/web/app/services/server/requests/role-permissions.ts +++ b/apps/web/app/services/server/requests/role-permissions.ts @@ -1,5 +1,6 @@ import { IRolePermissions } from '@app/interfaces/IRolePermissions'; import { serverFetch } from '../fetch'; +import qs from 'qs'; export function getRolePermissionsRequest({ bearer_token, @@ -18,10 +19,11 @@ export function getRolePermissionsRequest({ } }) }; - const query = new URLSearchParams(params); + + const query = qs.stringify(params); return serverFetch({ - path: `/role-permissions?${query.toString()}`, + path: `/role-permissions?${query}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/task-labels.ts b/apps/web/app/services/server/requests/task-labels.ts index 28ec48bd9..323909239 100644 --- a/apps/web/app/services/server/requests/task-labels.ts +++ b/apps/web/app/services/server/requests/task-labels.ts @@ -1,5 +1,6 @@ import { ITaskLabelsCreate, ITaskLabelsItemList } from '@app/interfaces'; import { serverFetch } from '../fetch'; +import qs from 'qs'; export function createLabelsRequest(datas: ITaskLabelsCreate, bearer_token: string, tenantId?: any) { return serverFetch({ @@ -56,7 +57,7 @@ export function getTaskLabelsListRequest( }: { tenantId: string; organizationId: string; organizationTeamId: string | null }, bearer_token: string ) { - const params = new URLSearchParams({ + const params = qs.stringify({ tenantId, organizationId, organizationTeamId: organizationTeamId || '' diff --git a/apps/web/app/services/server/requests/tasks.ts b/apps/web/app/services/server/requests/tasks.ts index ef7407a95..63b751554 100644 --- a/apps/web/app/services/server/requests/tasks.ts +++ b/apps/web/app/services/server/requests/tasks.ts @@ -2,6 +2,7 @@ import { DeleteResponse, PaginationResponse, SingleDataResponse } from '@app/int import { ICreateTask, ITeamTask } from '@app/interfaces/ITask'; import { serverFetch } from '../fetch'; import { IUser } from '@app/interfaces'; +import qs from 'qs'; export function getTeamTasksRequest({ tenantId, @@ -43,10 +44,10 @@ export function getTeamTasksRequest({ obj[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(obj); + const query = qs.stringify(obj); return serverFetch>({ - path: `/tasks/team?${query.toString()}`, + path: `/tasks/team?${query}`, method: 'GET', bearer_token, tenantId @@ -90,10 +91,10 @@ export function getTaskByIdRequest({ obj[`relations[${i}]`] = rl; }); - const query = new URLSearchParams(obj); + const query = qs.stringify(obj); return serverFetch({ - path: `/tasks/${taskId}?${query.toString()}`, + path: `/tasks/${taskId}?${query}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/timer.ts b/apps/web/app/services/server/requests/timer.ts index 65f9bf47c..539ff3a79 100644 --- a/apps/web/app/services/server/requests/timer.ts +++ b/apps/web/app/services/server/requests/timer.ts @@ -7,11 +7,13 @@ import { TimerSource } from '@app/interfaces/ITimer'; import { serverFetch } from '../fetch'; +import qs from 'qs'; export function getTimerStatusRequest({ tenantId, organizationId }: ITimerStatusParams, bearer_token: string) { - const params = new URLSearchParams({ tenantId, organizationId }); + const params = qs.stringify({ tenantId, organizationId }); + return serverFetch({ - path: `/timesheet/timer/status?${params.toString()}`, + path: `/timesheet/timer/status?${params}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/timer/daily.ts b/apps/web/app/services/server/requests/timer/daily.ts index 0e30f7c79..e414483d0 100644 --- a/apps/web/app/services/server/requests/timer/daily.ts +++ b/apps/web/app/services/server/requests/timer/daily.ts @@ -1,3 +1,4 @@ +import qs from 'qs'; import { serverFetch } from '../../fetch'; import { ITimerSlotDataRequest } from '@app/interfaces/timer/ITimerSlot'; @@ -31,9 +32,10 @@ export function getEmployeeDailyRequest({ 'activityLevel[end]': activityLevel.end.toString() }; - const query = new URLSearchParams(params); + const query = qs.stringify(params); + return serverFetch({ - path: `/timesheet/activity/daily?${query.toString()}`, + path: `/timesheet/activity/daily?${query}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/timer/status.ts b/apps/web/app/services/server/requests/timer/status.ts index ec83813a0..31daef778 100644 --- a/apps/web/app/services/server/requests/timer/status.ts +++ b/apps/web/app/services/server/requests/timer/status.ts @@ -1,5 +1,6 @@ import { ITimerSlotDataRequest } from '@app/interfaces/timer/ITimerSlot'; import { serverFetch } from '../../fetch'; +import qs from 'qs'; export function getTimerStatusRequest({ bearer_token, @@ -24,9 +25,11 @@ export function getTimerStatusRequest({ todayEnd: todayEnd.toISOString(), 'relations[0]': 'employee' }; - const query = new URLSearchParams(params); + + const query = qs.stringify(params); + return serverFetch({ - path: `/timesheet/timer/status?${query.toString()}`, + path: `/timesheet/timer/status?${query}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/timer/timer-slot.ts b/apps/web/app/services/server/requests/timer/timer-slot.ts index 0806d5444..9ffc18b7e 100644 --- a/apps/web/app/services/server/requests/timer/timer-slot.ts +++ b/apps/web/app/services/server/requests/timer/timer-slot.ts @@ -1,3 +1,4 @@ +import qs from 'qs'; import { serverFetch } from '../../fetch'; import { ITimerSlotDataRequest } from '@app/interfaces/timer/ITimerSlot'; @@ -23,9 +24,10 @@ export function getEmployeeTimeSlotsRequest({ startDate: todayEnd.toISOString(), endDate: todayStart.toISOString() }; - const query = new URLSearchParams(params); + const query = qs.stringify(params); + return serverFetch({ - path: `/timesheet/statistics/time-slots?${query.toString()}`, + path: `/timesheet/statistics/time-slots?${query}`, method: 'GET', bearer_token, tenantId @@ -51,9 +53,9 @@ export function deleteEmployeeTimeSlotsRequest({ tenantId: tenantId, organizationId: organizationId }; - const query = new URLSearchParams(params); + const query = qs.stringify(params); return serverFetch({ - path: `/timesheet/statistics/time-slots?${query.toString()}${idParams}`, + path: `/timesheet/statistics/time-slots?${query}${idParams}`, method: 'GET', bearer_token, tenantId diff --git a/apps/web/app/services/server/requests/timesheet.ts b/apps/web/app/services/server/requests/timesheet.ts index 4dfda5ce6..4a48b9bcd 100644 --- a/apps/web/app/services/server/requests/timesheet.ts +++ b/apps/web/app/services/server/requests/timesheet.ts @@ -1,5 +1,6 @@ import { ITasksTimesheet } from '@app/interfaces/ITimer'; import { serverFetch } from '../fetch'; +import qs from 'qs'; export type TTasksTimesheetStatisticsParams = { tenantId: string; @@ -14,7 +15,7 @@ export type TTasksTimesheetStatisticsParams = { export function tasksTimesheetStatisticsRequest(params: TTasksTimesheetStatisticsParams, bearer_token: string) { const { employeeIds, ...rest } = params; - const queries = new URLSearchParams({ + const queries = qs.stringify({ ...rest, ...employeeIds.reduce( (acc, v, i) => { @@ -26,7 +27,7 @@ export function tasksTimesheetStatisticsRequest(params: TTasksTimesheetStatistic }); return serverFetch({ - path: `/timesheet/statistics/tasks?${queries.toString()}`, + path: `/timesheet/statistics/tasks?${queries}`, method: 'GET', bearer_token, tenantId: params.tenantId @@ -42,7 +43,7 @@ export type TTaskActivityParams = { }; export function taskActivityRequest(params: TTaskActivityParams, bearer_token: string) { - const queries = new URLSearchParams(params); + const queries = qs.stringify(params); return serverFetch({ path: `/timesheet/activity?${queries.toString()}`, diff --git a/apps/web/lib/features/unverified-email.tsx b/apps/web/lib/features/unverified-email.tsx index 3abe9f9cc..104c6a73c 100644 --- a/apps/web/lib/features/unverified-email.tsx +++ b/apps/web/lib/features/unverified-email.tsx @@ -87,13 +87,13 @@ export function ConfirmUserModal({ open, user, closeModal }: { open: boolean; us const handleVerifyEmail = useCallback( (e: React.MouseEvent) => { e.preventDefault(); - if (code.length < 6) return; + if (code.length < 6 || !user) return; - queryCall(code).finally(() => { + queryCall(code, user.email).finally(() => { window.location.reload(); }); }, - [code, queryCall] + [code, queryCall, user] ); return ( diff --git a/apps/web/lib/settings/integration-setting.tsx b/apps/web/lib/settings/integration-setting.tsx index cb858fe87..f1436337b 100644 --- a/apps/web/lib/settings/integration-setting.tsx +++ b/apps/web/lib/settings/integration-setting.tsx @@ -13,6 +13,7 @@ import { Switch } from '@headlessui/react'; import debounce from 'lodash/debounce'; import Link from 'next/link'; import { useParams } from 'next/navigation'; +import qs from 'qs'; export const IntegrationSetting = () => { const t = useTranslations(); @@ -31,7 +32,8 @@ export const IntegrationSetting = () => { } as { [x: string]: string }; }, [locale]); - const queries = new URLSearchParams(params); + const queries = qs.stringify(params); + const url = `https://github.com/apps/${GITHUB_APP_NAME.value}/installations/new?${queries.toString()}`; const { activeTeam } = useOrganizationTeams(); diff --git a/apps/web/package.json b/apps/web/package.json index 68aac4517..0007f70ae 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -73,6 +73,7 @@ "pako": "^2.1.0", "polished": "^4.2.2", "postcss": "^8.4.19", + "qs": "^6.11.2", "react": "^18.2.0", "react-beautiful-dnd": "^13.1.1", "react-colorful": "^5.6.1", diff --git a/apps/web/pages/api/auth/signin-workspace.ts b/apps/web/pages/api/auth/signin-workspace.ts index 66ae2ffe9..3abef61a6 100644 --- a/apps/web/pages/api/auth/signin-workspace.ts +++ b/apps/web/pages/api/auth/signin-workspace.ts @@ -106,6 +106,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) if (!team) { setNoTeamPopupShowCookie(true); } + setAuthCookies( { access_token: loginResponse.token, @@ -119,9 +120,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) noTeamPopup: true, userId }, - req, - res + { req, res } ); + return res.status(200).json({ team, loginResponse }); } // Accept Invite Flow End @@ -160,8 +161,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) noTeamPopup: true, userId }, - req, - res + { req, res } ); res.status(200).json({ loginResponse: data }); diff --git a/yarn.lock b/yarn.lock index e873febcc..b549a6c89 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19013,7 +19013,7 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" -qs@^6.11.0, qs@^6.4.0: +qs@^6.11.0, qs@^6.11.2, qs@^6.4.0: version "6.11.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==