{t('PASSWORD_VALIDATOR_PASSWORD_REQUIREMENTS')}
- values.password.length >= 6}>
+ password.length >= 6}>
{t('PASSWORD_VALIDATOR_MINIMUM_OF_6_CHARACTERS')}
- values.password.match(/[A-Z]/) !== null}
- >
+ password.match(/[A-Z]/) !== null}>
{t('PASSWORD_VALIDATOR_CONTAIN_AN_UPPERCASE_LETTER')}
- values.password.match(/[a-z]/) !== null}
- >
+ password.match(/[a-z]/) !== null}>
{t('PASSWORD_VALIDATOR_CONTAIN_A_LOWERCASE_LETTER')}
- values.password.match(/[0-9]/) !== null}
- >
+ password.match(/[0-9]/) !== null}>
{t('PASSWORD_VALIDATOR_CONTAIN_A_NUMBER')}
diff --git a/src/common/components/inviteUsers/userItem.tsx b/src/common/components/inviteUsers/userItem.tsx
index 254c0a77f..cd0232849 100644
--- a/src/common/components/inviteUsers/userItem.tsx
+++ b/src/common/components/inviteUsers/userItem.tsx
@@ -9,9 +9,11 @@ import {
} from '@appquality/unguess-design-system';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { useAppSelector } from 'src/app/hooks';
import { appTheme } from 'src/app/theme';
-import { GetWorkspacesByWidUsersApiResponse } from 'src/features/api';
+import {
+ GetWorkspacesByWidUsersApiResponse,
+ useGetUsersMeQuery,
+} from 'src/features/api';
import styled from 'styled-components';
import { getInitials } from '../navigation/header/utils';
import RemoveConfirmModal from './modals/RemoveConfirmModal';
@@ -40,7 +42,8 @@ export const UserItem = ({
showRemoveConfirm?: boolean;
}) => {
const { t } = useTranslation();
- const { userData } = useAppSelector((state) => state.user);
+ const { data: userData, isLoading, isSuccess } = useGetUsersMeQuery();
+
const [showRemoveConfirmModal, setShowRemoveConfirmModal] = useState(false);
const handleRemoveUser = () => {
@@ -49,103 +52,111 @@ export const UserItem = ({
const isMe = userData?.email === user.email;
+ if (isLoading || !isSuccess || !userData) return null;
+
return (
- <>
-
-
- {getInitials(user.name.length ? user.name : user.email)}
-
-
-
-
- {user.name.length ? user.name : user.email}{' '}
- {isMe && t('__WORKSPACE_SETTINGS_CURRENT_MEMBER_YOU_LABEL')}
-
-
- {user.name.length > 0 && (
-
+
+
+ {getInitials(user.name.length ? user.name : user.email)}
+
+
+
- {user.email}
-
- )}
-
- {onResendInvite && onRemoveUser ? (
-
- {!isMe && (
-
+ {user.name.length ? user.name : user.email}{' '}
+ {isMe && t('__WORKSPACE_SETTINGS_CURRENT_MEMBER_YOU_LABEL')}
+
+
+ {user.name.length > 0 && (
+ {
- if (value === 'invite') {
- onResendInvite();
- return;
+ >
+ {user.email}
+
+ )}
+
+ {onResendInvite && onRemoveUser ? (
+
+ {!isMe && (
+ {
+ if (value === 'invite') {
+ onResendInvite();
+ return;
+ }
- if (value === 'remove') {
- if (showRemoveConfirm) {
- handleRemoveUser();
- } else {
- onRemoveUser();
+ if (value === 'remove') {
+ if (showRemoveConfirm) {
+ handleRemoveUser();
+ } else {
+ onRemoveUser();
+ }
}
- }
- }}
- >
- {user.invitationPending && (
-
- {t('__WORKSPACE_SETTINGS_MEMBER_RESEND_INVITE_ACTION')}
+ }}
+ >
+ {user.invitationPending && (
+
+ {t('__WORKSPACE_SETTINGS_MEMBER_RESEND_INVITE_ACTION')}
+
+ )}
+
+
+ {t('__WORKSPACE_SETTINGS_MEMBER_REMOVE_USER_ACTION')}
+
- )}
-
-
- {t('__WORKSPACE_SETTINGS_MEMBER_REMOVE_USER_ACTION')}
-
-
-
- )}
-
- ) : (
- <>
- {user.invitationPending && (
-
- {t('__WORKSPACE_SETTINGS_MEMBER_INVITATION_PENDING_LABEL')}
-
- )}
- {!user.invitationPending && (
-
- {t('__WORKSPACE_SETTINGS_MEMBER_ACTIONS_LABEL')}
-
- )}
- >
+
+ )}
+
+ ) : (
+ <>
+ {user.invitationPending && (
+
+ {t('__WORKSPACE_SETTINGS_MEMBER_INVITATION_PENDING_LABEL')}
+
+ )}
+ {!user.invitationPending && (
+
+ {t('__WORKSPACE_SETTINGS_MEMBER_ACTIONS_LABEL')}
+
+ )}
+ >
+ )}
+
+ {showRemoveConfirmModal && onRemoveUser && (
+
onRemoveUser(includeShared)}
+ handleCancel={() => setShowRemoveConfirmModal(false)}
+ />
)}
-
- {showRemoveConfirmModal && onRemoveUser && (
- onRemoveUser(includeShared)}
- handleCancel={() => setShowRemoveConfirmModal(false)}
- />
- )}
- >
+ >
+ )
);
};
diff --git a/src/common/components/navigation/header/profileAvatar.tsx b/src/common/components/navigation/header/profileAvatar.tsx
index b1de9a3f1..9644b8008 100644
--- a/src/common/components/navigation/header/profileAvatar.tsx
+++ b/src/common/components/navigation/header/profileAvatar.tsx
@@ -8,6 +8,7 @@ import {
import { useAppDispatch, useAppSelector } from 'src/app/hooks';
import { prepareGravatar } from 'src/common/utils';
import { toggleProfileModal } from 'src/features/navigation/navigationSlice';
+import { useGetUsersMeQuery } from 'src/features/api';
import { ReactComponent as ChevronIcon } from 'src/assets/icons/chevron-down-stroke.svg';
import styled from 'styled-components';
import { getInitials } from './utils';
@@ -20,7 +21,9 @@ const ChevronButton = styled(IconButton)`
export const ProfileAvatar = () => {
const dispatch = useAppDispatch();
- const { userData: user } = useAppSelector((state) => state.user);
+
+ const { data: user, isLoading, isError } = useGetUsersMeQuery();
+
const { isProfileModalOpen } = useAppSelector((state) => state.navigation);
const toggleProfileModalState = () => {
@@ -30,7 +33,7 @@ export const ProfileAvatar = () => {
return (
- {!user ? (
+ {!user || isLoading || isError ? (
+
+
+
+
+
+
+
+
diff --git a/src/common/schema.ts b/src/common/schema.ts
index dede54d87..b9cc440fb 100644
--- a/src/common/schema.ts
+++ b/src/common/schema.ts
@@ -415,6 +415,8 @@ export interface paths {
};
"/users/me": {
get: operations["get-users-me"];
+ /** Update one or multiple user data */
+ patch: operations["patch-users-me"];
};
"/users/me/preferences": {
get: operations["get-users-me-preferences"];
@@ -576,6 +578,7 @@ export interface paths {
};
"/workspaces/{wid}/templates": {
get: operations["get-workspaces-templates"];
+ post: operations["post-workspaces-wid-templates"];
parameters: {
path: {
/** Workspace (company, customer) id */
@@ -1186,6 +1189,7 @@ export interface components {
/** OutputModuleTaskAccessibility */
OutputModuleTaskAccessibility: {
description?: string;
+ id?: string;
/** @enum {string} */
kind: "accessibility";
title: string;
@@ -1195,6 +1199,7 @@ export interface components {
/** SubcomponentTaskBug */
OutputModuleTaskBug: {
description?: string;
+ id?: string;
/** @enum {string} */
kind: "bug";
title: string;
@@ -1204,6 +1209,7 @@ export interface components {
/** OutputModuleTaskExplorativeBug */
OutputModuleTaskExplorativeBug: {
description?: string;
+ id?: string;
/** @enum {string} */
kind: "explorative-bug";
title: string;
@@ -1213,6 +1219,7 @@ export interface components {
/** OutputModuleTaskModerateVideo */
OutputModuleTaskModerateVideo: {
description?: string;
+ id?: string;
/** @enum {string} */
kind: "moderate-video";
title: string;
@@ -1222,6 +1229,7 @@ export interface components {
/** SubcomponentTaskSurvey */
OutputModuleTaskSurvey: {
description?: string;
+ id?: string;
/** @enum {string} */
kind: "survey";
title: string;
@@ -1231,6 +1239,7 @@ export interface components {
/** SubcomponentTaskVideo */
OutputModuleTaskVideo: {
description?: string;
+ id?: string;
/** @enum {string} */
kind: "video";
title: string;
@@ -1504,8 +1513,10 @@ export interface components {
/** Format: email */
email: string;
features?: components["schemas"]["Feature"][];
+ first_name: string;
/** @description This is the main id of the user. Currently is equal to tryber_wp_user_id */
id: number;
+ last_name: string;
name: string;
picture?: string;
profile_id: number;
@@ -3560,6 +3571,36 @@ export interface operations {
500: components["responses"]["Error"];
};
};
+ /** Update one or multiple user data */
+ "patch-users-me": {
+ responses: {
+ /** OK */
+ 200: {
+ content: {
+ "application/json": {
+ name?: string;
+ role?: string;
+ surname?: string;
+ };
+ };
+ };
+ 401: components["responses"]["Error"];
+ 403: components["responses"]["Error"];
+ };
+ requestBody: {
+ content: {
+ "application/json": {
+ name?: string;
+ password?: {
+ current: string;
+ new: string;
+ };
+ roleId?: number;
+ surname?: string;
+ };
+ };
+ };
+ };
"get-users-me-preferences": {
responses: {
/** OK */
@@ -4164,6 +4205,37 @@ export interface operations {
500: components["responses"]["Error"];
};
};
+ "post-workspaces-wid-templates": {
+ parameters: {
+ path: {
+ /** Workspace (company, customer) id */
+ wid: string;
+ };
+ };
+ responses: {
+ /** Created */
+ 201: {
+ content: {
+ "application/json": {
+ id: number;
+ };
+ };
+ };
+ /** Forbidden */
+ 403: unknown;
+ /** Not Found */
+ 404: unknown;
+ };
+ requestBody: {
+ content: {
+ "application/json": {
+ description?: string;
+ from_plan: number;
+ name: string;
+ };
+ };
+ };
+ };
"get-workspaces-wid-templates-tid": {
parameters: {
path: {
diff --git a/src/common/wpapi.ts b/src/common/wpapi.ts
index 49252c715..442f2cb69 100644
--- a/src/common/wpapi.ts
+++ b/src/common/wpapi.ts
@@ -98,6 +98,16 @@ const WPAPI = {
console.error('error', error);
});
},
+ destroyOtherSessions: () =>
+ fetch(
+ `${process.env.REACT_APP_CROWD_WP_URL}/wp-admin/admin-ajax.php?action=destroy_other_sessions`,
+ {
+ method: 'GET',
+ }
+ ).catch((e) => {
+ // eslint-disable-next-line no-console
+ console.error(e.message);
+ }),
};
export default WPAPI;
diff --git a/src/features/api/api.ts b/src/features/api/api.ts
index 0f2071819..1f7258d88 100644
--- a/src/features/api/api.ts
+++ b/src/features/api/api.ts
@@ -35,6 +35,7 @@ export const apiSlice = createApi({
'Translation',
'Archive',
'Plans',
+ 'Users',
],
endpoints: () => ({}),
});
diff --git a/src/features/api/apiTags.ts b/src/features/api/apiTags.ts
index 817e60976..e930f9002 100644
--- a/src/features/api/apiTags.ts
+++ b/src/features/api/apiTags.ts
@@ -1,4 +1,5 @@
-import { unguessApi } from '.';
+import * as uuid from 'uuid';
+import { GetPlansByPidApiResponse, ModuleTask, unguessApi } from '.';
unguessApi.enhanceEndpoints({
endpoints: {
@@ -92,9 +93,15 @@ unguessApi.enhanceEndpoints({
deleteCampaignsByCidBugsAndBidCommentsCmid: {
invalidatesTags: ['BugComments'],
},
+ getUsersMe: {
+ providesTags: ['Users'],
+ },
getUsersMePreferences: {
providesTags: ['Preferences'],
},
+ patchUsersMe: {
+ invalidatesTags: ['Users'],
+ },
putUsersMePreferencesBySlug: {
invalidatesTags: ['Preferences'],
},
@@ -266,6 +273,33 @@ unguessApi.enhanceEndpoints({
},
getPlansByPid: {
providesTags: ['Plans'],
+ transformResponse: (response: GetPlansByPidApiResponse) => {
+ if (response && response.config) {
+ // find the task module if any
+ const taskModule = response.config.modules.find(
+ (module) => module.type === 'tasks'
+ ) as ModuleTask | undefined;
+ if (taskModule && taskModule?.output) {
+ // add an id to each task for better identification
+ const mappedTasks = taskModule.output.map((task) => ({
+ ...task,
+ id: task.id || uuid.v4(), // generate a new UUID for each task
+ }));
+ taskModule.output = mappedTasks;
+ // now we can safely return the response
+ response.config.modules = response.config.modules.map((module) => {
+ if (module.type === 'tasks') {
+ return {
+ ...module,
+ output: mappedTasks,
+ };
+ }
+ return module;
+ });
+ }
+ }
+ return response;
+ },
},
patchPlansByPid: {
invalidatesTags: ['Plans'],
diff --git a/src/features/api/index.ts b/src/features/api/index.ts
index 13440433e..4d2911195 100644
--- a/src/features/api/index.ts
+++ b/src/features/api/index.ts
@@ -541,6 +541,13 @@ const injectedRtkApi = api.injectEndpoints({
getUsersMe: build.query({
query: () => ({ url: `/users/me` }),
}),
+ patchUsersMe: build.mutation({
+ query: (queryArg) => ({
+ url: `/users/me`,
+ method: 'PATCH',
+ body: queryArg.body,
+ }),
+ }),
getUsersMePreferences: build.query<
GetUsersMePreferencesApiResponse,
GetUsersMePreferencesApiArg
@@ -747,6 +754,16 @@ const injectedRtkApi = api.injectEndpoints({
},
}),
}),
+ postWorkspacesByWidTemplates: build.mutation<
+ PostWorkspacesByWidTemplatesApiResponse,
+ PostWorkspacesByWidTemplatesApiArg
+ >({
+ query: (queryArg) => ({
+ url: `/workspaces/${queryArg.wid}/templates`,
+ method: 'POST',
+ body: queryArg.body,
+ }),
+ }),
deleteWorkspacesByWidTemplatesAndTid: build.mutation<
DeleteWorkspacesByWidTemplatesAndTidApiResponse,
DeleteWorkspacesByWidTemplatesAndTidApiArg
@@ -1606,6 +1623,22 @@ export type HeadUsersByEmailByEmailApiArg = {
};
export type GetUsersMeApiResponse = /** status 200 */ User;
export type GetUsersMeApiArg = void;
+export type PatchUsersMeApiResponse = /** status 200 OK */ {
+ name?: string;
+ role?: string;
+ surname?: string;
+};
+export type PatchUsersMeApiArg = {
+ body: {
+ name?: string;
+ password?: {
+ current: string;
+ new: string;
+ };
+ roleId?: number;
+ surname?: string;
+ };
+};
export type GetUsersMePreferencesApiResponse = /** status 200 OK */ {
items?: UserPreference[];
};
@@ -1862,6 +1895,19 @@ export type GetWorkspacesByWidTemplatesApiArg = {
/** filterBy[]= */
filterBy?: any;
};
+export type PostWorkspacesByWidTemplatesApiResponse =
+ /** status 201 Created */ {
+ id: number;
+ };
+export type PostWorkspacesByWidTemplatesApiArg = {
+ /** Workspace (company, customer) id */
+ wid: string;
+ body: {
+ description?: string;
+ from_plan: number;
+ name: string;
+ };
+};
export type DeleteWorkspacesByWidTemplatesAndTidApiResponse =
/** status 200 OK */ {};
export type DeleteWorkspacesByWidTemplatesAndTidApiArg = {
@@ -2375,36 +2421,42 @@ export type ModuleDate = {
};
export type SubcomponentTaskVideo = {
description?: string;
+ id?: string;
kind: 'video';
title: string;
url?: string;
};
export type SubcomponentTaskBug = {
description?: string;
+ id?: string;
kind: 'bug';
title: string;
url?: string;
};
export type SubcomponentTaskSurvey = {
description?: string;
+ id?: string;
kind: 'survey';
title: string;
url?: string;
};
export type OutputModuleTaskModerateVideo = {
description?: string;
+ id?: string;
kind: 'moderate-video';
title: string;
url?: string;
};
export type OutputModuleTaskExplorativeBug = {
description?: string;
+ id?: string;
kind: 'explorative-bug';
title: string;
url?: string;
};
export type OutputModuleTaskAccessibility = {
description?: string;
+ id?: string;
kind: 'accessibility';
title: string;
url?: string;
@@ -2674,8 +2726,10 @@ export type User = {
customer_role: string;
email: string;
features?: Feature[];
+ first_name: string;
/** This is the main id of the user. Currently is equal to tryber_wp_user_id */
id: number;
+ last_name: string;
name: string;
picture?: string;
profile_id: number;
@@ -2832,6 +2886,7 @@ export const {
usePostUsersMutation,
useHeadUsersByEmailByEmailMutation,
useGetUsersMeQuery,
+ usePatchUsersMeMutation,
useGetUsersMePreferencesQuery,
usePutUsersMePreferencesBySlugMutation,
useGetUsersRolesQuery,
@@ -2854,6 +2909,7 @@ export const {
useGetWorkspacesByWidProjectsAndPidQuery,
useGetWorkspacesByWidProjectsAndPidCampaignsQuery,
useGetWorkspacesByWidTemplatesQuery,
+ usePostWorkspacesByWidTemplatesMutation,
useDeleteWorkspacesByWidTemplatesAndTidMutation,
useGetWorkspacesByWidTemplatesAndTidQuery,
useDeleteWorkspacesByWidUsersMutation,
diff --git a/src/features/navigation/Navigation/NavigationProfileModal.tsx b/src/features/navigation/Navigation/NavigationProfileModal.tsx
index 8f75a58f9..045d376f4 100644
--- a/src/features/navigation/Navigation/NavigationProfileModal.tsx
+++ b/src/features/navigation/Navigation/NavigationProfileModal.tsx
@@ -4,12 +4,14 @@ import {
useToast,
} from '@appquality/unguess-design-system';
import { useTranslation } from 'react-i18next';
+import { useNavigate } from 'react-router-dom';
import { useAppDispatch, useAppSelector } from 'src/app/hooks';
import { isDev } from 'src/common/isDevEnvironment';
import { prepareGravatar } from 'src/common/utils';
import WPAPI from 'src/common/wpapi';
import {
useGetUsersMePreferencesQuery,
+ useGetUsersMeQuery,
usePutUsersMePreferencesBySlugMutation,
} from 'src/features/api';
import { useActiveWorkspace } from 'src/hooks/useActiveWorkspace';
@@ -20,12 +22,14 @@ export const NavigationProfileModal = () => {
const isProfileModalOpen = useAppSelector(
(state) => state.navigation.isProfileModalOpen
);
- const { userData: user } = useAppSelector((state) => state.user);
+ const { data: user, isLoading, error: dataError } = useGetUsersMeQuery();
+
const { activeWorkspace } = useActiveWorkspace();
const { addToast } = useToast();
const { t, i18n } = useTranslation();
const dispatch = useAppDispatch();
+ const navigate = useNavigate();
const { data: preferences } = useGetUsersMePreferencesQuery();
@@ -62,6 +66,8 @@ export const NavigationProfileModal = () => {
});
};
+ if (dataError || !user || isLoading) return null;
+
const profileModal = {
user: {
name: user.name,
@@ -90,6 +96,13 @@ export const NavigationProfileModal = () => {
currentLanguage: i18n.language,
feedbackTitle: t('__PROFILE_MODAL_FEEDBACK_TITLE'),
feedbackSubTitle: t('__PROFILE_MODAL_FEEDBACK_SUBTITLE'),
+ profile: {
+ title: t('__PROFILE_MODAL_GO_TO_PROFILE'),
+ onClick: () => {
+ navigate('/profile');
+ dispatch(setProfileModalOpen(false));
+ },
+ },
csmTitle: t('__PROFILE_MODAL_CSM_TITLE'),
csmContactLabel: t('__PROFILE_MODAL_CSM_CONTACT_LABEL'),
languageTitle: t('__PROFILE_MODAL_LANGUAGES_TITLE'),
diff --git a/src/features/planModules/index.tsx b/src/features/planModules/index.tsx
index 39be38232..c8f416cd7 100644
--- a/src/features/planModules/index.tsx
+++ b/src/features/planModules/index.tsx
@@ -103,6 +103,7 @@ const planModuleSlice = createSlice({
state.currentModules = state.currentModules.filter(
(module) => module !== action.payload
);
+ // Remove errors related to the removed module
const newErrors = { ...state.errors };
Object.keys(newErrors).forEach((key) => {
if (key.startsWith(`${action.payload}.`) || key === action.payload) {
@@ -110,6 +111,10 @@ const planModuleSlice = createSlice({
}
});
state.errors = newErrors;
+ // remove the validation function for the removed module
+ if (state.validationFunctions[action.payload]) {
+ delete state.validationFunctions[action.payload];
+ }
},
setStatus: (state, action: PayloadAction) => {
state.status = action.payload;
diff --git a/src/features/templates/Logged.tsx b/src/features/templates/Logged.tsx
index 0b41ead8d..4d56b165d 100644
--- a/src/features/templates/Logged.tsx
+++ b/src/features/templates/Logged.tsx
@@ -3,11 +3,11 @@ import { Chrome, Body, Main, Anchor } from '@appquality/unguess-design-system';
import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute';
import { useNavigate, useLocation } from 'react-router-dom';
import { appTheme } from 'src/app/theme';
-import { useAppSelector } from 'src/app/hooks';
import styled from 'styled-components';
import { PageLoader } from 'src/common/components/PageLoader';
import * as Sentry from '@sentry/react';
import { Navigation } from '../navigation/Navigation';
+import { useGetUsersMeQuery } from '../api';
const StyledMain = styled(Main)`
background-color: ${({ theme }) => theme.palette.grey[100]};
@@ -37,17 +37,17 @@ export const Logged = ({
const loginRoute = useLocalizeRoute('login');
const navigate = useNavigate();
- const { status, userData } = useAppSelector((state) => state.user);
+ const { data: userData, isLoading, error, isFetching } = useGetUsersMeQuery();
useEffect(() => {
- if (status === 'failed') {
+ if (error) {
navigate(loginRoute, {
state: { from: locationState?.from ?? pathname },
});
}
- }, [status]);
+ }, [error]);
- if (status === 'idle' || status === 'loading') {
+ if (isLoading || isFetching || !userData) {
return ;
}
diff --git a/src/features/user/userSlice.ts b/src/features/user/userSlice.ts
deleted file mode 100644
index af1ecee06..000000000
--- a/src/features/user/userSlice.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { createSlice } from '@reduxjs/toolkit';
-import { fetchUser } from './actions/fetchUser';
-import { UserState } from './types';
-
-const initialState: UserState = {
- status: 'idle',
- userData: {
- id: 0,
- email: '',
- role: 'none',
- name: '',
- profile_id: 0,
- customer_role: 'Not set',
- tryber_wp_user_id: 0,
- unguess_wp_user_id: 0,
- },
-};
-
-const userSlice = createSlice({
- name: 'user',
- initialState,
- reducers: {},
- extraReducers: (builder) => {
- builder.addCase(fetchUser.pending, (state) => {
- state.status = 'loading';
- });
- builder.addCase(fetchUser.fulfilled, (state, action) => {
- state.userData = action.payload;
- state.status = 'logged';
- });
- builder.addCase(fetchUser.rejected, (state) => {
- state.status = 'failed';
- });
- },
-});
-
-export default userSlice.reducer;
diff --git a/src/hooks/useActiveWorkspace.ts b/src/hooks/useActiveWorkspace.ts
index e9db17977..6ecd73c56 100644
--- a/src/hooks/useActiveWorkspace.ts
+++ b/src/hooks/useActiveWorkspace.ts
@@ -6,10 +6,11 @@ import {
saveWorkspaceToLs,
} from 'src/features/navigation/cachedStorage';
-export const useActiveWorkspace = () => {
- const { data: workspaces, isLoading } = useGetWorkspacesQuery({
- orderBy: 'company',
- });
+export const useActiveWorkspace = ({ skip = false } = {}) => {
+ const { data: workspaces, isLoading } = useGetWorkspacesQuery(
+ { orderBy: 'company' },
+ { skip }
+ );
const activeWorkspaceFromRedux = useAppSelector(
(state) => state.navigation.activeWorkspace
diff --git a/src/hooks/useFeatureFlag.ts b/src/hooks/useFeatureFlag.ts
index 0cd2cc39f..e984cfd3c 100644
--- a/src/hooks/useFeatureFlag.ts
+++ b/src/hooks/useFeatureFlag.ts
@@ -1,23 +1,25 @@
-import { shallowEqual } from 'react-redux';
-import { useAppSelector } from 'src/app/hooks';
+import { useGetUsersMeQuery } from 'src/features/api';
export const useFeatureFlag = () => {
- const { role, features } = useAppSelector(
- (state) => ({
- role: state.user.userData.role,
- features: state.user.userData.features,
- }),
- shallowEqual
- );
+ const {
+ data: userData,
+ isLoading: isUserDataLoading,
+ isFetching: isUserFetching,
+ isError,
+ } = useGetUsersMeQuery();
+
+ if (isUserDataLoading || isUserFetching || isError || !userData) {
+ return { hasFeatureFlag: () => false };
+ }
+
+ const { role, features = [] } = userData;
const hasFeatureFlag = (slug?: string) => {
if (role === 'administrator') {
return true;
}
- if (features) {
- return features.some((feature) => feature.slug === slug);
- }
- return false;
+
+ return features.some((feature) => feature.slug === slug);
};
return { hasFeatureFlag };
diff --git a/src/hooks/useGTMevent.ts b/src/hooks/useGTMevent.ts
index 181da662e..471a6e277 100644
--- a/src/hooks/useGTMevent.ts
+++ b/src/hooks/useGTMevent.ts
@@ -1,6 +1,5 @@
import { useCallback } from 'react';
-import { shallowEqual } from 'react-redux';
-import { useAppSelector } from 'src/app/hooks';
+import { useGetUsersMeQuery } from 'src/features/api';
import { useAnalytics } from 'use-analytics';
import { useActiveWorkspace } from './useActiveWorkspace';
@@ -15,20 +14,23 @@ interface GTMEventData {
export const useSendGTMevent = ({
loggedUser = true,
}: { loggedUser?: boolean } = {}) => {
- const user = useAppSelector(
- (state) => ({
- role: state.user.userData.role,
- customer_role: state.user.userData.customer_role,
- tryber_wp_user_id: state.user.userData.tryber_wp_user_id,
- id: state.user.userData.id,
- name: state.user.userData.name,
- email: state.user.userData.email,
- }),
- shallowEqual
- );
- const { activeWorkspace } = useActiveWorkspace();
+ const { data: userData } = useGetUsersMeQuery(undefined, {
+ skip: !loggedUser,
+ });
+ const { activeWorkspace } = useActiveWorkspace({
+ skip: !loggedUser,
+ });
const { track } = useAnalytics();
+ const user = userData || {
+ role: undefined,
+ customer_role: undefined,
+ tryber_wp_user_id: undefined,
+ id: undefined,
+ name: undefined,
+ email: undefined,
+ };
+
const callback = useCallback(
(data: GTMEventData) => {
if (
diff --git a/src/index.tsx b/src/index.tsx
index 599020200..dff9bbb4b 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,14 +1,12 @@
-import { getWorkspaces } from 'src/features/workspaces/actions';
import { createRoot } from 'react-dom/client';
+import { getWorkspaces } from 'src/features/workspaces/actions';
import App from './app/App';
import { store } from './app/store';
-import { fetchUser } from './features/user/actions/fetchUser';
import reportWebVitals from './reportWebVitals';
const container = document.getElementById('root');
const root = createRoot(container!); // createRoot(container!) if you use TypeScript
-store.dispatch(fetchUser());
store.dispatch(getWorkspaces());
root.render();
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index ba310e231..274223efd 100644
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -25,7 +25,6 @@
"__ASIDE_NAVIGATION_MODULE_ADDITIONAL_TARGET_SUBTITLE": " ",
"__ASIDE_NAVIGATION_MODULE_AGE_SUBTITLE": "Participant age groups",
"__ASIDE_NAVIGATION_MODULE_BROWSER_SUBTITLE": "Compatible browsers",
- "__ASIDE_NAVIGATION_MODULE_DATES_BLOCK_SUBTITLE": " ",
"__ASIDE_NAVIGATION_MODULE_DIGITAL_LITERACY_ACCORDION_SUBTITLE": "Participant technical proficiency",
"__ASIDE_NAVIGATION_MODULE_GENDER_ACCORDION_SUBTITLE": "Participant gender criteria",
"__ASIDE_NAVIGATION_MODULE_GOAL_SUBTITLE": "Activity objective",
@@ -34,7 +33,6 @@
"__ASIDE_NAVIGATION_MODULE_LOCALITY_SUBTITLE": "Participant location criteria",
"__ASIDE_NAVIGATION_MODULE_OUT_OF_SCOPE_SUBTITLE": " ",
"__ASIDE_NAVIGATION_MODULE_SETUP_NOTE_BLOCK_SUBTITLE": " ",
- "__ASIDE_NAVIGATION_MODULE_SUBTITLE_BLOCK_SUBTITLE": " ",
"__ASIDE_NAVIGATION_MODULE_TARGET_NOTE_BLOCK_SUBTITLE": " ",
"__ASIDE_NAVIGATION_MODULE_TARGET_SUBTITLE": "Participant number",
"__ASIDE_NAVIGATION_MODULE_TASKS_SUBTITLE": " ",
@@ -342,6 +340,7 @@
"__CAMPAIGN_PAGE_DEVICE_AND_BUG_TYPES_SECTION_SUBTITLE": "Check all the isolated bugs organized for devices and OS plus all the bug typologies",
"__CAMPAIGN_PAGE_DEVICE_AND_BUG_TYPES_SECTION_TITLE": "Devices and bug types",
"__CAMPAIGN_PAGE_DOTS_MENU_ARCHIVE_CAMPAIGN_BUTTON": "Archive",
+ "__CAMPAIGN_PAGE_DOTS_MENU_GO_TO_PLAN_BUTTON": "Go to Activity Setup",
"__CAMPAIGN_PAGE_DOTS_MENU_MOVE_CAMPAIGN_BUTTON": "Move to",
"__CAMPAIGN_PAGE_EXP_OVERVIEW_SECTION_SUBTITLE": "The overall user experience with the product",
"__CAMPAIGN_PAGE_EXP_OVERVIEW_SECTION_TITLE": "Overview",
@@ -713,6 +712,14 @@
"__PAGE_NOT_ACCESIBLE_BUTTON_LOGOUT": "Logout",
"__PAGE_NOT_ACCESIBLE_DESCRIPTION": "It seems that your access is no longer active. You can log out or contact our support center. We are here to help you!",
"__PAGE_NOT_ACCESIBLE_TITLE": "You cannot access this page at the moment.",
+ "__PAGE_PROFILE_CONFIRM_PASSWORD_LABEL": "Confirm new password",
+ "__PAGE_PROFILE_CONFIRM_PASSWORD_PLACEHOLDER": "Confirm your new password",
+ "__PAGE_PROFILE_CURRENT_PASSWORD_LABEL": "Current password",
+ "__PAGE_PROFILE_CURRENT_PASSWORD_PLACEHOLDER": "Enter your current password",
+ "__PAGE_PROFILE_FORGOT_PASSWORD": "Forgot password?",
+ "__PAGE_PROFILE_NEW_PASSWORD_LABEL": "New password",
+ "__PAGE_PROFILE_NEW_PASSWORD_PLACEHOLDER": "Enter your new password",
+ "__PAGE_PROFILE_SAVE_CHANGES_BUTTON": "Save changes",
"__PAGE_TITLE_BUGS_COLLECTION": "Bug collection",
"__PAGE_TITLE_JOIN": "join page",
"__PAGE_TITLE_LOGIN": "Log in",
@@ -745,6 +752,7 @@
"__PLAN_DATE_ERROR_REQUIRED": "Required field: enter a date to continue",
"__PLAN_DATE_IN_FUTURE_ERROR": "Date must be at least one business day in the future",
"__PLAN_DELETE_PLAN_CTA": "Delete draft",
+ "__PLAN_DELETE_PLAN_TOOLTIP": "You can’t delete this activity because it’s no longer in draft",
"__PLAN_EMPLOYMENT_SIZE_ERROR_REQUIRED": "Please select at least one category to continue",
"__PLAN_GOAL_SIZE_ERROR_REQUIRED": "Required field: enter a goal to continue",
"__PLAN_GOAL_SIZE_ERROR_TOO_LONG": "Character limit exceeded: Please reduce your text to 256 characters",
@@ -808,7 +816,6 @@
"__PLAN_PAGE_MODULE_BROWSER_LABEL": "Browser selection",
"__PLAN_PAGE_MODULE_BROWSER_REMOVE_BUTTON": "Delete",
"__PLAN_PAGE_MODULE_BROWSER_TITLE": "Choose the browser you want to include in the activity",
- "__PLAN_PAGE_MODULE_DATES_BLOCK_TITLE": "Dates item",
"__PLAN_PAGE_MODULE_DIGITAL_LITERACY_ACCORDION_LABEL": "Digital skills",
"__PLAN_PAGE_MODULE_DIGITAL_LITERACY_ALL_LABEL": "All levels",
"__PLAN_PAGE_MODULE_DIGITAL_LITERACY_ALL_LABEL_HINT": "Participants equally divided by literacy level",
@@ -984,7 +991,6 @@
"__PLAN_PAGE_MODULE_TASKS_TASK_TITLE_PLACEHOLDER_EMPTY": "Task title",
"__PLAN_PAGE_MODULE_TASKS_TASK_URL_LINK_ERROR_INVALID_URL": "Task link should be a valid URL",
"__PLAN_PAGE_MODULE_TASKS_TITLE": "Tasks",
- "__PLAN_PAGE_MODULE_TITLE_BLOCK_TITLE": "Title item",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_ADD_TOUCHPOINT_APP_TAB": "App based",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_ADD_TOUCHPOINT_BUTTON": "Add touchpoint",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_ADD_TOUCHPOINT_MODAL_DEFAULT_TAB": "All",
@@ -1044,6 +1050,18 @@
"__PLAN_PAGE_MODULE_TOUCHPOINTS_TOUCHPOINT_WEB_LINK_LABEL": "Test link",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_TOUCHPOINT_WEB_LINK_PLACEHOLDER": "https://example.com",
"__PLAN_PAGE_NAV_GENERIC_MODULE_ERROR": "This item has some errors",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_CANCEL": "Cancel",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_CONFIRM": "Save template",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_CONTINUE_SETUP": "Continue setup",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_VIEW_TEMPLATES": "View templates",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_DESCRIPTION_MAX": "This description is a bit long. We advise you to stay within 512 characters including spaces.",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_HEADER": "Did you find the perfect match?This template will help you launch similar activities more quickly.",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_NAME_MAX": "This name is a bit long. We advise you to stay within 64 characters including spaces.",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_NAME_REQUIRED": "Choose a name before saving the template",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_TITLE": "Save as template",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_QUOTE_DISCLAIMER": "The final price may vary based on your activities settings",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_QUOTE_TITLE": "STARTING PRICE",
+ "__PLAN_PAGE_SAVE_PLAN_MODAL_ERROR": "The plan could not be saved: please try again later.",
"__PLAN_PAGE_SUMMARY_TAB_ACTIVITY_INFO_APPROVED_DESCRIPTION": "The quotation are currently being processed. Some details may vary or need confirmation",
"__PLAN_PAGE_SUMMARY_TAB_ACTIVITY_INFO_AWAITING_DESCRIPTION": "Your request has been processed. Please review and confirm these details.",
"__PLAN_PAGE_SUMMARY_TAB_ACTIVITY_INFO_DATE_LABEL": "Start date",
@@ -1063,11 +1081,17 @@
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_DESCRIPTION": "Your quotation is confirmed.<1><0>Approve now0> to <3>secure your date3> and begin collecting valuable insights:1><2><0>Start on the scheduled date0><1>Collect valuable user feedback for your digital product1><2>Receive notifications when first results become available2>2>You can also <4>return to draft status4> if you need to make changes.",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_GO_TO_CAMPAIGN_CTA": "Go to dashboard",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_REFUSE_CTA": "Return to draft",
+ "__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_SAVE_TEMPLATE_CTA": "Save as template",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_TITLE": "Ready to confirm and launch your activity?",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_WARNING_DESCRIPTION": "Returning to draft will require a new quotation process and may affect your start date and pricing.",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_WARNING_TITLE": "Important:",
"__PLAN_PAGE_SUMMARY_TAB_GO_TO_DASHBOARD_CARD_DESCRIPTION": "<0>We'll notify you by email when the first results are available. In the meantime, you can:0><1><0>Set up email notifications for key milestones;0><1>Invite team members who should have access to results1>1>",
"__PLAN_PAGE_SUMMARY_TAB_GO_TO_DASHBOARD_CARD_TITLE": "What can you do now?",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_CARD_DESCRIPTION": "Save this configuration as a template and launch future campaigns in no time.",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_CARD_TITLE": "Did you find the perfect match?",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_TEMPLATE_LIST_MORE_one": "...and {{count}} more",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_TEMPLATE_LIST_MORE_other": "...and {{count}} more",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_TEMPLATE_LIST_TITLE": "Latest templates saved from this activity:",
"__PLAN_PAGE_TAB_INSTRUCTIONS_TAB_TITLE": "Assign task",
"__PLAN_PAGE_TAB_SETUP_TAB_TITLE": "Set up",
"__PLAN_PAGE_TAB_SUMMARY_TAB_TITLE": "Get expert feedback",
@@ -1077,6 +1101,7 @@
"__PLAN_SAVE_CONFIGURATION_CTA": "Save Draft",
"__PLAN_SAVE_DRAFT_TOAST_ERROR": "We couldn't save your draft: please try again later.",
"__PLAN_SAVE_DRAFT_TOAST_SUCCESS": "Activity draft saved! You can safely continue editing.",
+ "__PLAN_SAVE_TEMPLATE_CTA": "Save as template",
"__PLAN_SETUP_NOTE_SIZE_ERROR_EMPTY": "Required: please enter a text to continue",
"__PLAN_TARGET_NOTE_SIZE_ERROR_EMPTY": "Please enter a text to continue",
"__PLAN_TARGET_SIZE_ERROR_REQUIRED": "Please enter at least one user to include in the activity",
@@ -1089,6 +1114,7 @@
"__PROFILE_MODAL_CURRENT_LANGUAGE_LABEL": "Now:",
"__PROFILE_MODAL_FEEDBACK_SUBTITLE": "Help us improve UNGUESS!",
"__PROFILE_MODAL_FEEDBACK_TITLE": "Give us your feedback",
+ "__PROFILE_MODAL_GO_TO_PROFILE": "Edit profile",
"__PROFILE_MODAL_LANGUAGES_TITLE": "Change Language",
"__PROFILE_MODAL_LOGOUT_TITLE": "Log Out",
"__PROFILE_MODAL_NOTIFICATIONS_INTRO": "Manage the notifications we send you by email.",
@@ -1101,6 +1127,27 @@
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_TITLE": "Allow notifications",
"__PROFILE_MODAL_NOTIFICATIONS_UPDATED": "Changes saved",
"__PROFILE_MODAL_PRIVACY_ITEM_LABEL": "Privacy settings",
+ "__PROFILE_PAGE_CONFIRM_PASSWORD_MUST_MATCH_NEW_PASSWORD": "The confirmation password must match the new password",
+ "__PROFILE_PAGE_NAME_REQUIRED_ERROR": "Name is required",
+ "__PROFILE_PAGE_NAV_ITEM_PASSWORD": "Password settings",
+ "__PROFILE_PAGE_NAV_ITEM_PROFILE": "Profile settings",
+ "__PROFILE_PAGE_NAV_SECTION_PASSWORD": "PASSWORD",
+ "__PROFILE_PAGE_NEW_PASSWORD_REQUIRED_ERROR": "New password is required",
+ "__PROFILE_PAGE_PASSWORD_ACCORDION_LABEL": "Password settings",
+ "__PROFILE_PAGE_ROLE_REQUIRED_ERROR": "Role is required",
+ "__PROFILE_PAGE_SURNAME_REQUIRED_ERROR": "Surname is required",
+ "__PROFILE_PAGE_TITLE": "My Profile",
+ "__PROFILE_PAGE_TOAST_ERROR_INVALID_CURRENT_PASSWORD": "Invalid current password. Please try again.",
+ "__PROFILE_PAGE_TOAST_ERROR_UPDATING_PASSWORD": "An error occurred while updating the password. Please try again.",
+ "__PROFILE_PAGE_TOAST_ERROR_UPDATING_PROFILE": "An error occurred while updating your profile. Please try again.",
+ "__PROFILE_PAGE_TOAST_SUCCESS_PASSWORD_UPDATED": "Password updated successfully",
+ "__PROFILE_PAGE_UPDATE_SUCCESS": "Profile updated successfully",
+ "__PROFILE_PAGE_USER_CARD_EMAIL_LABEL": "Work email",
+ "__PROFILE_PAGE_USER_CARD_LABEL": "Profile settings",
+ "__PROFILE_PAGE_USER_CARD_NAME_LABEL": "First name",
+ "__PROFILE_PAGE_USER_CARD_ROLE_LABEL": "Job role",
+ "__PROFILE_PAGE_USER_CARD_ROLE_PLACEHOLDER": "Select a Job role",
+ "__PROFILE_PAGE_USER_CARD_SURNAME_LABEL": "Last name",
"__PROJECT_FORM_DESCRIPTION_MAX": "This description is a bit long. It is recommended not to exceed 234 characters, including spaces.",
"__PROJECT_FORM_NAME_MAX": "This name is a bit long. We advise you to stay within 64 characters including spaces.",
"__PROJECT_FORM_NAME_REQUIRED": "Choose a name before creating the project",
@@ -1255,6 +1302,7 @@
"_CAMPAIGN_WIDGET_UX_TEST_PROGRESS_MONITORING_HEADER": "Test Progress",
"_CAMPAIGN_WIDGET_UX_USER_ANALYSIS_DESCRIPTION_HEADER": "There are observations on",
"_CAMPAIGN_WIDGET_UX_USER_ANALYSIS_HEADER": "Analyzed User Contributions",
+ "_PAGE_PROFILE_HEADER_TEXT": "Keep your profile up to date: edit your name, role, or password anytime to make UNGUESS truly yours.",
"_PLAN_PAGE_MODULE_LANGUAGE_DESCRIPTION": "You’ll receive feedback in the language you’re selecting",
"_PLAN_PAGE_MODULE_LANGUAGE_SUBTITLE": "Select participants' preferred language",
"_PROJECT_PAGE_PLANS_GROUP_SEE_ALL": "View more",
@@ -1291,6 +1339,13 @@
"PLAN_GLOBAL_ALERT_AWATING_STATE_TITLE": "Your quotation is ready!",
"PLAN_GLOBAL_ALERT_SUBMITTED_STATE_MESSAGE": "You'll receive a notification once your quotation is available.",
"PLAN_GLOBAL_ALERT_SUBMITTED_STATE_TITLE": "Activity submitted for review",
+ "SAVE_AS_TEMPLATE_FORM_DESCRIPTION": "Template description (optional)",
+ "SAVE_AS_TEMPLATE_FORM_DESCRIPTION_PLACEHOLDER": "Write the template description",
+ "SAVE_AS_TEMPLATE_FORM_TITLE": "Template name",
+ "SAVE_AS_TEMPLATE_FORM_TITLE_PLACEHOLDER": "Write the template name",
+ "SAVE_AS_TEMPLATE_SUCCESS_TEXT_1": "You’ve saved a template from this setup.",
+ "SAVE_AS_TEMPLATE_SUCCESS_TEXT_2": "It’s now available on your Templates page and can be reused anytime to quickly launch similar activities.",
+ "SAVE_AS_TEMPLATE_SUCCESS_TITLE": "Template saved successfully!",
"Severity ({{count}})_one": "Severity ({{count}})",
"Severity ({{count}})_other": "Severities ({{count}})",
"SIGNUP_FORM_CTA_RETURN_TO_UNGUESS_LANDING": "Go to the UNGUESS website",
@@ -1318,6 +1373,7 @@
"SIGNUP_FORM_RETURN_TO_STEP_2": "Back",
"SIGNUP_FORM_ROLE_IS_REQUIRED": "This field is required",
"SIGNUP_FORM_ROLE_LABEL": "Job title",
+ "SIGNUP_FORM_ROLE_PLACEHOLDER": "Select a Job role",
"SIGNUP_FORM_STEP_1_TITLE": "Welcome!
Get started with your account!",
"SIGNUP_FORM_STEP_2_DESCRIPTION": "So we can tailor the experience to fit your role and needs.",
"SIGNUP_FORM_STEP_2_TITLE": "Tell us a bit about yourself",
diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json
index e21a5a7e7..e4a9da1c7 100644
--- a/src/locales/it/translation.json
+++ b/src/locales/it/translation.json
@@ -25,7 +25,6 @@
"__ASIDE_NAVIGATION_MODULE_ADDITIONAL_TARGET_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_AGE_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_BROWSER_SUBTITLE": "",
- "__ASIDE_NAVIGATION_MODULE_DATES_BLOCK_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_DIGITAL_LITERACY_ACCORDION_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_GENDER_ACCORDION_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_GOAL_SUBTITLE": "",
@@ -34,7 +33,6 @@
"__ASIDE_NAVIGATION_MODULE_LOCALITY_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_OUT_OF_SCOPE_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_SETUP_NOTE_BLOCK_SUBTITLE": "",
- "__ASIDE_NAVIGATION_MODULE_SUBTITLE_BLOCK_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_TARGET_NOTE_BLOCK_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_TARGET_SUBTITLE": "",
"__ASIDE_NAVIGATION_MODULE_TASKS_SUBTITLE": "",
@@ -361,6 +359,7 @@
"__CAMPAIGN_PAGE_DEVICE_AND_BUG_TYPES_SECTION_SUBTITLE": "Visualizza i bug divisi per dispositivi e sistemi operativi e le tipologie di tutti i bug segnalati",
"__CAMPAIGN_PAGE_DEVICE_AND_BUG_TYPES_SECTION_TITLE": "Dispositivi e tipologie bug",
"__CAMPAIGN_PAGE_DOTS_MENU_ARCHIVE_CAMPAIGN_BUTTON": "Archivia",
+ "__CAMPAIGN_PAGE_DOTS_MENU_GO_TO_PLAN_BUTTON": "",
"__CAMPAIGN_PAGE_DOTS_MENU_MOVE_CAMPAIGN_BUTTON": "",
"__CAMPAIGN_PAGE_EXP_OVERVIEW_SECTION_SUBTITLE": "Com’è stata l’esperienza complessiva degli utenti con il prodotto",
"__CAMPAIGN_PAGE_EXP_OVERVIEW_SECTION_TITLE": "Panoramica",
@@ -743,6 +742,14 @@
"__PAGE_NOT_ACCESIBLE_BUTTON_LOGOUT": "Logout",
"__PAGE_NOT_ACCESIBLE_DESCRIPTION": "Sembra che tu non abbia più accesso al workspace. Se hai bisogno di aiuto, contatta il nostro centro assistenza. ",
"__PAGE_NOT_ACCESIBLE_TITLE": "Al momento non è possibile accedere a questa pagina.",
+ "__PAGE_PROFILE_CONFIRM_PASSWORD_LABEL": "",
+ "__PAGE_PROFILE_CONFIRM_PASSWORD_PLACEHOLDER": "",
+ "__PAGE_PROFILE_CURRENT_PASSWORD_LABEL": "",
+ "__PAGE_PROFILE_CURRENT_PASSWORD_PLACEHOLDER": "",
+ "__PAGE_PROFILE_FORGOT_PASSWORD": "",
+ "__PAGE_PROFILE_NEW_PASSWORD_LABEL": "",
+ "__PAGE_PROFILE_NEW_PASSWORD_PLACEHOLDER": "",
+ "__PAGE_PROFILE_SAVE_CHANGES_BUTTON": "",
"__PAGE_TITLE_BUGS_COLLECTION": "Raccolta bug",
"__PAGE_TITLE_JOIN": "",
"__PAGE_TITLE_LOGIN": "Accedi",
@@ -775,6 +782,7 @@
"__PLAN_DATE_ERROR_REQUIRED": "",
"__PLAN_DATE_IN_FUTURE_ERROR": "",
"__PLAN_DELETE_PLAN_CTA": "",
+ "__PLAN_DELETE_PLAN_TOOLTIP": "",
"__PLAN_EMPLOYMENT_SIZE_ERROR_REQUIRED": "",
"__PLAN_GOAL_SIZE_ERROR_REQUIRED": "",
"__PLAN_GOAL_SIZE_ERROR_TOO_LONG": "",
@@ -838,7 +846,6 @@
"__PLAN_PAGE_MODULE_BROWSER_LABEL": "",
"__PLAN_PAGE_MODULE_BROWSER_REMOVE_BUTTON": "",
"__PLAN_PAGE_MODULE_BROWSER_TITLE": "",
- "__PLAN_PAGE_MODULE_DATES_BLOCK_TITLE": "",
"__PLAN_PAGE_MODULE_DIGITAL_LITERACY_ACCORDION_LABEL": "",
"__PLAN_PAGE_MODULE_DIGITAL_LITERACY_ALL_LABEL": "",
"__PLAN_PAGE_MODULE_DIGITAL_LITERACY_ALL_LABEL_HINT": "",
@@ -1014,7 +1021,6 @@
"__PLAN_PAGE_MODULE_TASKS_TASK_TITLE_PLACEHOLDER_EMPTY": "",
"__PLAN_PAGE_MODULE_TASKS_TASK_URL_LINK_ERROR_INVALID_URL": "",
"__PLAN_PAGE_MODULE_TASKS_TITLE": "",
- "__PLAN_PAGE_MODULE_TITLE_BLOCK_TITLE": "",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_ADD_TOUCHPOINT_APP_TAB": "",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_ADD_TOUCHPOINT_BUTTON": "",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_ADD_TOUCHPOINT_MODAL_DEFAULT_TAB": "",
@@ -1074,6 +1080,18 @@
"__PLAN_PAGE_MODULE_TOUCHPOINTS_TOUCHPOINT_WEB_LINK_LABEL": "",
"__PLAN_PAGE_MODULE_TOUCHPOINTS_TOUCHPOINT_WEB_LINK_PLACEHOLDER": "",
"__PLAN_PAGE_NAV_GENERIC_MODULE_ERROR": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_CANCEL": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_CONFIRM": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_CONTINUE_SETUP": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_BUTTON_VIEW_TEMPLATES": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_DESCRIPTION_MAX": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_HEADER": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_NAME_MAX": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_NAME_REQUIRED": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_MODAL_TITLE": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_QUOTE_DISCLAIMER": "",
+ "__PLAN_PAGE_SAVE_AS_TEMPLATE_QUOTE_TITLE": "",
+ "__PLAN_PAGE_SAVE_PLAN_MODAL_ERROR": "",
"__PLAN_PAGE_SUMMARY_TAB_ACTIVITY_INFO_APPROVED_DESCRIPTION": "",
"__PLAN_PAGE_SUMMARY_TAB_ACTIVITY_INFO_AWAITING_DESCRIPTION": "",
"__PLAN_PAGE_SUMMARY_TAB_ACTIVITY_INFO_DATE_LABEL": "",
@@ -1093,11 +1111,18 @@
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_DESCRIPTION": "",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_GO_TO_CAMPAIGN_CTA": "",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_REFUSE_CTA": "",
+ "__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_SAVE_TEMPLATE_CTA": "",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_TITLE": "",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_WARNING_DESCRIPTION": "",
"__PLAN_PAGE_SUMMARY_TAB_CONFIRMATION_CARD_WARNING_TITLE": "",
"__PLAN_PAGE_SUMMARY_TAB_GO_TO_DASHBOARD_CARD_DESCRIPTION": "<0>We'll notify you by email when the first results are available. In the meantime, you can:0><1><0>Set up email notifications for key milestones;0><1>Invite team members who should have access to results1>1>",
"__PLAN_PAGE_SUMMARY_TAB_GO_TO_DASHBOARD_CARD_TITLE": "",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_CARD_DESCRIPTION": "",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_CARD_TITLE": "",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_TEMPLATE_LIST_MORE_one": "",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_TEMPLATE_LIST_MORE_many": "",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_TEMPLATE_LIST_MORE_other": "",
+ "__PLAN_PAGE_SUMMARY_TAB_SAVE_TEMPLATE_TEMPLATE_LIST_TITLE": "",
"__PLAN_PAGE_TAB_INSTRUCTIONS_TAB_TITLE": "",
"__PLAN_PAGE_TAB_SETUP_TAB_TITLE": "",
"__PLAN_PAGE_TAB_SUMMARY_TAB_TITLE": "",
@@ -1107,6 +1132,7 @@
"__PLAN_SAVE_CONFIGURATION_CTA": "",
"__PLAN_SAVE_DRAFT_TOAST_ERROR": "",
"__PLAN_SAVE_DRAFT_TOAST_SUCCESS": "",
+ "__PLAN_SAVE_TEMPLATE_CTA": "",
"__PLAN_SETUP_NOTE_SIZE_ERROR_EMPTY": "",
"__PLAN_TARGET_NOTE_SIZE_ERROR_EMPTY": "",
"__PLAN_TARGET_SIZE_ERROR_REQUIRED": "",
@@ -1119,6 +1145,7 @@
"__PROFILE_MODAL_CURRENT_LANGUAGE_LABEL": "Adesso:",
"__PROFILE_MODAL_FEEDBACK_SUBTITLE": "Aiutaci a migliorare UNGUESS!",
"__PROFILE_MODAL_FEEDBACK_TITLE": "Dacci il tuo feedback",
+ "__PROFILE_MODAL_GO_TO_PROFILE": "",
"__PROFILE_MODAL_LANGUAGES_TITLE": "Cambia Lingua",
"__PROFILE_MODAL_LOGOUT_TITLE": "Esci",
"__PROFILE_MODAL_NOTIFICATIONS_INTRO": "Gestisci le notifiche che ti mandiamo per email.",
@@ -1131,6 +1158,27 @@
"__PROFILE_MODAL_NOTIFICATIONS_TOGGLE_TITLE": "Vuoi ricevere le notifiche?",
"__PROFILE_MODAL_NOTIFICATIONS_UPDATED": "Modifiche salvate",
"__PROFILE_MODAL_PRIVACY_ITEM_LABEL": "Opzioni Privacy",
+ "__PROFILE_PAGE_CONFIRM_PASSWORD_MUST_MATCH_NEW_PASSWORD": "",
+ "__PROFILE_PAGE_NAME_REQUIRED_ERROR": "",
+ "__PROFILE_PAGE_NAV_ITEM_PASSWORD": "",
+ "__PROFILE_PAGE_NAV_ITEM_PROFILE": "",
+ "__PROFILE_PAGE_NAV_SECTION_PASSWORD": "",
+ "__PROFILE_PAGE_NEW_PASSWORD_REQUIRED_ERROR": "",
+ "__PROFILE_PAGE_PASSWORD_ACCORDION_LABEL": "",
+ "__PROFILE_PAGE_ROLE_REQUIRED_ERROR": "",
+ "__PROFILE_PAGE_SURNAME_REQUIRED_ERROR": "",
+ "__PROFILE_PAGE_TITLE": "Profilo",
+ "__PROFILE_PAGE_TOAST_ERROR_INVALID_CURRENT_PASSWORD": "",
+ "__PROFILE_PAGE_TOAST_ERROR_UPDATING_PASSWORD": "",
+ "__PROFILE_PAGE_TOAST_ERROR_UPDATING_PROFILE": "",
+ "__PROFILE_PAGE_TOAST_SUCCESS_PASSWORD_UPDATED": "",
+ "__PROFILE_PAGE_UPDATE_SUCCESS": "",
+ "__PROFILE_PAGE_USER_CARD_EMAIL_LABEL": "",
+ "__PROFILE_PAGE_USER_CARD_LABEL": "",
+ "__PROFILE_PAGE_USER_CARD_NAME_LABEL": "",
+ "__PROFILE_PAGE_USER_CARD_ROLE_LABEL": "",
+ "__PROFILE_PAGE_USER_CARD_ROLE_PLACEHOLDER": "",
+ "__PROFILE_PAGE_USER_CARD_SURNAME_LABEL": "",
"__PROJECT_FORM_DESCRIPTION_MAX": "",
"__PROJECT_FORM_NAME_MAX": "",
"__PROJECT_FORM_NAME_REQUIRED": "",
@@ -1292,6 +1340,7 @@
"_CAMPAIGN_WIDGET_UX_TEST_PROGRESS_MONITORING_HEADER": "Andamento Test",
"_CAMPAIGN_WIDGET_UX_USER_ANALYSIS_DESCRIPTION_HEADER": "Hai aggiunto osservazioni su",
"_CAMPAIGN_WIDGET_UX_USER_ANALYSIS_HEADER": "Contributi utente analizzati",
+ "_PAGE_PROFILE_HEADER_TEXT": "",
"_PLAN_PAGE_MODULE_LANGUAGE_DESCRIPTION": "",
"_PLAN_PAGE_MODULE_LANGUAGE_SUBTITLE": "",
"_PROJECT_PAGE_PLANS_GROUP_SEE_ALL": "Vedi tutti",
@@ -1329,6 +1378,13 @@
"PLAN_GLOBAL_ALERT_AWATING_STATE_TITLE": "",
"PLAN_GLOBAL_ALERT_SUBMITTED_STATE_MESSAGE": "",
"PLAN_GLOBAL_ALERT_SUBMITTED_STATE_TITLE": "",
+ "SAVE_AS_TEMPLATE_FORM_DESCRIPTION": "",
+ "SAVE_AS_TEMPLATE_FORM_DESCRIPTION_PLACEHOLDER": "",
+ "SAVE_AS_TEMPLATE_FORM_TITLE": "",
+ "SAVE_AS_TEMPLATE_FORM_TITLE_PLACEHOLDER": "",
+ "SAVE_AS_TEMPLATE_SUCCESS_TEXT_1": "",
+ "SAVE_AS_TEMPLATE_SUCCESS_TEXT_2": "",
+ "SAVE_AS_TEMPLATE_SUCCESS_TITLE": "",
"Severity ({{count}})_one": "Gravità ({{count}})",
"Severity ({{count}})_many": "",
"Severity ({{count}})_other": "Gravità ({{count}})",
@@ -1357,6 +1413,7 @@
"SIGNUP_FORM_RETURN_TO_STEP_2": "",
"SIGNUP_FORM_ROLE_IS_REQUIRED": "",
"SIGNUP_FORM_ROLE_LABEL": "",
+ "SIGNUP_FORM_ROLE_PLACEHOLDER": "",
"SIGNUP_FORM_STEP_1_TITLE": "",
"SIGNUP_FORM_STEP_2_DESCRIPTION": "",
"SIGNUP_FORM_STEP_2_TITLE": "",
diff --git a/src/pages/Bug/Chat.tsx b/src/pages/Bug/Chat.tsx
index b6a426658..97f4dc7d9 100644
--- a/src/pages/Bug/Chat.tsx
+++ b/src/pages/Bug/Chat.tsx
@@ -9,12 +9,12 @@ import {
} from '@appquality/unguess-design-system';
import { t } from 'i18next';
import { useEffect, useRef, useState } from 'react';
-import { useAppSelector } from 'src/app/hooks';
import defaultBkg from 'src/assets/bg-chat.svg';
import { getInitials } from 'src/common/components/navigation/header/utils';
import {
useDeleteCampaignsByCidBugsAndBidCommentsCmidMutation,
useGetCampaignsByCidBugsAndBidCommentsQuery,
+ useGetUsersMeQuery,
} from 'src/features/api';
import i18n from 'src/i18n';
import { styled } from 'styled-components';
@@ -59,7 +59,13 @@ export const ChatBox = ({
setIsSubmitting: (state: boolean) => void;
}) => {
const { triggerSave, editor, clearInput } = useChatContext();
- const { userData: user } = useAppSelector((state) => state.user);
+ const {
+ data: user,
+ isLoading: userDataLoading,
+ isSuccess,
+ isError: isUserError,
+ } = useGetUsersMeQuery();
+
const [isModalOpen, setIsModalOpen] = useState(false);
const [commentToDelete, setCommentToDelete] = useState('');
const { addToast } = useToast();
@@ -127,6 +133,8 @@ export const ChatBox = ({
};
}, [comments]);
+ if (!user || isUserError || userDataLoading) return null;
+
return (
<>
@@ -171,16 +179,17 @@ export const ChatBox = ({
<>
{(comment.creator.id === user.profile_id ||
- user.role === 'administrator') && (
-
- )}
+ user.role === 'administrator') &&
+ isSuccess && (
+
+ )}
>
))}
diff --git a/src/pages/Bug/hooks/getMentionableUsers.ts b/src/pages/Bug/hooks/getMentionableUsers.ts
index ee05d41c6..f6618b811 100644
--- a/src/pages/Bug/hooks/getMentionableUsers.ts
+++ b/src/pages/Bug/hooks/getMentionableUsers.ts
@@ -4,6 +4,7 @@ import {
Tenant,
useGetCampaignsByCidUsersQuery,
useGetProjectsByPidUsersQuery,
+ useGetUsersMeQuery,
useGetWorkspacesByWidUsersQuery,
} from 'src/features/api';
import { useGetCampaignWithWorkspaceQuery } from 'src/features/api/customEndpoints/getCampaignWithWorkspace';
@@ -19,7 +20,7 @@ export const useGetMentionableUsers = () => {
const { data: { campaign } = {} } = useGetCampaignWithWorkspaceQuery({
cid: campaignId || '0',
});
- const { userData } = useAppSelector((state) => state.user);
+ const { data: userData } = useGetUsersMeQuery();
const {
data: workspaceUsers,
@@ -78,7 +79,7 @@ export const useGetMentionableUsers = () => {
// Remove user himself
const users = filteredUsers.filter(
- (u) => u.profile_id !== userData.profile_id
+ (u) => u.profile_id !== userData?.profile_id
);
return {
diff --git a/src/pages/Campaign/pageHeader/Meta/index.tsx b/src/pages/Campaign/pageHeader/Meta/index.tsx
index 022f6dd9c..aef29272b 100644
--- a/src/pages/Campaign/pageHeader/Meta/index.tsx
+++ b/src/pages/Campaign/pageHeader/Meta/index.tsx
@@ -1,16 +1,18 @@
import {
Button,
- DotsMenu,
+ ButtonMenu,
IconButton,
MD,
Skeleton,
Tooltip,
} from '@appquality/unguess-design-system';
import { ReactComponent as InsightsIcon } from '@zendeskgarden/svg-icons/src/16/lightbulb-stroke.svg';
+import { ReactComponent as ExternalLinkIcon } from '@zendeskgarden/svg-icons/src/16/new-window-stroke.svg';
+import { ReactComponent as DotsIcon } from '@zendeskgarden/svg-icons/src/16/overflow-vertical-stroke.svg';
import { ReactComponent as VideoListIcon } from '@zendeskgarden/svg-icons/src/16/play-circle-stroke.svg';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { Link } from 'react-router-dom';
+import { Link, useNavigate } from 'react-router-dom';
import { appTheme } from 'src/app/theme';
import { ReactComponent as EditRedoStroke } from 'src/assets/icons/move-icon.svg';
import { ReactComponent as InboxFill } from 'src/assets/icons/project-archive.svg';
@@ -23,6 +25,7 @@ import { FEATURE_FLAG_TAGGING_TOOL } from 'src/constants';
import {
CampaignWithOutput,
useGetCampaignsByCidMetaQuery,
+ useGetCampaignsByCidQuery,
} from 'src/features/api';
import { useActiveWorkspaceProjects } from 'src/hooks/useActiveWorkspaceProjects';
import { useCanAccessToActiveWorkspace } from 'src/hooks/useCanAccessToActiveWorkspace';
@@ -96,6 +99,7 @@ export const Metas = ({
const videoDashboardRoute = useLocalizeRoute(
`campaigns/${campaign.id}/videos`
);
+ const navigate = useNavigate();
const insightsRoute = useLocalizeRoute(`campaigns/${campaign.id}/insights`);
const hasWorkspaceAccess = useCanAccessToActiveWorkspace();
@@ -104,6 +108,10 @@ export const Metas = ({
isLoading,
isFetching,
} = useGetCampaignsByCidMetaQuery({ cid: campaign.id.toString() });
+ const { data: campaignData } = useGetCampaignsByCidQuery({
+ cid: campaign.id.toString(),
+ });
+ const plan = campaignData?.plan;
const {
sorted: videos,
isLoading: isLoadingVideos,
@@ -206,42 +214,50 @@ export const Metas = ({
!isLoadingProjects &&
!isFetchingProjects &&
!isArchived && (
- {
+ if (value === 'move_campaign') {
+ setIsMoveModalOpen(true);
+ } else if (value === 'archive_campaign') {
+ setIsArchiveModalOpen(true);
+ } else if (value === 'go_to_plan') {
+ navigate(`/plans/${plan}`);
+ }
}}
+ label={(props) => (
+
+
+
+ )}
>
-
-
-
-
+
+ {!!plan && (
+ <>
+
+ }
+ >
+ {t('__CAMPAIGN_PAGE_DOTS_MENU_GO_TO_PLAN_BUTTON')}
+
+ >
+ )}
+
)}
diff --git a/src/pages/Campaign/pageHeader/useCampaign.tsx b/src/pages/Campaign/pageHeader/useCampaign.tsx
index 70282c435..3094e39c8 100644
--- a/src/pages/Campaign/pageHeader/useCampaign.tsx
+++ b/src/pages/Campaign/pageHeader/useCampaign.tsx
@@ -1,12 +1,13 @@
-import { useAppSelector } from 'src/app/hooks';
import {
useGetCampaignsByCidQuery,
useGetProjectsByPidQuery,
+ useGetUsersMeQuery,
} from 'src/features/api';
import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute';
export const useCampaign = (campaignId: number) => {
- const { status: userStatus } = useAppSelector((state) => state.user);
+ const { isLoading: isUserLoading, isFetching: isUserFetching } =
+ useGetUsersMeQuery();
const {
isLoading: isCampaignLoading,
@@ -50,7 +51,7 @@ export const useCampaign = (campaignId: number) => {
return {
isLoading: false as const,
isError: false as const,
- isUserLoading: userStatus === 'idle' || userStatus === 'loading',
+ isUserLoading: isUserLoading || isUserFetching,
campaign,
project: {
...(campaign && { ...campaign.project, hasAccess: false }),
diff --git a/src/pages/Dashboard/CampaignItem.tsx b/src/pages/Dashboard/CampaignItem.tsx
index 1e6920e48..5978e7fdf 100644
--- a/src/pages/Dashboard/CampaignItem.tsx
+++ b/src/pages/Dashboard/CampaignItem.tsx
@@ -25,6 +25,7 @@ export const CampaignItem = ({
return (
{
isReadOnly
groups={groupesCampaigns}
columns={columns}
- style={{ backgroundColor: 'white' }}
+ style={{
+ backgroundColor: 'white',
+ wordBreak: 'break-word',
+ whiteSpace: 'normal',
+ }}
/>
);
};
diff --git a/src/pages/Dashboard/headerContent.tsx b/src/pages/Dashboard/headerContent.tsx
index d8fe37fc7..d16bc1697 100644
--- a/src/pages/Dashboard/headerContent.tsx
+++ b/src/pages/Dashboard/headerContent.tsx
@@ -1,10 +1,10 @@
import { Button, PageHeader } from '@appquality/unguess-design-system';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
-import { useAppSelector } from 'src/app/hooks';
import { appTheme } from 'src/app/theme';
import { LayoutWrapper } from 'src/common/components/LayoutWrapper';
import { PageTitle } from 'src/common/components/PageTitle';
+import { useGetUsersMeQuery } from 'src/features/api';
import { useCanAccessToActiveWorkspace } from 'src/hooks/useCanAccessToActiveWorkspace';
import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute';
import { Counters } from './Counters';
@@ -17,12 +17,14 @@ export const DashboardHeaderContent = ({
handleOpenModal: () => void;
}) => {
const { t } = useTranslation();
- const { status } = useAppSelector((state) => state.user);
+ const { isLoading: isUserLoading, isFetching: isUserFetching } =
+ useGetUsersMeQuery();
+
const hasWorksPacePermission = useCanAccessToActiveWorkspace();
const navigate = useNavigate();
const templatesRoute = useLocalizeRoute('templates');
- return status === 'idle' || status === 'loading' ? null : (
+ return isUserFetching || isUserLoading ? null : (
diff --git a/src/pages/Dashboard/index.tsx b/src/pages/Dashboard/index.tsx
index 89f2c655f..03943c440 100644
--- a/src/pages/Dashboard/index.tsx
+++ b/src/pages/Dashboard/index.tsx
@@ -1,8 +1,9 @@
import { Grid } from '@appquality/unguess-design-system';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { useAppDispatch, useAppSelector } from 'src/app/hooks';
+import { useAppDispatch } from 'src/app/hooks';
import { LayoutWrapper } from 'src/common/components/LayoutWrapper';
+import { useGetUsersMeQuery } from 'src/features/api';
import { resetFilters } from 'src/features/campaignsFilter/campaignsFilterSlice';
import { Page } from 'src/features/templates/Page';
import { useSendGTMevent } from 'src/hooks/useGTMevent';
@@ -16,10 +17,11 @@ import { SuggestedCampaigns } from './SuggestedCampaigns';
const Dashboard = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
- const status = useAppSelector((state) => state.user.status);
+ const { data: userData, isLoading, isFetching } = useGetUsersMeQuery();
+
const sendGTMEvent = useSendGTMevent();
- if (status === 'logged') dispatch(resetFilters()); // Reset filters
+ if (!isFetching && !isLoading && userData) dispatch(resetFilters()); // Reset filters
const [openCreateProjectModal, setOpenCreateProjectModal] = useState(false);
diff --git a/src/pages/Dashboard/project-items/table.tsx b/src/pages/Dashboard/project-items/table.tsx
index 780d57ac5..e1a35915a 100644
--- a/src/pages/Dashboard/project-items/table.tsx
+++ b/src/pages/Dashboard/project-items/table.tsx
@@ -34,7 +34,11 @@ export const TableList = ({
return (
diff --git a/src/pages/Dashboard/projectPageHeader.tsx b/src/pages/Dashboard/projectPageHeader.tsx
index 2c9ae041e..76256c8ce 100644
--- a/src/pages/Dashboard/projectPageHeader.tsx
+++ b/src/pages/Dashboard/projectPageHeader.tsx
@@ -10,11 +10,10 @@ import { ReactComponent as DeleteIcon } from '@zendeskgarden/svg-icons/src/16/tr
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate } from 'react-router-dom';
-import { useAppSelector } from 'src/app/hooks';
import { appTheme } from 'src/app/theme';
import { ProjectSettings } from 'src/common/components/inviteUsers/projectSettings';
import { LayoutWrapper } from 'src/common/components/LayoutWrapper';
-import { useGetProjectsByPidQuery } from 'src/features/api';
+import { useGetProjectsByPidQuery, useGetUsersMeQuery } from 'src/features/api';
import { useCanAccessToActiveWorkspace } from 'src/hooks/useCanAccessToActiveWorkspace';
import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute';
import styled from 'styled-components';
@@ -51,7 +50,9 @@ export const ProjectPageHeader = ({ projectId }: { projectId: number }) => {
const navigate = useNavigate();
const notFoundRoute = useLocalizeRoute('oops');
const location = useLocation();
- const { status } = useAppSelector((state) => state.user);
+ const { isLoading: isUserLoading, isFetching: isUserFetching } =
+ useGetUsersMeQuery();
+
const templatesRoute = useLocalizeRoute('templates');
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
@@ -97,7 +98,8 @@ export const ProjectPageHeader = ({ projectId }: { projectId: number }) => {
{isLoading ||
isLoadingPlans ||
isFetching ||
- status === 'loading' ? (
+ isUserLoading ||
+ isUserFetching ? (
) : (
titleContent
@@ -107,7 +109,8 @@ export const ProjectPageHeader = ({ projectId }: { projectId: number }) => {
{isLoading ||
isLoadingPlans ||
isFetching ||
- status === 'loading' ? (
+ isUserLoading ||
+ isUserFetching ? (
) : (
descriptionContent
diff --git a/src/pages/Insights/index.tsx b/src/pages/Insights/index.tsx
index 8e33c9424..b65240f86 100644
--- a/src/pages/Insights/index.tsx
+++ b/src/pages/Insights/index.tsx
@@ -3,7 +3,7 @@ import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { useGetCampaignWithWorkspaceQuery } from 'src/features/api/customEndpoints/getCampaignWithWorkspace';
import { Page } from 'src/features/templates/Page';
import { useLocalizeRoute } from 'src/hooks/useLocalizedRoute';
-import { useAppDispatch, useAppSelector } from 'src/app/hooks';
+import { useAppDispatch } from 'src/app/hooks';
import { useCampaignAnalytics } from 'src/hooks/useCampaignAnalytics';
import { useEffect } from 'react';
import {
@@ -12,6 +12,7 @@ import {
setWorkspace,
} from 'src/features/navigation/navigationSlice';
import { FEATURE_FLAG_TAGGING_TOOL } from 'src/constants';
+import { useGetUsersMeQuery } from 'src/features/api';
import { useFeatureFlag } from 'src/hooks/useFeatureFlag';
import InsightsPageContent from './Content';
import InsightsPageHeader from './PageHeader';
@@ -24,7 +25,12 @@ const InsightsPage = () => {
const { campaignId } = useParams();
const dispatch = useAppDispatch();
const location = useLocation();
- const { status } = useAppSelector((state) => state.user);
+ const {
+ isLoading: isUserLoading,
+ isFetching: isUserFetching,
+ data: userData,
+ } = useGetUsersMeQuery();
+
const { hasFeatureFlag } = useFeatureFlag();
const hasTaggingToolFeature = hasFeatureFlag(FEATURE_FLAG_TAGGING_TOOL);
@@ -67,14 +73,14 @@ const InsightsPage = () => {
}
useEffect(() => {
- if (status === 'idle' || status === 'loading') return;
+ if (isUserFetching || isUserLoading) return;
- if (!hasTaggingToolFeature && status === 'logged') {
+ if (!hasTaggingToolFeature && userData) {
navigate(notFoundRoute, {
state: { from: location.pathname },
});
}
- }, [status, hasTaggingToolFeature]);
+ }, [isUserFetching, isUserLoading, userData, hasTaggingToolFeature]);
return (
diff --git a/src/pages/JoinPage/Steps/Step1.tsx b/src/pages/JoinPage/Steps/Step1.tsx
index 50b43ec90..a1aea1a53 100644
--- a/src/pages/JoinPage/Steps/Step1.tsx
+++ b/src/pages/JoinPage/Steps/Step1.tsx
@@ -16,10 +16,10 @@ import { Field, FieldProps, useFormikContext } from 'formik';
import { useEffect, useState } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { appTheme } from 'src/app/theme';
+import { PasswordRequirements } from 'src/common/components/PasswordRequirements';
import { useSendGTMevent } from 'src/hooks/useGTMevent';
import { JoinFormValues } from '../valuesType';
import { ButtonContainer } from './ButtonContainer';
-import { PasswordRequirements } from './PasswordRequirements';
export const Step1 = () => {
const { setFieldValue, validateForm, setTouched, status, values } =
@@ -138,13 +138,13 @@ export const Step1 = () => {
title="Password"
end={
inputType === 'password' ? (
-
) : (
- {
);
}}
-
+