diff --git a/packages/backend/src/graphql/queries/get-trial-status.ee.js b/packages/backend/src/graphql/queries/get-trial-status.ee.js deleted file mode 100644 index 1980ccb7..00000000 --- a/packages/backend/src/graphql/queries/get-trial-status.ee.js +++ /dev/null @@ -1,17 +0,0 @@ -import appConfig from '../../config/app.js'; - -const getTrialStatus = async (_parent, _params, context) => { - if (!appConfig.isCloud) return; - - const inTrial = await context.currentUser.inTrial(); - const hasActiveSubscription = - await context.currentUser.hasActiveSubscription(); - - if (!inTrial && hasActiveSubscription) return; - - return { - expireAt: context.currentUser.trialExpiryDate, - }; -}; - -export default getTrialStatus; diff --git a/packages/backend/src/graphql/queries/get-trial-status.ee.test.js b/packages/backend/src/graphql/queries/get-trial-status.ee.test.js deleted file mode 100644 index 3189cb69..00000000 --- a/packages/backend/src/graphql/queries/get-trial-status.ee.test.js +++ /dev/null @@ -1,100 +0,0 @@ -import { vi, describe, it, expect, beforeEach } from 'vitest'; -import request from 'supertest'; -import app from '../../app'; -import User from '../../models/user'; -import { createUser } from '../../../test/factories/user'; -import createAuthTokenByUserId from '../../helpers/create-auth-token-by-user-id'; -import { DateTime } from 'luxon'; -import appConfig from '../../config/app'; - -describe('graphQL getTrialStatus query', () => { - const query = ` - query GetTrialStatus { - getTrialStatus { - expireAt - } - } - `; - - let user, userToken; - - beforeEach(async () => { - const trialExpiryDate = DateTime.now().plus({ days: 30 }).toISODate(); - - user = await createUser({ trialExpiryDate }); - userToken = createAuthTokenByUserId(user.id); - }); - - describe('and with cloud flag disabled', () => { - beforeEach(async () => { - vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(false); - }); - - it('should return null', async () => { - const response = await request(app) - .post('/graphql') - .set('Authorization', userToken) - .send({ query }) - .expect(200); - - const expectedResponsePayload = { - data: { getTrialStatus: null }, - }; - - expect(response.body).toEqual(expectedResponsePayload); - }); - }); - - describe('and with cloud flag enabled', () => { - beforeEach(async () => { - vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(true); - }); - - describe('and not in trial and has active subscription', () => { - beforeEach(async () => { - vi.spyOn(User.prototype, 'inTrial').mockResolvedValue(false); - vi.spyOn(User.prototype, 'hasActiveSubscription').mockResolvedValue( - true - ); - }); - - it('should return null', async () => { - const response = await request(app) - .post('/graphql') - .set('Authorization', userToken) - .send({ query }) - .expect(200); - - const expectedResponsePayload = { - data: { getTrialStatus: null }, - }; - - expect(response.body).toEqual(expectedResponsePayload); - }); - }); - - describe('and in trial period', () => { - beforeEach(async () => { - vi.spyOn(User.prototype, 'inTrial').mockResolvedValue(true); - }); - - it('should return null', async () => { - const response = await request(app) - .post('/graphql') - .set('Authorization', userToken) - .send({ query }) - .expect(200); - - const expectedResponsePayload = { - data: { - getTrialStatus: { - expireAt: new Date(user.trialExpiryDate).getTime().toString(), - }, - }, - }; - - expect(response.body).toEqual(expectedResponsePayload); - }); - }); - }); -}); diff --git a/packages/backend/src/graphql/query-resolvers.js b/packages/backend/src/graphql/query-resolvers.js index 48d4ac97..ff26502d 100644 --- a/packages/backend/src/graphql/query-resolvers.js +++ b/packages/backend/src/graphql/query-resolvers.js @@ -12,7 +12,6 @@ import getNotifications from './queries/get-notifications.js'; import getPermissionCatalog from './queries/get-permission-catalog.ee.js'; import getSamlAuthProviderRoleMappings from './queries/get-saml-auth-provider-role-mappings.ee.js'; import getStepWithTestExecutions from './queries/get-step-with-test-executions.js'; -import getTrialStatus from './queries/get-trial-status.ee.js'; import getUsers from './queries/get-users.js'; import listSamlAuthProviders from './queries/list-saml-auth-providers.ee.js'; import testConnection from './queries/test-connection.js'; @@ -32,7 +31,6 @@ const queryResolvers = { getPermissionCatalog, getSamlAuthProviderRoleMappings, getStepWithTestExecutions, - getTrialStatus, getUsers, listSamlAuthProviders, testConnection, diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index eec816d3..eb584aca 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -28,7 +28,6 @@ type Query { getPermissionCatalog: PermissionCatalog getNotifications: [Notification] getSamlAuthProviderRoleMappings(id: String!): [SamlAuthProvidersRoleMapping] - getTrialStatus: GetTrialStatus getUsers(limit: Int!, offset: Int!): UserConnection listSamlAuthProviders: [ListSamlAuthProvider] } @@ -601,10 +600,6 @@ type License { verified: Boolean } -type GetTrialStatus { - expireAt: String -} - type GetBillingAndUsage { subscription: Subscription usage: Usage diff --git a/packages/web/src/components/TrialOverAlert/index.ee.jsx b/packages/web/src/components/TrialOverAlert/index.ee.jsx index 8095a2ae..cbb53f1c 100644 --- a/packages/web/src/components/TrialOverAlert/index.ee.jsx +++ b/packages/web/src/components/TrialOverAlert/index.ee.jsx @@ -1,14 +1,18 @@ import * as React from 'react'; import Alert from '@mui/material/Alert'; import Typography from '@mui/material/Typography'; + import * as URLS from 'config/urls'; import { generateInternalLink } from 'helpers/translationValues'; -import useTrialStatus from 'hooks/useTrialStatus.ee'; +import useUserTrial from 'hooks/useUserTrial.ee'; import useFormatMessage from 'hooks/useFormatMessage'; + export default function TrialOverAlert() { const formatMessage = useFormatMessage(); - const trialStatus = useTrialStatus(); + const trialStatus = useUserTrial(); + if (!trialStatus || !trialStatus.over) return ; + return ( ; + const { message, status } = data; + return ( { + const { data } = await api.get('/v1/users/me/trial', { + signal, + }); + + return data; + }, + refetchInterval: isPolling ? 1000 : false, + }); + const userTrial = data?.data; + + const hasTrial = userTrial?.inTrial; + React.useEffect( function pollDataUntilTrialEnds() { if (checkoutCompleted && hasTrial) { - startPolling(1000); + setIsPolling(true); } }, - [checkoutCompleted, hasTrial, startPolling], + [checkoutCompleted, hasTrial, setIsPolling], ); + React.useEffect( function stopPollingWhenTrialEnds() { if (checkoutCompleted && !hasTrial) { - stopPolling(); + setIsPolling(false); } }, - [checkoutCompleted, hasTrial, stopPolling], + [checkoutCompleted, hasTrial, setIsPolling], ); - if (loading || !data?.getTrialStatus) return null; - const expireAt = DateTime.fromMillis( - Number(data.getTrialStatus.expireAt), - ).startOf('day'); + + if (isUserTrialLoading || !userTrial) return null; + + const expireAt = DateTime.fromISO(userTrial?.expireAt).startOf('day'); + const { translationEntryId, translationEntryValues, status, over } = getFeedbackPayload(expireAt); + return { message: formatMessage(translationEntryId, translationEntryValues), expireAt,