refactor(web): remove typescript

This commit is contained in:
Ali BARIN
2024-02-27 15:23:23 +00:00
parent 636870a075
commit b3ae2d2748
337 changed files with 2067 additions and 4997 deletions

View File

@@ -1,18 +1,10 @@
import { useQuery } from '@apollo/client';
import { IApp } from 'types';
import { GET_APP } from 'graphql/queries/get-app';
type QueryResponse = {
getApp: IApp;
};
export default function useApp(key: string) {
const { data, loading } = useQuery<QueryResponse>(GET_APP, {
export default function useApp(key) {
const { data, loading } = useQuery(GET_APP, {
variables: { key },
});
const app = data?.getApp;
return {
app,
loading,

View File

@@ -1,27 +1,17 @@
import { useLazyQuery } from '@apollo/client';
import { AppAuthClient } from 'types';
import * as React from 'react';
import { GET_APP_AUTH_CLIENT } from 'graphql/queries/get-app-auth-client.ee';
type QueryResponse = {
getAppAuthClient: AppAuthClient;
};
export default function useAppAuthClient(id?: string) {
export default function useAppAuthClient(id) {
const [getAppAuthClient, { data, loading }] =
useLazyQuery<QueryResponse>(GET_APP_AUTH_CLIENT);
useLazyQuery(GET_APP_AUTH_CLIENT);
const appAuthClient = data?.getAppAuthClient;
React.useEffect(
function fetchUponId() {
if (!id) return;
getAppAuthClient({ variables: { id } });
},
[id]
[id],
);
return {
appAuthClient,
loading,

View File

@@ -1,39 +1,23 @@
import { useLazyQuery } from '@apollo/client';
import { AppAuthClient } from 'types';
import * as React from 'react';
import { GET_APP_AUTH_CLIENTS } from 'graphql/queries/get-app-auth-clients.ee';
type QueryResponse = {
getAppAuthClients: AppAuthClient[];
};
export default function useAppAuthClient({
appKey,
active,
}: {
appKey: string;
active?: boolean;
}) {
const [getAppAuthClients, { data, loading }] = useLazyQuery<QueryResponse>(
export default function useAppAuthClient({ appKey, active }) {
const [getAppAuthClients, { data, loading }] = useLazyQuery(
GET_APP_AUTH_CLIENTS,
{
context: { autoSnackbar: false },
}
},
);
const appAuthClients = data?.getAppAuthClients;
React.useEffect(
function fetchUponAppKey() {
if (!appKey) return;
getAppAuthClients({
variables: { appKey, ...(typeof active === 'boolean' && { active }) },
});
},
[appKey]
[appKey],
);
return {
appAuthClients,
loading,

View File

@@ -1,19 +1,11 @@
import { useQuery } from '@apollo/client';
import { AppConfig } from 'types';
import { GET_APP_CONFIG } from 'graphql/queries/get-app-config.ee';
type QueryResponse = {
getAppConfig: AppConfig;
};
export default function useAppConfig(key: string) {
const { data, loading } = useQuery<QueryResponse>(GET_APP_CONFIG, {
export default function useAppConfig(key) {
const { data, loading } = useQuery(GET_APP_CONFIG, {
variables: { key },
context: { autoSnackbar: false },
});
const appConfig = data?.getAppConfig;
return {
appConfig,
loading,

View File

@@ -0,0 +1,12 @@
import { useQuery } from '@apollo/client';
import { GET_APPS } from 'graphql/queries/get-apps';
export default function useApps(variables) {
const { data, loading } = useQuery(GET_APPS, {
variables,
});
const apps = data?.getApps;
return {
apps,
loading,
};
}

View File

@@ -1,26 +0,0 @@
import { useQuery } from '@apollo/client';
import { IApp } from 'types';
import { GET_APPS } from 'graphql/queries/get-apps';
type QueryResponse = {
getApps: IApp[];
};
type UseAppsVariables = {
name?: string;
onlyWithTriggers?: boolean;
onlyWithActions?: boolean;
};
export default function useApps(variables?: UseAppsVariables) {
const { data, loading } = useQuery<QueryResponse>(GET_APPS, {
variables,
});
const apps = data?.getApps;
return {
apps,
loading,
};
}

View File

@@ -1,57 +1,31 @@
import { IApp } from 'types';
import * as React from 'react';
import { processStep } from 'helpers/authenticationSteps';
import computeAuthStepVariables from 'helpers/computeAuthStepVariables';
import useApp from './useApp';
type UseAuthenticateAppParams = {
appKey: string;
appAuthClientId?: string;
useShared?: boolean;
connectionId?: string;
};
type AuthenticatePayload = {
fields?: Record<string, string>;
appAuthClientId?: string;
};
function getSteps(
auth: IApp['auth'],
hasConnection: boolean,
useShared: boolean
) {
function getSteps(auth, hasConnection, useShared) {
if (hasConnection) {
if (useShared) {
return auth?.sharedReconnectionSteps;
}
return auth?.reconnectionSteps;
}
if (useShared) {
return auth?.sharedAuthenticationSteps;
}
return auth?.authenticationSteps;
}
export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
export default function useAuthenticateApp(payload) {
const { appKey, appAuthClientId, connectionId, useShared = false } = payload;
const { app } = useApp(appKey);
const [authenticationInProgress, setAuthenticationInProgress] =
React.useState(false);
const steps = getSteps(app?.auth, !!connectionId, useShared);
const authenticate = React.useMemo(() => {
if (!steps?.length) return;
return async function authenticate(payload: AuthenticatePayload = {}) {
return async function authenticate(payload = {}) {
const { fields } = payload;
setAuthenticationInProgress(true);
const response: Record<string, any> = {
const response = {
key: appKey,
appAuthClientId: appAuthClientId || payload.appAuthClientId,
connection: {
@@ -59,35 +33,26 @@ export default function useAuthenticateApp(payload: UseAuthenticateAppParams) {
},
fields,
};
let stepIndex = 0;
while (stepIndex < steps?.length) {
const step = steps[stepIndex];
const variables = computeAuthStepVariables(step.arguments, response);
try {
const stepResponse = await processStep(step, variables);
response[step.name] = stepResponse;
} catch (err) {
console.log(err);
throw err;
setAuthenticationInProgress(false);
break;
throw err;
}
stepIndex++;
if (stepIndex === steps.length) {
return response;
}
setAuthenticationInProgress(false);
}
};
}, [steps, appKey, appAuthClientId, connectionId]);
return {
authenticate,
inProgress: authenticationInProgress,

View File

@@ -1,16 +1,7 @@
import * as React from 'react';
import { AuthenticationContext } from 'contexts/Authentication';
import type { AuthenticationContextParams } from 'contexts/Authentication';
type UseAuthenticationReturn = {
isAuthenticated: boolean;
token: AuthenticationContextParams['token'];
updateToken: AuthenticationContextParams['updateToken'];
};
export default function useAuthentication(): UseAuthenticationReturn {
export default function useAuthentication() {
const authenticationContext = React.useContext(AuthenticationContext);
return {
token: authenticationContext.token,
updateToken: authenticationContext.updateToken,

View File

@@ -1,15 +1,7 @@
import * as React from 'react';
import { AutomatischInfoContext } from 'contexts/AutomatischInfo';
type UseAutomatischInfoReturn = {
isCloud: boolean;
isMation: boolean;
loading: boolean;
};
export default function useAutomatischInfo(): UseAutomatischInfoReturn {
export default function useAutomatischInfo() {
const automatischInfoContext = React.useContext(AutomatischInfoContext);
return {
isCloud: automatischInfoContext.isCloud,
isMation: automatischInfoContext.isMation,

View File

@@ -2,22 +2,16 @@ import * as React from 'react';
import { useQuery } from '@apollo/client';
import { useLocation } from 'react-router-dom';
import { DateTime } from 'luxon';
import { TSubscription } from 'types';
import { GET_BILLING_AND_USAGE } from 'graphql/queries/get-billing-and-usage.ee';
function transform(
billingAndUsageData: NonNullable<UseBillingAndUsageDataReturn>
) {
function transform(billingAndUsageData) {
const nextBillDate = billingAndUsageData.subscription.nextBillDate;
const nextBillDateTitle = nextBillDate.title;
const nextBillDateTitleDateObject = DateTime.fromMillis(
Number(nextBillDateTitle)
Number(nextBillDateTitle),
);
const formattedNextBillDateTitle = nextBillDateTitleDateObject.isValid
? nextBillDateTitleDateObject.toFormat('LLL dd, yyyy')
: nextBillDateTitle;
return {
...billingAndUsageData,
subscription: {
@@ -29,42 +23,30 @@ function transform(
},
};
}
type UseBillingAndUsageDataReturn = {
subscription: TSubscription;
usage: {
task: number;
};
} | null;
export default function useBillingAndUsageData(): UseBillingAndUsageDataReturn {
export default function useBillingAndUsageData() {
const location = useLocation();
const state = location.state as { checkoutCompleted: boolean };
const state = location.state;
const { data, loading, startPolling, stopPolling } = useQuery(
GET_BILLING_AND_USAGE
GET_BILLING_AND_USAGE,
);
const checkoutCompleted = state?.checkoutCompleted;
const hasSubscription = !!data?.getBillingAndUsage?.subscription?.status;
React.useEffect(
function pollDataUntilSubscriptionIsCreated() {
if (checkoutCompleted && !hasSubscription) {
startPolling(1000);
}
},
[checkoutCompleted, hasSubscription, startPolling]
[checkoutCompleted, hasSubscription, startPolling],
);
React.useEffect(
function stopPollingWhenSubscriptionIsCreated() {
if (checkoutCompleted && hasSubscription) {
stopPolling();
}
},
[checkoutCompleted, hasSubscription, stopPolling]
[checkoutCompleted, hasSubscription, stopPolling],
);
if (loading) return null;
return transform(data.getBillingAndUsage);
}

View File

@@ -1,20 +1,11 @@
import { useNavigate } from 'react-router-dom';
import useAutomatischInfo from './useAutomatischInfo';
type UseCloudOptions = {
redirect?: boolean;
}
export default function useCloud(options?: UseCloudOptions): boolean {
export default function useCloud(options) {
const redirect = options?.redirect || false;
const { isCloud } = useAutomatischInfo();
const navigate = useNavigate();
if (isCloud === false && redirect) {
navigate('/');
}
return isCloud;
}

View File

@@ -0,0 +1,11 @@
import { useQuery } from '@apollo/client';
import { GET_CONFIG } from 'graphql/queries/get-config.ee';
export default function useConfig(keys) {
const { data, loading } = useQuery(GET_CONFIG, {
variables: { keys },
});
return {
config: data?.getConfig,
loading,
};
}

View File

@@ -1,19 +0,0 @@
import { useQuery } from '@apollo/client';
import { IJSONObject } from 'types';
import { GET_CONFIG } from 'graphql/queries/get-config.ee';
type QueryResponse = {
getConfig: IJSONObject;
};
export default function useConfig(keys?: string[]) {
const { data, loading } = useQuery<QueryResponse>(GET_CONFIG, {
variables: { keys },
});
return {
config: data?.getConfig,
loading,
};
}

View File

@@ -1,10 +1,6 @@
import { useQuery } from '@apollo/client';
import { IUser } from 'types';
import { GET_CURRENT_USER } from 'graphql/queries/get-current-user';
export default function useCurrentUser(): IUser {
export default function useCurrentUser() {
const { data } = useQuery(GET_CURRENT_USER);
return data?.getCurrentUser;
}

View File

@@ -1,8 +1,6 @@
import userAbility from 'helpers/userAbility';
import useCurrentUser from 'hooks/useCurrentUser';
export default function useCurrentUserAbility() {
const currentUser = useCurrentUser();
return userAbility(currentUser);
}

View File

@@ -2,40 +2,25 @@ import * as React from 'react';
import { useLazyQuery } from '@apollo/client';
import { useFormContext } from 'react-hook-form';
import set from 'lodash/set';
import type { UseFormReturn } from 'react-hook-form';
import isEqual from 'lodash/isEqual';
import type { IField, IFieldDropdownSource, IJSONObject } from 'types';
import { GET_DYNAMIC_DATA } from 'graphql/queries/get-dynamic-data';
const variableRegExp = /({.*?})/;
function computeArguments(
args: IFieldDropdownSource['arguments'],
getValues: UseFormReturn['getValues']
): IJSONObject {
function computeArguments(args, getValues) {
const initialValue = {};
return args.reduce((result, { name, value }) => {
const isVariable = variableRegExp.test(value);
if (isVariable) {
const sanitizedFieldPath = value.replace(/{|}/g, '');
const computedValue = getValues(sanitizedFieldPath);
if (computedValue === undefined)
throw new Error(`The ${sanitizedFieldPath} field is required.`);
set(result, name, computedValue);
return result;
}
set(result, name, value);
return result;
}, initialValue);
}
/**
* Fetch the dynamic data for the given step.
* This hook must be within a react-hook-form context.
@@ -43,13 +28,12 @@ function computeArguments(
* @param stepId - the id of the step
* @param schema - the field that needs the dynamic data
*/
function useDynamicData(stepId: string | undefined, schema: IField) {
function useDynamicData(stepId, schema) {
const lastComputedVariables = React.useRef({});
const [getDynamicData, { called, data, loading }] =
useLazyQuery(GET_DYNAMIC_DATA);
const { getValues } = useFormContext();
const formValues = getValues();
/**
* Return `null` when even a field is missing value.
*
@@ -60,27 +44,22 @@ function useDynamicData(stepId: string | undefined, schema: IField) {
if (schema.type === 'dropdown' && schema.source) {
try {
const variables = computeArguments(schema.source.arguments, getValues);
// if computed variables are the same, return the last computed variables.
if (isEqual(variables, lastComputedVariables.current)) {
return lastComputedVariables.current;
}
lastComputedVariables.current = variables;
return variables;
} catch (err) {
return null;
}
}
return null;
/**
* `formValues` is to trigger recomputation when form is updated.
* `getValues` is for convenience as it supports paths for fields like `getValues('foo.bar.baz')`.
*/
}, [schema, formValues, getValues]);
React.useEffect(() => {
if (
schema.type === 'dropdown' &&
@@ -96,12 +75,10 @@ function useDynamicData(stepId: string | undefined, schema: IField) {
});
}
}, [getDynamicData, stepId, schema, computedVariables]);
return {
called,
data: data?.getDynamicData,
loading,
};
}
export default useDynamicData;

View File

@@ -1,46 +1,27 @@
import * as React from 'react';
import { useLazyQuery } from '@apollo/client';
import type { UseFormReturn } from 'react-hook-form';
import { useFormContext } from 'react-hook-form';
import set from 'lodash/set';
import isEqual from 'lodash/isEqual';
import type {
IField,
IFieldDropdownAdditionalFields,
IJSONObject,
} from 'types';
import { GET_DYNAMIC_FIELDS } from 'graphql/queries/get-dynamic-fields';
const variableRegExp = /({.*?})/;
// TODO: extract this function to a separate file
function computeArguments(
args: IFieldDropdownAdditionalFields['arguments'],
getValues: UseFormReturn['getValues']
): IJSONObject {
function computeArguments(args, getValues) {
const initialValue = {};
return args.reduce((result, { name, value }) => {
const isVariable = variableRegExp.test(value);
if (isVariable) {
const sanitizedFieldPath = value.replace(/{|}/g, '');
const computedValue = getValues(sanitizedFieldPath);
if (computedValue === undefined || computedValue === '')
throw new Error(`The ${sanitizedFieldPath} field is required.`);
set(result, name, computedValue);
return result;
}
set(result, name, value);
return result;
}, initialValue);
}
/**
* Fetch the dynamic fields for the given step.
* This hook must be within a react-hook-form context.
@@ -48,13 +29,12 @@ function computeArguments(
* @param stepId - the id of the step
* @param schema - the field schema that needs the dynamic fields
*/
function useDynamicFields(stepId: string | undefined, schema: IField) {
function useDynamicFields(stepId, schema) {
const lastComputedVariables = React.useRef({});
const [getDynamicFields, { called, data, loading }] =
useLazyQuery(GET_DYNAMIC_FIELDS);
const { getValues } = useFormContext();
const formValues = getValues();
/**
* Return `null` when even a field is missing value.
*
@@ -66,29 +46,24 @@ function useDynamicFields(stepId: string | undefined, schema: IField) {
try {
const variables = computeArguments(
schema.additionalFields.arguments,
getValues
getValues,
);
// if computed variables are the same, return the last computed variables.
if (isEqual(variables, lastComputedVariables.current)) {
return lastComputedVariables.current;
}
lastComputedVariables.current = variables;
return variables;
} catch (err) {
return null;
}
}
return null;
/**
* `formValues` is to trigger recomputation when form is updated.
* `getValues` is for convenience as it supports paths for fields like `getValues('foo.bar.baz')`.
*/
}, [schema, formValues, getValues]);
React.useEffect(() => {
if (
schema.type === 'dropdown' &&
@@ -104,12 +79,10 @@ function useDynamicFields(stepId: string | undefined, schema: IField) {
});
}
}, [getDynamicFields, stepId, schema, computedVariables]);
return {
called,
data: data?.getDynamicFields as IField[] | undefined,
data: data?.getDynamicFields,
loading,
};
}
export default useDynamicFields;

View File

@@ -0,0 +1,18 @@
import { useSnackbar } from 'notistack';
export default function useEnqueueSnackbar() {
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
return function wrappedEnqueueSnackbar(message, options) {
const key = enqueueSnackbar(message, {
...(options || {}),
SnackbarProps: {
onClick: () => closeSnackbar(key),
...{
'data-test': 'snackbar',
'data-snackbar-variant': `${options.variant}` || 'default',
},
...(options.SnackbarProps || {}),
},
});
return key;
};
}

View File

@@ -1,34 +0,0 @@
import type {
OptionsWithExtraProps,
SnackbarMessage,
VariantType,
SnackbarKey
} from 'notistack';
import { useSnackbar } from 'notistack';
type ExtendedOptionsWithExtraProps<V extends VariantType> = OptionsWithExtraProps<V> & {
SnackbarProps?: OptionsWithExtraProps<V> & { 'data-test'?: string; }
}
export default function useEnqueueSnackbar() {
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
return function wrappedEnqueueSnackbar<V extends VariantType>(message: SnackbarMessage, options: ExtendedOptionsWithExtraProps<V>) {
const key: SnackbarKey = enqueueSnackbar(
message,
{
...(options || {}) as Record<string, unknown>,
SnackbarProps: {
onClick: () => closeSnackbar(key),
...({
'data-test': 'snackbar', // keep above options.snackbarProps
'data-snackbar-variant': `${options.variant}` || 'default',
}) as Record<string, string>,
...(options.SnackbarProps || {}) as Record<string, unknown>,
}
}
);
return key;
};
}

View File

@@ -0,0 +1,5 @@
import { useIntl } from 'react-intl';
export default function useFormatMessage() {
const { formatMessage } = useIntl();
return (id, values = {}) => formatMessage({ id }, values);
}

View File

@@ -1,14 +0,0 @@
import { useIntl } from 'react-intl';
type Values = {
[key: string]: any;
};
export default function useFormatMessage(): (
id: string,
values?: Values
) => string {
const { formatMessage } = useIntl();
return (id: string, values: Values = {}) => formatMessage({ id }, values);
}

View File

@@ -1,16 +1,7 @@
import { useQuery } from '@apollo/client';
import { TInvoice } from 'types';
import { GET_INVOICES } from 'graphql/queries/get-invoices.ee';
type UseInvoicesReturn = {
invoices: TInvoice[];
loading: boolean;
};
export default function useInvoices(): UseInvoicesReturn {
export default function useInvoices() {
const { data, loading } = useQuery(GET_INVOICES);
return {
invoices: data?.getInvoices || [],
loading: loading,

View File

@@ -1,18 +1,8 @@
import { useQuery } from '@apollo/client';
import type { Notification } from 'types';
import { GET_NOTIFICATIONS } from 'graphql/queries/get-notifications';
type UseNotificationsReturn = {
notifications: Notification[];
loading: boolean;
};
export default function useNotifications(): UseNotificationsReturn {
export default function useNotifications() {
const { data, loading } = useQuery(GET_NOTIFICATIONS);
const notifications = data?.getNotifications || [];
return {
loading,
notifications,

View File

@@ -1,13 +1,7 @@
import * as React from 'react';
import { PaddleContext } from 'contexts/Paddle.ee';
type UsePaddleReturn = {
loaded: boolean;
};
export default function usePaddle(): UsePaddleReturn {
export default function usePaddle() {
const paddleContext = React.useContext(PaddleContext);
return {
loaded: paddleContext.loaded,
};

View File

@@ -1,19 +1,10 @@
import { useQuery } from '@apollo/client';
import { GET_PADDLE_INFO } from 'graphql/queries/get-paddle-info.ee';
type UsePaddleInfoReturn = {
sandbox: boolean;
vendorId: string;
loading: boolean;
};
export default function usePaddleInfo(): UsePaddleInfoReturn {
export default function usePaddleInfo() {
const { data, loading } = useQuery(GET_PADDLE_INFO);
return {
sandbox: data?.getPaddleInfo?.sandbox,
vendorId: data?.getPaddleInfo?.vendorId,
loading
loading,
};
}

View File

@@ -1,16 +1,7 @@
import { useQuery } from '@apollo/client';
import { TPaymentPlan } from 'types';
import { GET_PAYMENT_PLANS } from 'graphql/queries/get-payment-plans.ee';
type UsePaymentPlansReturn = {
plans: TPaymentPlan[];
loading: boolean;
};
export default function usePaymentPlans(): UsePaymentPlansReturn {
export default function usePaymentPlans() {
const { data, loading } = useQuery(GET_PAYMENT_PLANS);
return {
plans: data?.getPaymentPlans || [],
loading,

View File

@@ -1,15 +1,6 @@
import { useQuery } from '@apollo/client';
import { IPermissionCatalog } from 'types';
import { GET_PERMISSION_CATALOG } from 'graphql/queries/get-permission-catalog.ee';
type UsePermissionCatalogReturn = {
permissionCatalog: IPermissionCatalog;
loading: boolean;
};
export default function usePermissionCatalog(): UsePermissionCatalogReturn {
export default function usePermissionCatalog() {
const { data, loading } = useQuery(GET_PERMISSION_CATALOG);
return { permissionCatalog: data?.getPermissionCatalog, loading };
}

View File

@@ -1,16 +1,8 @@
import * as React from 'react';
import { useLazyQuery } from '@apollo/client';
import { IRole } from 'types';
import { GET_ROLE } from 'graphql/queries/get-role.ee';
type QueryResponse = {
getRole: IRole;
};
export default function useRole(roleId?: string) {
const [getRole, { data, loading }] = useLazyQuery<QueryResponse>(GET_ROLE);
export default function useRole(roleId) {
const [getRole, { data, loading }] = useLazyQuery(GET_ROLE);
React.useEffect(() => {
if (roleId) {
getRole({
@@ -20,7 +12,6 @@ export default function useRole(roleId?: string) {
});
}
}, [roleId]);
return {
role: data?.getRole,
loading,

View File

@@ -1,17 +1,9 @@
import { useQuery } from '@apollo/client';
import { IRole } from 'types';
import { GET_ROLES } from 'graphql/queries/get-roles.ee';
type QueryResponse = {
getRoles: IRole[];
};
export default function useRoles() {
const { data, loading } = useQuery<QueryResponse>(GET_ROLES, {
const { data, loading } = useQuery(GET_ROLES, {
context: { autoSnackbar: false },
});
return {
roles: data?.getRoles || [],
loading,

View File

@@ -0,0 +1,12 @@
import { useQuery } from '@apollo/client';
import { GET_SAML_AUTH_PROVIDER } from 'graphql/queries/get-saml-auth-provider';
export default function useSamlAuthProvider() {
const { data, loading, refetch } = useQuery(GET_SAML_AUTH_PROVIDER, {
context: { autoSnackbar: false },
});
return {
provider: data?.getSamlAuthProvider,
loading,
refetch,
};
}

View File

@@ -1,22 +0,0 @@
import { QueryResult, useQuery } from '@apollo/client';
import { TSamlAuthProvider } from 'types';
import { GET_SAML_AUTH_PROVIDER } from 'graphql/queries/get-saml-auth-provider';
type UseSamlAuthProviderReturn = {
provider?: TSamlAuthProvider;
loading: boolean;
refetch: QueryResult<TSamlAuthProvider | undefined>['refetch'];
};
export default function useSamlAuthProvider(): UseSamlAuthProviderReturn {
const { data, loading, refetch } = useQuery(GET_SAML_AUTH_PROVIDER, {
context: { autoSnackbar: false },
});
return {
provider: data?.getSamlAuthProvider,
loading,
refetch,
};
}

View File

@@ -1,17 +1,10 @@
import * as React from 'react';
import { useLazyQuery } from '@apollo/client';
import { TSamlAuthProviderRole } from 'types';
import { GET_SAML_AUTH_PROVIDER_ROLE_MAPPINGS } from 'graphql/queries/get-saml-auth-provider-role-mappings';
type QueryResponse = {
getSamlAuthProviderRoleMappings: TSamlAuthProviderRole[];
};
export default function useSamlAuthProviderRoleMappings(providerId?: string) {
const [getSamlAuthProviderRoleMappings, { data, loading }] =
useLazyQuery<QueryResponse>(GET_SAML_AUTH_PROVIDER_ROLE_MAPPINGS);
export default function useSamlAuthProviderRoleMappings(providerId) {
const [getSamlAuthProviderRoleMappings, { data, loading }] = useLazyQuery(
GET_SAML_AUTH_PROVIDER_ROLE_MAPPINGS,
);
React.useEffect(() => {
if (providerId) {
getSamlAuthProviderRoleMappings({
@@ -21,7 +14,6 @@ export default function useSamlAuthProviderRoleMappings(providerId?: string) {
});
}
}, [providerId]);
return {
roleMappings: data?.getSamlAuthProviderRoleMappings || [],
loading,

View File

@@ -1,16 +1,7 @@
import { useQuery } from '@apollo/client';
import { TSamlAuthProvider } from 'types';
import { LIST_SAML_AUTH_PROVIDERS } from 'graphql/queries/list-saml-auth-providers.ee';
type UseSamlAuthProvidersReturn = {
providers: TSamlAuthProvider[];
loading: boolean;
};
export default function useSamlAuthProviders(): UseSamlAuthProvidersReturn {
export default function useSamlAuthProviders() {
const { data, loading } = useQuery(LIST_SAML_AUTH_PROVIDERS);
return {
providers: data?.listSamlAuthProviders || [],
loading,

View File

@@ -0,0 +1,21 @@
import { useQuery } from '@apollo/client';
import { DateTime } from 'luxon';
import { GET_SUBSCRIPTION_STATUS } from 'graphql/queries/get-subscription-status.ee';
import useFormatMessage from './useFormatMessage';
export default function useSubscriptionStatus() {
const formatMessage = useFormatMessage();
const { data, loading } = useQuery(GET_SUBSCRIPTION_STATUS);
const cancellationEffectiveDate =
data?.getSubscriptionStatus?.cancellationEffectiveDate;
const hasCancelled = !!cancellationEffectiveDate;
if (loading || !hasCancelled) return null;
const cancellationEffectiveDateObject = DateTime.fromMillis(
Number(cancellationEffectiveDate),
).startOf('day');
return {
message: formatMessage('subscriptionCancelledAlert.text', {
date: cancellationEffectiveDateObject.toFormat('DDD'),
}),
cancellationEffectiveDate: cancellationEffectiveDateObject,
};
}

View File

@@ -1,31 +0,0 @@
import { useQuery } from '@apollo/client';
import { DateTime } from 'luxon';
import { GET_SUBSCRIPTION_STATUS } from 'graphql/queries/get-subscription-status.ee';
import useFormatMessage from './useFormatMessage';
type UseSubscriptionStatusReturn = {
cancellationEffectiveDate: DateTime;
message: string;
} | null;
export default function useSubscriptionStatus(): UseSubscriptionStatusReturn {
const formatMessage = useFormatMessage();
const { data, loading, } = useQuery(GET_SUBSCRIPTION_STATUS);
const cancellationEffectiveDate = data?.getSubscriptionStatus?.cancellationEffectiveDate as string;
const hasCancelled = !!cancellationEffectiveDate;
if (loading || !hasCancelled) return null;
const cancellationEffectiveDateObject = DateTime.fromMillis(Number(cancellationEffectiveDate)).startOf('day');
return {
message: formatMessage(
'subscriptionCancelledAlert.text',
{
date: cancellationEffectiveDateObject.toFormat('DDD')
}
),
cancellationEffectiveDate: cancellationEffectiveDateObject,
};
}

View File

@@ -2,87 +2,73 @@ import * as React from 'react';
import { useQuery } from '@apollo/client';
import { useLocation } from 'react-router-dom';
import { DateTime } from 'luxon';
import { GET_TRIAL_STATUS } from 'graphql/queries/get-trial-status.ee';
import useFormatMessage from './useFormatMessage';
type UseTrialStatusReturn = {
expireAt: DateTime;
message: string;
over: boolean;
status: 'error' | 'warning';
} | null;
function getDiffInDays(date: DateTime) {
function getDiffInDays(date) {
const today = DateTime.now().startOf('day');
const diffInDays = date.diff(today, 'days').days;
const roundedDiffInDays = Math.round(diffInDays);
return roundedDiffInDays;
}
function getFeedbackPayload(date: DateTime) {
function getFeedbackPayload(date) {
const diffInDays = getDiffInDays(date);
if (diffInDays <= -1) {
return {
translationEntryId: 'trialBadge.over',
status: 'error' as const,
status: 'error',
over: true,
};
} else if (diffInDays <= 0) {
return {
translationEntryId: 'trialBadge.endsToday',
status: 'warning' as const,
status: 'warning',
over: false,
}
};
} else {
return {
translationEntryId: 'trialBadge.xDaysLeft',
translationEntryValues: {
remainingDays: diffInDays
remainingDays: diffInDays,
},
status: 'warning' as const,
status: 'warning',
over: false,
}
};
}
}
export default function useTrialStatus(): UseTrialStatusReturn {
export default function useTrialStatus() {
const formatMessage = useFormatMessage();
const location = useLocation();
const state = location.state as { checkoutCompleted: boolean };
const state = location.state;
const checkoutCompleted = state?.checkoutCompleted;
const { data, loading, startPolling, stopPolling } = useQuery(GET_TRIAL_STATUS);
const { data, loading, startPolling, stopPolling } =
useQuery(GET_TRIAL_STATUS);
const hasTrial = !!data?.getTrialStatus?.expireAt;
React.useEffect(function pollDataUntilTrialEnds() {
if (checkoutCompleted && hasTrial) {
startPolling(1000);
}
}, [checkoutCompleted, hasTrial, startPolling]);
React.useEffect(function stopPollingWhenTrialEnds() {
if (checkoutCompleted && !hasTrial) {
stopPolling();
}
}, [checkoutCompleted, hasTrial, stopPolling]);
React.useEffect(
function pollDataUntilTrialEnds() {
if (checkoutCompleted && hasTrial) {
startPolling(1000);
}
},
[checkoutCompleted, hasTrial, startPolling],
);
React.useEffect(
function stopPollingWhenTrialEnds() {
if (checkoutCompleted && !hasTrial) {
stopPolling();
}
},
[checkoutCompleted, hasTrial, stopPolling],
);
if (loading || !data.getTrialStatus) return null;
const expireAt = DateTime.fromMillis(Number(data.getTrialStatus.expireAt)).startOf('day');
const {
translationEntryId,
translationEntryValues,
status,
over,
} = getFeedbackPayload(expireAt);
const expireAt = DateTime.fromMillis(
Number(data.getTrialStatus.expireAt),
).startOf('day');
const { translationEntryId, translationEntryValues, status, over } =
getFeedbackPayload(expireAt);
return {
message: formatMessage(translationEntryId, translationEntryValues),
expireAt,
over,
status
status,
};
}

View File

@@ -1,16 +1,8 @@
import * as React from 'react';
import { useLazyQuery } from '@apollo/client';
import { IUser } from 'types';
import { GET_USER } from 'graphql/queries/get-user';
type QueryResponse = {
getUser: IUser;
};
export default function useUser(userId?: string) {
const [getUser, { data, loading }] = useLazyQuery<QueryResponse>(GET_USER);
export default function useUser(userId) {
const [getUser, { data, loading }] = useLazyQuery(GET_USER);
React.useEffect(() => {
if (userId) {
getUser({
@@ -20,7 +12,6 @@ export default function useUser(userId?: string) {
});
}
}, [userId]);
return {
user: data?.getUser,
loading,

View File

@@ -1,36 +1,16 @@
import { useQuery } from '@apollo/client';
import { IUser } from 'types';
import { GET_USERS } from 'graphql/queries/get-users';
type Edge = {
node: IUser;
};
type QueryResponse = {
getUsers: {
pageInfo: {
currentPage: number;
totalPages: number;
};
totalCount: number;
edges: Edge[];
};
};
const getLimitAndOffset = (page: number, rowsPerPage: number) => ({
const getLimitAndOffset = (page, rowsPerPage) => ({
limit: rowsPerPage,
offset: page * rowsPerPage,
});
export default function useUsers(page: number, rowsPerPage: number) {
const { data, loading } = useQuery<QueryResponse>(GET_USERS, {
export default function useUsers(page, rowsPerPage) {
const { data, loading } = useQuery(GET_USERS, {
variables: getLimitAndOffset(page, rowsPerPage),
});
const users = data?.getUsers.edges.map(({ node }) => node) || [];
const pageInfo = data?.getUsers.pageInfo;
const totalCount = data?.getUsers.totalCount;
return {
users,
pageInfo,

View File

@@ -1,32 +1,21 @@
import { useQuery } from '@apollo/client';
import { compare } from 'compare-versions';
import { HEALTHCHECK } from 'graphql/queries/healthcheck';
import useNotifications from 'hooks/useNotifications';
type TVersionInfo = {
version: string;
newVersionCount: number;
};
export default function useVersion(): TVersionInfo {
export default function useVersion() {
const { notifications } = useNotifications();
const { data } = useQuery(HEALTHCHECK, { fetchPolicy: 'cache-and-network' });
const version = data?.healthcheck.version;
const newVersionCount = notifications.reduce((count, notification) => {
if (!version) return 0;
// an unexpectedly invalid version would throw and thus, try-catch.
try {
const isNewer = compare(version, notification.name, '<');
return isNewer ? count + 1 : count;
} catch {
return count;
}
}, 0);
return {
version,
newVersionCount,