diff --git a/backend/erxes-api-shared/src/utils/apollo/utils.ts b/backend/erxes-api-shared/src/utils/apollo/utils.ts index eacf427f53..24ab9432c0 100644 --- a/backend/erxes-api-shared/src/utils/apollo/utils.ts +++ b/backend/erxes-api-shared/src/utils/apollo/utils.ts @@ -1,9 +1,9 @@ -import { IMainContext } from '../../core-types'; -import { extractUserFromHeader } from '../headers'; -import { getSubdomain } from '../utils'; import { ExpressContextFunctionArgument } from '@apollo/server/dist/esm/express4'; import { Request as ApiRequest, Response as ApiResponse } from 'express'; import { nanoid } from 'nanoid'; +import { IMainContext } from '../../core-types'; +import { extractUserFromHeader, getTimezone } from '../headers'; +import { getSubdomain } from '../utils'; export const generateApolloContext = ( @@ -22,6 +22,7 @@ export const generateApolloContext = return {}; } const user: any = extractUserFromHeader(req.headers); + const timezone: string = getTimezone(req.headers); const subdomain = getSubdomain(req); @@ -39,6 +40,7 @@ export const generateApolloContext = requestInfo: { secure: req.secure, cookies: req.cookies, + timezone, }, }; diff --git a/backend/erxes-api-shared/src/utils/headers/index.ts b/backend/erxes-api-shared/src/utils/headers/index.ts index 4df33a412c..849a32a36a 100644 --- a/backend/erxes-api-shared/src/utils/headers/index.ts +++ b/backend/erxes-api-shared/src/utils/headers/index.ts @@ -1,4 +1,5 @@ -export * from './sanitize'; -export * from './user'; export * from './get-hostname'; +export * from './sanitize'; export * from './subdomain'; +export * from './timezone'; +export * from './user'; diff --git a/backend/erxes-api-shared/src/utils/headers/timezone.ts b/backend/erxes-api-shared/src/utils/headers/timezone.ts new file mode 100644 index 0000000000..8adff327a7 --- /dev/null +++ b/backend/erxes-api-shared/src/utils/headers/timezone.ts @@ -0,0 +1,11 @@ +import { IncomingHttpHeaders } from 'http'; + +export const getTimezone = (req: IncomingHttpHeaders): string => { + const timezone = req['x-timezone'] || req['timezone'] || 'UTC'; + + if (Array.isArray(timezone)) { + return timezone[0]; + } + + return timezone; +}; diff --git a/backend/plugins/operation_api/src/modules/cycle/graphql/resolvers/queries/cycle.ts b/backend/plugins/operation_api/src/modules/cycle/graphql/resolvers/queries/cycle.ts index d081feea19..7c4378bd1c 100644 --- a/backend/plugins/operation_api/src/modules/cycle/graphql/resolvers/queries/cycle.ts +++ b/backend/plugins/operation_api/src/modules/cycle/graphql/resolvers/queries/cycle.ts @@ -1,7 +1,7 @@ -import { cursorPaginate } from 'erxes-api-shared/utils'; -import { IContext } from '~/connectionResolvers'; import { ICycleDocument } from '@/cycle/types'; import { STATUS_TYPES } from '@/status/constants/types'; +import { cursorPaginate } from 'erxes-api-shared/utils'; +import { IContext } from '~/connectionResolvers'; import { getCycleProgressByMember, @@ -80,9 +80,9 @@ export const cycleQueries = { getCycleProgressChart: async ( _parent: undefined, { _id, assigneeId }, - { models }: IContext, + { models, requestInfo: { timezone } }: IContext, ) => { - return getCycleProgressChart(_id, assigneeId, models); + return getCycleProgressChart(_id, assigneeId, models, timezone); }, getCycleProgressByMember: async ( diff --git a/backend/plugins/operation_api/src/modules/cycle/utils.ts b/backend/plugins/operation_api/src/modules/cycle/utils.ts index f68a15c996..9b82684bf3 100644 --- a/backend/plugins/operation_api/src/modules/cycle/utils.ts +++ b/backend/plugins/operation_api/src/modules/cycle/utils.ts @@ -1,6 +1,7 @@ import { fillMissingDays } from '@/project/utils/charUtils'; import { STATUS_TYPES } from '@/status/constants/types'; -import { differenceInCalendarDays, startOfDay } from 'date-fns'; +import { differenceInCalendarDays } from 'date-fns'; +import { toZonedTime } from 'date-fns-tz'; import { Types } from 'mongoose'; import { IModels } from '~/connectionResolvers'; @@ -115,6 +116,7 @@ export const getCycleProgressChart = async ( cycleId: string, assigneeId: string | undefined, models: IModels, + timezone: string, ) => { const filter: { cycleId: Types.ObjectId; assigneeId?: string } = { cycleId: new Types.ObjectId(cycleId), @@ -177,10 +179,10 @@ export const getCycleProgressChart = async ( { $addFields: { dayDate: { - $dateFromParts: { - year: { $year: '$statusChangedDate' }, - month: { $month: '$statusChangedDate' }, - day: { $dayOfMonth: '$statusChangedDate' }, + $dateToString: { + format: '%Y-%m-%d', + date: '$statusChangedDate', + timezone, }, }, isStarted: { $eq: ['$statusType', STATUS_TYPES.STARTED] }, @@ -210,7 +212,7 @@ export const getCycleProgressChart = async ( { $project: { _id: 0, - date: { $dateToString: { format: '%Y-%m-%d', date: '$_id' } }, + date: '$_id', started: 1, completed: 1, }, @@ -238,16 +240,12 @@ export const getCycleProgressChart = async ( chartData: [], }; - const start = startOfDay(new Date(cycle.startDate)); - const end = startOfDay(new Date(cycle.endDate)); + const start = toZonedTime(cycle.startDate, timezone); + const end = toZonedTime(cycle.endDate, timezone); const days = differenceInCalendarDays(end, start) + 1; - chartData.chartData = fillMissingDays( - chartDataAggregation, - cycle.startDate, - days, - ); + chartData.chartData = fillMissingDays(chartDataAggregation, start, days); return chartData; }; diff --git a/frontend/core-ui/src/providers/apollo-provider/apolloClient.ts b/frontend/core-ui/src/providers/apollo-provider/apolloClient.ts index f4410484ad..8e51df3716 100644 --- a/frontend/core-ui/src/providers/apollo-provider/apolloClient.ts +++ b/frontend/core-ui/src/providers/apollo-provider/apolloClient.ts @@ -35,6 +35,7 @@ const authLink = setContext((_, { headers }) => { headers: { ...headers, sessioncode: sessionStorage.getItem('sessioncode') || '', + 'x-timezone': Intl.DateTimeFormat().resolvedOptions().timeZone, }, }; }); diff --git a/frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx b/frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx index df0e16de32..c00d45982b 100644 --- a/frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx +++ b/frontend/plugins/operation_ui/src/modules/cycle/components/detail/CycleProgressChart.tsx @@ -107,6 +107,7 @@ export const CycleProgressChart = ({ dot={false} connectNulls={true} strokeLinecap="round" + activeDot={{ fill: STATUS_COLORS.started, r: 4 }} />