From a07c857149de6ef41d4812f4b80c9681773c1fc7 Mon Sep 17 00:00:00 2001
From: Edouard Lefebvre <1556109+edlefebvre@users.noreply.github.com>
Date: Mon, 27 Mar 2023 15:59:28 +0200
Subject: [PATCH 1/6] translation(core admin): add some missing fr translations
---
.../core/admin/admin/src/translations/fr.json | 90 ++++++++++++++++++-
1 file changed, 89 insertions(+), 1 deletion(-)
diff --git a/packages/core/admin/admin/src/translations/fr.json b/packages/core/admin/admin/src/translations/fr.json
index 9224b22609..2940a51009 100644
--- a/packages/core/admin/admin/src/translations/fr.json
+++ b/packages/core/admin/admin/src/translations/fr.json
@@ -3,6 +3,7 @@
"Auth.components.Oops.text": "Votre compte a été suspendu.",
"Auth.components.Oops.text.admin": "Si c'est une erreur, veuillez contacter votre administrateur.",
"Auth.components.Oops.title": "Oups !",
+ "Auth.form.active.label": "Actif",
"Auth.form.button.forgot-password": "Envoyer à nouveau",
"Auth.form.button.go-home": "Retour à l'accueil",
"Auth.form.button.login": "Se connecter",
@@ -54,6 +55,7 @@
"Auth.login.sso.subtitle": "Vous connecter via SSO",
"Auth.privacy-policy-agreement.policy": "la politique de confidentialité",
"Auth.privacy-policy-agreement.terms": "termes",
+ "Auth.reset-password.title": "Réinitialiser le mot de passe",
"Content Manager": "Content Manager",
"Content Type Builder": "Content Types Builder",
"Documentation": "Documentation",
@@ -74,22 +76,95 @@
"Roles.ListPage.notification.delete-all-not-allowed": "Certains rôles n'ont pas pu être supprimés car ils sont associés à des utilisateurs.",
"Roles.ListPage.notification.delete-not-allowed": "Un rôle ne peu pas être supprimé s'il est associé à des utilisateurs.",
"Roles.RoleRow.select-all": "Sélectionner {name} pour action groupée",
+ "Roles.RoleRow.user-count": "{number, plural, =0 {# utilisateur} one {# utilisateur} other {# utilisateurs}}",
"Roles.components.List.empty.withSearch": "Il n'y a pas de rôles correspondant à la recherche ({search})...",
"Settings.PageTitle": "Réglages - {name}",
+ "Settings.apiTokens.ListView.headers.createdAt": "Créé le",
+ "Settings.apiTokens.ListView.headers.description": "Description",
+ "Settings.apiTokens.ListView.headers.lastUsedAt": "Dernière utilisation le",
+ "Settings.apiTokens.ListView.headers.name": "Nom",
+ "Settings.apiTokens.ListView.headers.type": "Type de jeton",
+ "Settings.apiTokens.regenerate": "Régénérer",
+ "Settings.apiTokens.createPage.title": "Créer un jeton d'API",
+ "Settings.transferTokens.createPage.title": "Créer un jeton de transfert",
+ "Settings.tokens.RegenerateDialog.title": "Régénérer le jeton",
"Settings.apiTokens.addFirstToken": "Ajouter votre premier jeton d'API",
"Settings.apiTokens.addNewToken": "Ajouter un nouveau jeton d'API",
"Settings.tokens.copy.editMessage": "Pour des raisons de sécurité, vous ne pouvoir voir votre jeton qu'une seule fois",
"Settings.tokens.copy.editTitle": "Ce jeton n'est désormais plus accessible",
"Settings.tokens.copy.lastWarning": "Assurez-vous de copier ce jeton, vous ne pourrez plus le revoir par la suite !",
"Settings.apiTokens.create": "Ajouter une entrée",
+ "Settings.apiTokens.createPage.permissions.description": "Seules les actions rattachées à une route sont listées ci-dessous.",
+ "Settings.apiTokens.createPage.permissions.title": "Permissions",
"Settings.apiTokens.description": "Liste des jetons générés pour consommer l'API",
+ "Settings.apiTokens.createPage.BoundRoute.title": "Route rattachée à",
+ "Settings.apiTokens.createPage.permissions.header.title": "Paramètres avancés",
+ "Settings.apiTokens.createPage.permissions.header.hint": "Sélectionner les actions de l'application ou du plugin et sur l'icône de la roue crantée pour afficher la route rattachée",
+ "Settings.tokens.duration.30-days": "30 jours",
+ "Settings.tokens.duration.7-days": "7 jours",
+ "Settings.tokens.duration.90-days": "90 jours",
+ "Settings.tokens.duration.expiration-date": "Date d'expiration",
+ "Settings.tokens.duration.unlimited": "Illimité",
"Settings.apiTokens.emptyStateLayout": "Vous n'avez pas encore de contenu...",
+ "Settings.tokens.form.duration": "Durée de vie du jeton",
+ "Settings.tokens.form.type": "Type de jeton",
+ "Settings.tokens.form.name": "Nom",
+ "Settings.tokens.form.description": "Description",
"Settings.tokens.notification.copied": "Jeton copié dans le press-papiers.",
- "Settings.apiTokens.title": "Jetons d'API",
+ "Settings.tokens.popUpWarning.message": "Êtes-vous sûr(e) de vouloir régénérer ce jeton ?",
+ "Settings.tokens.Button.cancel": "Annuler",
+ "Settings.tokens.Button.regenerate": "Régénérer",
"Settings.tokens.types.full-access": "Accès total",
"Settings.tokens.types.read-only": "Lecture seule",
+ "Settings.tokens.types.custom": "Custom",
+ "Settings.tokens.regenerate": "Régénérer",
+ "Settings.transferTokens.title": "Jetons de transfert",
+ "Settings.transferTokens.description": "Liste des jetons de transfert générés",
+ "Settings.transferTokens.create": "Créer un nouveau jeton de transfert",
+ "Settings.transferTokens.addFirstToken": "Ajouter votre premier jeton de transfert",
+ "Settings.transferTokens.addNewToken": "Ajouter un nouveau jeton de transfert",
+ "Settings.transferTokens.emptyStateLayout": "Vous n'avez aucun contenu pour le moment...",
+ "Settings.tokens.ListView.headers.name": "Nom",
+ "Settings.tokens.ListView.headers.description": "Description",
+ "Settings.transferTokens.ListView.headers.type": "Type de jeton",
+ "Settings.tokens.ListView.headers.createdAt": "Créé le",
+ "Settings.tokens.ListView.headers.lastUsedAt": "Dernière utilisation",
+ "Settings.application.ee.admin-seats.count": "{enforcementUserCount}/{permittedSeats}",
+ "Settings.application.ee.admin-seats.at-limit-tooltip": "Limite atteinte : ajouter des places pour inviter d'autres utilisateurs",
+ "Settings.application.ee.admin-seats.add-seats": "{isHostedOnStrapiCloud, select, true {AJouter des places} other {Contacter le service clients}}",
+ "Settings.application.customization": "Customisation",
+ "Settings.application.customization.auth-logo.carousel-hint": "Remplacer le logo dans la page de connexion",
+ "Settings.application.customization.carousel-hint": "Changer le logo dans l'interface d'administration (dimensions maximales: {dimension}x{dimension}, poids maximal du fichier : {size}KB)",
+ "Settings.application.customization.carousel-slide.label": "Logo slide",
+ "Settings.application.customization.carousel.auth-logo.title": "Logo de connexion",
+ "Settings.application.customization.carousel.change-action": "Changer le logo",
+ "Settings.application.customization.carousel.menu-logo.title": "Logo du menu",
+ "Settings.application.customization.carousel.reset-action": "Réinitialiser le logo",
+ "Settings.application.customization.carousel.title": "Logo",
+ "Settings.application.customization.menu-logo.carousel-hint": "Remplacer le logo dans la navigation principale",
+ "Settings.application.customization.modal.cancel": "Annuler",
+ "Settings.application.customization.modal.pending": "Téléchargement du logo",
+ "Settings.application.customization.modal.pending.card-badge": "image",
+ "Settings.application.customization.modal.pending.choose-another": "Choisir un autre logo",
+ "Settings.application.customization.modal.pending.subtitle": "Gérer le logo choisi avant de le télécharger",
+ "Settings.application.customization.modal.pending.title": "Logo prêt pour le téléchargement",
+ "Settings.application.customization.modal.pending.upload": "Téléchargement du logo",
+ "Settings.application.customization.modal.tab.label": "Comment voulez-vous télécharger vos medias ?",
+ "Settings.application.customization.modal.upload": "Télécharger le logo",
+ "Settings.application.customization.modal.upload.cta.browse": "Explorer les fichiers",
+ "Settings.application.customization.modal.upload.drag-drop": "Glisser-déposer ici ou",
+ "Settings.application.customization.modal.upload.error-format": "Mauvais format chargé (formats acceptés : jpeg, jpg, png, svg).",
+ "Settings.application.customization.modal.upload.error-network": "Erreur réseau",
+ "Settings.application.customization.modal.upload.error-size": "Le fichier téléchargé est trop grand (dimensions max : {dimension}x{dimension}, poids max: {size}KB)",
+ "Settings.application.customization.modal.upload.file-validation": "Dimensions maximales : {dimension}x{dimension}, poids maximal : {size}KB",
+ "Settings.application.customization.modal.upload.from-computer": "Depuis l'ordinateur",
+ "Settings.application.customization.modal.upload.from-url": "Depuis une URL",
+ "Settings.application.customization.modal.upload.from-url.input-label": "URL",
+ "Settings.application.customization.modal.upload.next": "Suivant",
+ "Settings.application.customization.size-details": "Dimensions maximales : {dimension}×{dimension}, poids maximal : {size}KB",
"Settings.application.description": "Informations globales du panneau d'administration",
"Settings.application.edition-title": "plan actuel",
+ "Settings.application.ee-or-ce": "{communityEdition, select, true {Édition Communauté} other {Édition Entreprise}}",
"Settings.application.get-help": "Obtenir de l'aide",
"Settings.application.link-pricing": "Voir tous les tarifs",
"Settings.application.link-upgrade": "Mettez à niveau votre panneau d'administration",
@@ -566,6 +641,14 @@
"content-manager.plugin.description.long": "Visualisez, modifiez et supprimez les données de votre base de données.",
"content-manager.plugin.description.short": "Visualisez, modifiez et supprimez les données de votre base de données.",
"content-manager.popover.display-relations.label": "Afficher les relations",
+ "content-manager.relation.add": "Ajouter une relation",
+ "content-manager.relation.disconnect": "Supprimer",
+ "content-manager.relation.isLoading": "Chargement des relations en cours",
+ "content-manager.relation.loadMore": "Charger davantage",
+ "content-manager.relation.notAvailable": "Aucune relation disponible",
+ "content-manager.relation.publicationState.draft": "Brouillon",
+ "content-manager.relation.publicationState.published": "Publiée",
+ "content-manager.select.currently.selected": "{count} actuellement sélectionnées",
"content-manager.success.record.delete": "Supprimé",
"content-manager.success.record.publish": "Publié",
"content-manager.success.record.save": "Sauvegardé",
@@ -575,9 +658,11 @@
"content-manager.popUpWarning.warning.publish-question": "Êtes-vous sûr de vouloir le publier ?",
"content-manager.popUpwarning.warning.has-draft-relations.button-confirm": "Oui, publier",
"content-manager.popUpwarning.warning.has-draft-relations.message": "{count, plural, =0 { des relations de votre contenu n'est} one { des relations de votre contenu n'est} other { des relations de votre contenu ne sont}} pas publié actuellement.
Cela peut engendrer des liens cassés ou des erreurs dans votre projet.",
+ "dark": "Sombre",
"form.button.continue": "Continuer",
"global.search": "Rechercher",
"global.actions": "Actions",
+ "global.auditLogs": "Journaux d'audit",
"global.back": "Retour",
"global.cancel": "Annuler",
"global.change-password": "Modifier le mot de passe",
@@ -606,6 +691,7 @@
"global.settings": "Paramètres",
"global.type": "Type",
"global.users": "Utilisateurs",
+ "light": "Clair",
"form.button.done": "Terminer",
"global.prompt.unsaved": "Êtes-vous sûr de vouloir quitter cette page? Toutes vos modifications seront perdues",
"notification.contentType.relations.conflict": "Le Type de Contenu à des relations qui rentrent en conflit",
@@ -621,8 +707,10 @@
"notification.success.title": "Succès :",
"notification.version.update.message": "Une nouvelle version de Strapi est disponible !",
"notification.warning.title": "Attention :",
+ "notification.warning.404": "404 - Introuvable",
"or": "OU",
"request.error.model.unknown": "Le model n'existe pas",
+ "selectButtonTitle": "Sélectionner",
"skipToContent": "Aller au contenu",
"submit": "Soumettre"
}
From 52f5b7a16e02d8cd543e252b665a97d63f142f48 Mon Sep 17 00:00:00 2001
From: derrickmehaffy
Date: Mon, 17 Apr 2023 07:30:28 -0700
Subject: [PATCH 2/6] update blacklist with all system fields
---
.../plugins/users-permissions/server/controllers/auth.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/packages/plugins/users-permissions/server/controllers/auth.js b/packages/plugins/users-permissions/server/controllers/auth.js
index cb73abd6e8..2d455602c2 100644
--- a/packages/plugins/users-permissions/server/controllers/auth.js
+++ b/packages/plugins/users-permissions/server/controllers/auth.js
@@ -280,6 +280,11 @@ module.exports = {
'confirmationToken',
'resetPasswordToken',
'provider',
+ 'id',
+ 'createdAt',
+ 'updatedAt',
+ 'createdBy',
+ 'updatedBy',
]),
provider: 'local',
};
From 773db0dcaf2476a50a20fa59b9e6796b6cdca0be Mon Sep 17 00:00:00 2001
From: derrickmehaffy
Date: Mon, 17 Apr 2023 08:08:19 -0700
Subject: [PATCH 3/6] add role as a failsafe
---
packages/plugins/users-permissions/server/controllers/auth.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/plugins/users-permissions/server/controllers/auth.js b/packages/plugins/users-permissions/server/controllers/auth.js
index 2d455602c2..02821f7ba4 100644
--- a/packages/plugins/users-permissions/server/controllers/auth.js
+++ b/packages/plugins/users-permissions/server/controllers/auth.js
@@ -285,6 +285,7 @@ module.exports = {
'updatedAt',
'createdBy',
'updatedBy',
+ 'role',
]),
provider: 'local',
};
From a572f92b1e8943fcc99d14a561ef4514d7124a46 Mon Sep 17 00:00:00 2001
From: Josh <37798644+joshuaellis@users.noreply.github.com>
Date: Thu, 20 Apr 2023 17:12:32 +0100
Subject: [PATCH 4/6] fix: localstorage in fe tests
---
.../lib/mocks/LocalStorageMock.js | 24 ++++++++++++++-----
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/packages/admin-test-utils/lib/mocks/LocalStorageMock.js b/packages/admin-test-utils/lib/mocks/LocalStorageMock.js
index d516355392..701520ac77 100644
--- a/packages/admin-test-utils/lib/mocks/LocalStorageMock.js
+++ b/packages/admin-test-utils/lib/mocks/LocalStorageMock.js
@@ -2,24 +2,36 @@
class LocalStorageMock {
constructor() {
- this.store = {};
+ this.store = new Map();
}
clear() {
- this.store = {};
+ this.store.clear();
}
getItem(key) {
- return this.store[key] || null;
+ /**
+ * We return null to avoid returning `undefined`
+ * because `undefined` is not a valid JSON value.
+ */
+ return this.store.get(key) ?? null;
}
setItem(key, value) {
- this.store[key] = String(value);
+ this.store.set(key, String(value));
}
removeItem(key) {
- delete this.store[key];
+ this.store.delete(key);
+ }
+
+ get length() {
+ return this.store.size;
}
}
-global.localStorage = new LocalStorageMock();
+// eslint-disable-next-line no-undef
+Object.defineProperty(window, 'localStorage', {
+ writable: true,
+ value: new LocalStorageMock(),
+});
From 2d55462e466cc11f21ff6db74e6ccf9a33983bdb Mon Sep 17 00:00:00 2001
From: Josh <37798644+joshuaellis@users.noreply.github.com>
Date: Wed, 19 Apr 2023 20:27:47 +0100
Subject: [PATCH 5/6] fix: remove instances of request and ban with eslint
chore: remove straggler
chore: fix hook
chore: pr amends
chore: pr amends
chore: use axios for analytics
fix missing once function import
chore(test): use defineProperty
fix: webhooks creation
fix: sso
Revert "chore(test): use defineProperty"
This reverts commit dfdcb82ccef720c4e4993fe4021acc190f38a204.
chore: make sure theres a url before trying to render the image
fix: webhook
---
.../hooks/useFetchPermissionsLayout/index.js | 35 +++++---
.../admin/src/hooks/useFetchRole/index.js | 67 +++++++-------
.../admin/admin/src/hooks/useModels/index.js | 34 ++++---
.../admin/src/hooks/useSettingsForm/index.js | 20 +++--
.../core/admin/admin/src/pages/App/index.js | 43 ++++-----
.../LogoModalStepper/PendingLogoDialog.js | 4 +-
.../pages/Roles/CreatePage/index.js | 18 ++--
.../pages/Roles/EditPage/index.js | 16 ++--
.../pages/Webhooks/EditView/index.js | 51 ++++-------
.../pages/Webhooks/ListView/index.js | 88 +++++++++----------
.../ee/admin/hooks/useAuthProviders/index.js | 57 ++++++------
.../ee/admin/pages/AuthResponse/index.js | 10 ++-
.../src/utils/hasPermissions/index.js | 13 +--
packages/core/helper-plugin/src/utils/once.js | 20 +++++
.../helper-plugin/src/utils/request/index.js | 10 ++-
.../admin/src/pages/utils/api.js | 31 -------
.../admin/src/pages/utils/useReactQuery.js | 48 +++++++---
.../admin/src/hooks/useAddLocale/index.js | 31 +++----
.../src/hooks/useDefaultLocales/index.js | 37 ++++----
.../admin/src/hooks/useDeleteLocale/index.js | 47 +++++-----
.../admin/src/hooks/useEditLocale/index.js | 47 ++++------
.../i18n/admin/src/hooks/useLocales/index.js | 43 +++++----
.../addCommonFieldsToInitialDataMiddleware.js | 10 +--
.../SettingsPage/tests/SettingsPage.test.js | 59 ++++++-------
.../admin/src/hooks/useForm/index.js | 11 +--
.../admin/src/hooks/useRolesList/index.js | 37 ++++----
packages/utils/eslint-config-custom/front.js | 6 ++
27 files changed, 442 insertions(+), 451 deletions(-)
create mode 100644 packages/core/helper-plugin/src/utils/once.js
delete mode 100644 packages/plugins/documentation/admin/src/pages/utils/api.js
diff --git a/packages/core/admin/admin/src/hooks/useFetchPermissionsLayout/index.js b/packages/core/admin/admin/src/hooks/useFetchPermissionsLayout/index.js
index 36c61c63f6..e38f7fc9a0 100644
--- a/packages/core/admin/admin/src/hooks/useFetchPermissionsLayout/index.js
+++ b/packages/core/admin/admin/src/hooks/useFetchPermissionsLayout/index.js
@@ -1,30 +1,39 @@
import { useEffect, useReducer } from 'react';
-import { request } from '@strapi/helper-plugin';
+import { useFetchClient } from '@strapi/helper-plugin';
import reducer, { initialState } from './reducer';
+/**
+ * TODO: refactor this to use react-query and move it to the `Roles` SettingsPage
+ */
const useFetchPermissionsLayout = (id) => {
const [{ data, error, isLoading }, dispatch] = useReducer(reducer, initialState);
+ const { get } = useFetchClient();
useEffect(() => {
const getData = async () => {
- dispatch({
- type: 'GET_DATA',
- });
+ try {
+ dispatch({
+ type: 'GET_DATA',
+ });
- const { data } = await request('/admin/permissions', {
- method: 'GET',
- params: { role: id },
- });
+ const {
+ data: { data },
+ } = await get('/admin/permissions', {
+ params: { role: id },
+ });
- dispatch({
- type: 'GET_DATA_SUCCEEDED',
- data,
- });
+ dispatch({
+ type: 'GET_DATA_SUCCEEDED',
+ data,
+ });
+ } catch (err) {
+ // silence is golden
+ }
};
getData();
- }, [id]);
+ }, [id, get]);
return { data, error, isLoading };
};
diff --git a/packages/core/admin/admin/src/hooks/useFetchRole/index.js b/packages/core/admin/admin/src/hooks/useFetchRole/index.js
index 6d756c0c0e..633126ee66 100644
--- a/packages/core/admin/admin/src/hooks/useFetchRole/index.js
+++ b/packages/core/admin/admin/src/hooks/useFetchRole/index.js
@@ -1,13 +1,48 @@
import { useCallback, useReducer, useEffect } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import reducer, { initialState } from './reducer';
const useFetchRole = (id) => {
const toggleNotification = useNotification();
const [state, dispatch] = useReducer(reducer, initialState);
+ const { get } = useFetchClient();
+
useEffect(() => {
if (id) {
+ const fetchRole = async (roleId) => {
+ try {
+ const [
+ {
+ data: { data: role },
+ },
+ {
+ data: { data: permissions },
+ },
+ ] = await Promise.all(
+ [`roles/${roleId}`, `roles/${roleId}/permissions`].map((endPoint) =>
+ get(`/admin/${endPoint}`)
+ )
+ );
+
+ dispatch({
+ type: 'GET_DATA_SUCCEEDED',
+ role,
+ permissions,
+ });
+ } catch (err) {
+ console.error(err);
+
+ dispatch({
+ type: 'GET_DATA_ERROR',
+ });
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+ }
+ };
+
fetchRole(id);
} else {
dispatch({
@@ -16,35 +51,7 @@ const useFetchRole = (id) => {
permissions: [],
});
}
-
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [id]);
-
- const fetchRole = async (roleId) => {
- try {
- const [{ data: role }, { data: permissions }] = await Promise.all(
- [`roles/${roleId}`, `roles/${roleId}/permissions`].map((endPoint) =>
- request(`/admin/${endPoint}`, { method: 'GET' })
- )
- );
-
- dispatch({
- type: 'GET_DATA_SUCCEEDED',
- role,
- permissions,
- });
- } catch (err) {
- console.error(err);
-
- dispatch({
- type: 'GET_DATA_ERROR',
- });
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
- }
- };
+ }, [get, id, toggleNotification]);
const handleSubmitSucceeded = useCallback((data) => {
dispatch({
diff --git a/packages/core/admin/admin/src/hooks/useModels/index.js b/packages/core/admin/admin/src/hooks/useModels/index.js
index d3458c4c56..7d631ac661 100644
--- a/packages/core/admin/admin/src/hooks/useModels/index.js
+++ b/packages/core/admin/admin/src/hooks/useModels/index.js
@@ -1,26 +1,32 @@
-import { useReducer, useEffect } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useReducer, useEffect, useCallback } from 'react';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import reducer, { initialState } from './reducer';
+/**
+ * TODO: refactor this to not use the `useReducer` hook,
+ * it's not really necessary. Also use `useQuery`?
+ */
const useModels = () => {
const toggleNotification = useNotification();
const [state, dispatch] = useReducer(reducer, initialState);
- useEffect(() => {
- fetchModels();
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ const { get } = useFetchClient();
- const fetchModels = async () => {
+ const fetchModels = useCallback(async () => {
dispatch({
type: 'GET_MODELS',
});
try {
- const [{ data: components }, { data: contentTypes }] = await Promise.all(
- ['components', 'content-types'].map((endPoint) =>
- request(`/content-manager/${endPoint}`, { method: 'GET' })
- )
+ const [
+ {
+ data: { data: components },
+ },
+ {
+ data: { data: contentTypes },
+ },
+ ] = await Promise.all(
+ ['components', 'content-types'].map((endPoint) => get(`/content-manager/${endPoint}`))
);
dispatch({
@@ -37,7 +43,11 @@ const useModels = () => {
message: { id: 'notification.error' },
});
}
- };
+ }, [toggleNotification, get]);
+
+ useEffect(() => {
+ fetchModels();
+ }, [fetchModels]);
return {
...state,
diff --git a/packages/core/admin/admin/src/hooks/useSettingsForm/index.js b/packages/core/admin/admin/src/hooks/useSettingsForm/index.js
index beb0fc4e77..95345b3891 100644
--- a/packages/core/admin/admin/src/hooks/useSettingsForm/index.js
+++ b/packages/core/admin/admin/src/hooks/useSettingsForm/index.js
@@ -1,10 +1,15 @@
import { useEffect, useReducer } from 'react';
-import { request, useNotification, useOverlayBlocker } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification, useOverlayBlocker } from '@strapi/helper-plugin';
import omit from 'lodash/omit';
import { checkFormValidity, formatAPIErrors } from '../../utils';
import { initialState, reducer } from './reducer';
import init from './init';
+/**
+ * TODO: refactor this, it's confusing and hard to read.
+ * It's also only used in `Settings/pages/SingleSignOn` so it can
+ * probably be deleted and everything written there...
+ */
const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
const [
{ formErrors, initialData, isLoading, modifiedData, showHeaderButtonLoader, showHeaderLoader },
@@ -13,10 +18,14 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
const toggleNotification = useNotification();
const { lockApp, unlockApp } = useOverlayBlocker();
+ const { get, put } = useFetchClient();
+
useEffect(() => {
const getData = async () => {
try {
- const { data } = await request(endPoint, { method: 'GET' });
+ const {
+ data: { data },
+ } = await get(endPoint);
dispatch({
type: 'GET_DATA_SUCCEEDED',
@@ -85,10 +94,9 @@ const useSettingsForm = (endPoint, schema, cbSuccess, fieldsToPick) => {
cleanedData.roles = cleanedData.roles.map((role) => role.id);
}
- const { data } = await request(endPoint, {
- method: 'PUT',
- body: cleanedData,
- });
+ const {
+ data: { data },
+ } = await put(endPoint, cleanedData);
cbSuccess(data);
diff --git a/packages/core/admin/admin/src/pages/App/index.js b/packages/core/admin/admin/src/pages/App/index.js
index ddd9e993e2..08cba52e3d 100644
--- a/packages/core/admin/admin/src/pages/App/index.js
+++ b/packages/core/admin/admin/src/pages/App/index.js
@@ -6,17 +6,16 @@
import React, { useEffect, useState, useMemo, lazy, Suspense } from 'react';
import { Switch, Route } from 'react-router-dom';
+import axios from 'axios';
import {
LoadingIndicatorPage,
auth,
- request,
useNotification,
TrackingProvider,
prefixFileUrlWithBackendUrl,
useAppInfos,
useFetchClient,
} from '@strapi/helper-plugin';
-import axios from 'axios';
import { SkipToContent } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import PrivateRoute from '../../components/PrivateRoute';
@@ -41,7 +40,7 @@ function App() {
hasAdmin: false,
});
const appInfo = useAppInfos();
- const { get } = useFetchClient();
+ const { get, post } = useFetchClient();
const authRoutes = useMemo(() => {
return makeUniqueRoutes(
@@ -57,11 +56,10 @@ function App() {
const renewToken = async () => {
try {
const {
- data: { token },
- } = await request('/admin/renew-token', {
- method: 'POST',
- body: { token: currentToken },
- });
+ data: {
+ data: { token },
+ },
+ } = await post('/admin/renew-token', { token: currentToken });
auth.updateToken(token);
} catch (err) {
// Refresh app
@@ -73,7 +71,7 @@ function App() {
if (currentToken) {
renewToken();
}
- }, []);
+ }, [post]);
useEffect(() => {
const getData = async () => {
@@ -82,7 +80,7 @@ function App() {
data: {
data: { hasAdmin, uuid, menuLogo, authLogo },
},
- } = await axios.get(`${strapi.backendURL}/admin/init`);
+ } = await get(`/admin/init`);
updateProjectSettings({
menuLogo: prefixFileUrlWithBackendUrl(menuLogo),
@@ -102,20 +100,17 @@ function App() {
setTelemetryProperties(properties);
try {
- await fetch('https://analytics.strapi.io/api/v2/track', {
- method: 'POST',
- body: JSON.stringify({
- // This event is anonymous
- event: 'didInitializeAdministration',
- userId: '',
- deviceId,
- eventPropeties: {},
- userProperties: { environment: appInfo.currentEnvironment },
- groupProperties: { ...properties, projectId: uuid },
- }),
- headers: {
- 'Content-Type': 'application/json',
- },
+ /**
+ * TODO: remove this call to `axios`
+ */
+ await axios.post('https://analytics.strapi.io/api/v2/track', {
+ // This event is anonymous
+ event: 'didInitializeAdministration',
+ userId: '',
+ deviceId,
+ eventPropeties: {},
+ userProperties: { environment: appInfo.currentEnvironment },
+ groupProperties: { ...properties, projectId: uuid },
});
} catch (e) {
// Silent.
diff --git a/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js b/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js
index f9ef1de9d0..0b11708d5b 100644
--- a/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js
+++ b/packages/core/admin/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js
@@ -43,9 +43,7 @@ const PendingLogoDialog = ({ onClose, asset, prev, next, goTo, setLocalImage, on
})}
-
-
-
+ {asset.url ? : null}
{
const { isLoading: isLayoutLoading, data: permissionsLayout } = useFetchPermissionsLayout();
const { permissions: rolePermissions, isLoading: isRoleLoading } = useFetchRole(id);
+ const { post, put } = useFetchClient();
+
const handleCreateRoleSubmit = (data) => {
lockApp();
setIsSubmiting(true);
@@ -69,13 +71,8 @@ const CreatePage = () => {
trackUsage('willCreateNewRole');
}
- Promise.resolve(
- request('/admin/roles', {
- method: 'POST',
- body: data,
- })
- )
- .then(async (res) => {
+ Promise.resolve(post('/admin/roles', data))
+ .then(async ({ data: res }) => {
const { permissionsToSend } = permissionsRef.current.getPermissions();
if (id) {
@@ -85,10 +82,7 @@ const CreatePage = () => {
}
if (res.data.id && !isEmpty(permissionsToSend)) {
- await request(`/admin/roles/${res.data.id}/permissions`, {
- method: 'PUT',
- body: { permissions: permissionsToSend },
- });
+ await put(`/admin/roles/${res.data.id}/permissions`, { permissions: permissionsToSend });
}
return res;
diff --git a/packages/core/admin/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js b/packages/core/admin/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js
index 89f74ef9bf..8ba6a28e6f 100644
--- a/packages/core/admin/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js
+++ b/packages/core/admin/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js
@@ -1,6 +1,6 @@
import React, { useRef, useState } from 'react';
import {
- request,
+ useFetchClient,
useNotification,
useOverlayBlocker,
useTracking,
@@ -37,6 +37,8 @@ const EditPage = () => {
onSubmitSucceeded,
} = useFetchRole(id);
+ const { put } = useFetchClient();
+
const handleEditRoleSubmit = async (data) => {
try {
lockApp();
@@ -44,17 +46,11 @@ const EditPage = () => {
const { permissionsToSend, didUpdateConditions } = permissionsRef.current.getPermissions();
- await request(`/admin/roles/${id}`, {
- method: 'PUT',
- body: data,
- });
+ await put(`/admin/roles/${id}`, data);
if (role.code !== 'strapi-super-admin') {
- await request(`/admin/roles/${id}/permissions`, {
- method: 'PUT',
- body: {
- permissions: permissionsToSend,
- },
+ await put(`/admin/roles/${id}/permissions`, {
+ permissions: permissionsToSend,
});
if (didUpdateConditions) {
diff --git a/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js b/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js
index 07ec03510e..0153c6a883 100644
--- a/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js
+++ b/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js
@@ -3,12 +3,10 @@
* EditView
*
*/
-import React, { useCallback, useMemo } from 'react';
+import * as React from 'react';
import {
LoadingIndicatorPage,
- request,
SettingsPageTitle,
- to,
useNotification,
useOverlayBlocker,
useFetchClient,
@@ -30,19 +28,20 @@ const EditView = () => {
const toggleNotification = useNotification();
const queryClient = useQueryClient();
const { isLoading: isLoadingForModels, collectionTypes } = useModels();
- const { post } = useFetchClient();
+ const { put, get, post } = useFetchClient();
const isCreating = id === 'create';
- const fetchWebhook = useCallback(
- async (id) => {
- const [err, { data }] = await to(
- request(`/admin/webhooks/${id}`, {
- method: 'GET',
- })
- );
+ const { isLoading, data } = useQuery(
+ ['get-webhook', id],
+ async () => {
+ try {
+ const {
+ data: { data },
+ } = await get(`/admin/webhooks/${id}`);
- if (err) {
+ return data;
+ } catch (err) {
toggleNotification({
type: 'warning',
message: { id: 'notification.error' },
@@ -50,16 +49,12 @@ const EditView = () => {
return null;
}
-
- return data;
},
- [toggleNotification]
+ {
+ enabled: !isCreating,
+ }
);
- const { isLoading, data } = useQuery(['get-webhook', id], () => fetchWebhook(id), {
- enabled: !isCreating,
- });
-
const {
isLoading: isTriggering,
data: triggerResponse,
@@ -77,25 +72,15 @@ const EditView = () => {
},
});
- const createWebhookMutation = useMutation((body) =>
- request('/admin/webhooks', {
- method: 'POST',
- body,
- })
- );
+ const createWebhookMutation = useMutation((body) => post('/admin/webhooks', body));
- const updateWebhookMutation = useMutation(({ id, body }) =>
- request(`/admin/webhooks/${id}`, {
- method: 'PUT',
- body,
- })
- );
+ const updateWebhookMutation = useMutation(({ id, body }) => put(`/admin/webhooks/${id}`, body));
const handleSubmit = async (data) => {
if (isCreating) {
lockApp();
createWebhookMutation.mutate(cleanData(data), {
- onSuccess(result) {
+ onSuccess({ data: result }) {
toggleNotification({
type: 'success',
message: { id: 'Settings.webhooks.created' },
@@ -138,7 +123,7 @@ const EditView = () => {
}
};
- const isDraftAndPublishEvents = useMemo(
+ const isDraftAndPublishEvents = React.useMemo(
() => collectionTypes.some((ct) => ct.options.draftAndPublish === true),
[collectionTypes]
);
diff --git a/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js b/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js
index 4d1d391eb1..f4eedd593e 100644
--- a/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js
+++ b/packages/core/admin/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js
@@ -9,7 +9,7 @@ import React, { useEffect, useReducer, useRef, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { useIntl } from 'react-intl';
import {
- request,
+ useFetchClient,
useRBAC,
LoadingIndicatorPage,
useNotification,
@@ -63,6 +63,8 @@ const ListView = () => {
);
const { notifyStatus } = useNotifyAT();
+ const { get, del, post, put } = useFetchClient();
+
useFocusWhenNavigate();
const { push } = useHistory();
const { pathname } = useLocation();
@@ -78,42 +80,45 @@ const ListView = () => {
};
}, []);
+ /**
+ * TODO: refactor this, but actually refactor
+ * the whole component. Needs some love.
+ */
useEffect(() => {
+ const fetchWebHooks = async () => {
+ try {
+ const {
+ data: { data },
+ } = await get('/admin/webhooks');
+
+ if (isMounted.current) {
+ dispatch({
+ type: 'GET_DATA_SUCCEEDED',
+ data,
+ });
+ notifyStatus('webhooks have been loaded');
+ }
+ } catch (err) {
+ console.log(err);
+
+ if (isMounted.current) {
+ if (err.code !== 20) {
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+ }
+ dispatch({
+ type: 'TOGGLE_LOADING',
+ });
+ }
+ }
+ };
+
if (canRead) {
fetchWebHooks();
}
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [canRead]);
-
- const fetchWebHooks = async () => {
- try {
- const { data } = await request('/admin/webhooks', {
- method: 'GET',
- });
-
- if (isMounted.current) {
- dispatch({
- type: 'GET_DATA_SUCCEEDED',
- data,
- });
- notifyStatus('webhooks have been loaded');
- }
- } catch (err) {
- console.log(err);
-
- if (isMounted.current) {
- if (err.code !== 20) {
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
- }
- dispatch({
- type: 'TOGGLE_LOADING',
- });
- }
- }
- };
+ }, [canRead, get, notifyStatus, toggleNotification]);
const handleToggleModal = () => {
setShowModal((prev) => !prev);
@@ -129,15 +134,16 @@ const ListView = () => {
const handleConfirmDeleteOne = async () => {
try {
- await request(`/admin/webhooks/${webhookToDelete}`, {
- method: 'DELETE',
- });
+ await del(`/admin/webhooks/${webhookToDelete}`);
dispatch({
type: 'WEBHOOK_DELETED',
index: getWebhookIndex(webhookToDelete),
});
} catch (err) {
+ /**
+ * TODO: especially this.
+ */
if (err.code !== 20) {
toggleNotification({
type: 'warning',
@@ -154,10 +160,7 @@ const ListView = () => {
};
try {
- await request('/admin/webhooks/batch-delete', {
- method: 'POST',
- body,
- });
+ await post('/admin/webhooks/batch-delete', body);
if (isMounted.current) {
dispatch({
@@ -207,10 +210,7 @@ const ListView = () => {
value,
});
- await request(`/admin/webhooks/${id}`, {
- method: 'PUT',
- body,
- });
+ await put(`/admin/webhooks/${id}`, body);
} catch (err) {
if (isMounted.current) {
dispatch({
diff --git a/packages/core/admin/ee/admin/hooks/useAuthProviders/index.js b/packages/core/admin/ee/admin/hooks/useAuthProviders/index.js
index f31b0ad9a6..b1396773a2 100644
--- a/packages/core/admin/ee/admin/hooks/useAuthProviders/index.js
+++ b/packages/core/admin/ee/admin/hooks/useAuthProviders/index.js
@@ -1,5 +1,5 @@
import { useReducer, useEffect } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import { getRequestUrl } from '../../../../admin/src/utils';
import reducer, { initialState } from './reducer';
@@ -7,43 +7,42 @@ import reducer, { initialState } from './reducer';
const useAuthProviders = ({ ssoEnabled }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const toggleNotification = useNotification();
+ const { get } = useFetchClient();
useEffect(() => {
- fetchAuthProviders();
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
+ const fetchAuthProviders = async () => {
+ try {
+ if (!ssoEnabled) {
+ dispatch({
+ type: 'GET_DATA_SUCCEEDED',
+ data: [],
+ });
+
+ return;
+ }
+
+ const { data } = await get(getRequestUrl('providers'));
- const fetchAuthProviders = async () => {
- try {
- if (!ssoEnabled) {
dispatch({
type: 'GET_DATA_SUCCEEDED',
- data: [],
+ data,
+ });
+ } catch (err) {
+ console.error(err);
+
+ dispatch({
+ type: 'GET_DATA_ERROR',
});
- return;
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
}
+ };
- const requestUrl = getRequestUrl('providers');
- const data = await request(requestUrl, { method: 'GET' });
-
- dispatch({
- type: 'GET_DATA_SUCCEEDED',
- data,
- });
- } catch (err) {
- console.error(err);
-
- dispatch({
- type: 'GET_DATA_ERROR',
- });
-
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
- }
- };
+ fetchAuthProviders();
+ }, [get, ssoEnabled, toggleNotification]);
return state;
};
diff --git a/packages/core/admin/ee/admin/pages/AuthResponse/index.js b/packages/core/admin/ee/admin/pages/AuthResponse/index.js
index 024abd3934..dc1b8a7108 100644
--- a/packages/core/admin/ee/admin/pages/AuthResponse/index.js
+++ b/packages/core/admin/ee/admin/pages/AuthResponse/index.js
@@ -2,7 +2,7 @@ import React, { useEffect, useRef, useCallback } from 'react';
import { useHistory, useRouteMatch } from 'react-router-dom';
import { useIntl } from 'react-intl';
import Cookies from 'js-cookie';
-import { auth, LoadingIndicatorPage, request } from '@strapi/helper-plugin';
+import { auth, LoadingIndicatorPage, useFetchClient } from '@strapi/helper-plugin';
import { getRequestUrl } from '../../../../admin/src/utils';
const AuthResponse = () => {
@@ -24,6 +24,8 @@ const AuthResponse = () => {
);
}, [push]);
+ const { get } = useFetchClient();
+
const fetchUserInfo = useCallback(async () => {
try {
const jwtToken = Cookies.get('jwtToken');
@@ -33,7 +35,9 @@ const AuthResponse = () => {
if (jwtToken) {
auth.setToken(jwtToken, true);
const requestUrl = getRequestUrl('users/me');
- const { data } = await request(requestUrl, { method: 'GET' });
+ const {
+ data: { data },
+ } = await get(requestUrl);
auth.setUserInfo(data, true);
@@ -44,7 +48,7 @@ const AuthResponse = () => {
} catch (e) {
redirectToOops();
}
- }, [push, redirectToOops]);
+ }, [get, push, redirectToOops]);
useEffect(() => {
if (authResponse === 'error') {
diff --git a/packages/core/helper-plugin/src/utils/hasPermissions/index.js b/packages/core/helper-plugin/src/utils/hasPermissions/index.js
index 080bd208a2..64dd60dfc7 100644
--- a/packages/core/helper-plugin/src/utils/hasPermissions/index.js
+++ b/packages/core/helper-plugin/src/utils/hasPermissions/index.js
@@ -3,6 +3,7 @@ import pickBy from 'lodash/pickBy';
import transform from 'lodash/transform';
import request from '../request';
+import getFetchClient from '../getFetchClient';
const findMatchingPermissions = (userPermissions, permissions) => {
return transform(
@@ -47,13 +48,15 @@ const hasPermissions = async (userPermissions, permissions, signal) => {
let hasPermission = false;
try {
- const { data } = await request('/admin/permissions/check', {
- method: 'POST',
- body: {
+ const {
+ data: { data },
+ } = await getFetchClient().post(
+ '/admin/permissions/check',
+ {
permissions: formatPermissionsForRequest(matchingPermissions),
},
- signal,
- });
+ { signal }
+ );
hasPermission = data.every((v) => v === true);
} catch (err) {
diff --git a/packages/core/helper-plugin/src/utils/once.js b/packages/core/helper-plugin/src/utils/once.js
new file mode 100644
index 0000000000..87d2a99010
--- /dev/null
+++ b/packages/core/helper-plugin/src/utils/once.js
@@ -0,0 +1,20 @@
+export const PREFIX = '[@strapi/helper-plugin]:';
+
+/**
+ * @type { any>(fn: TFunc) => (...args: any[]) => void}
+ */
+export const once = (fn) => {
+ const func = fn;
+ let called = false;
+
+ if (typeof func !== 'function') {
+ throw new TypeError(`${PREFIX} once requires a function parameter`);
+ }
+
+ return (...args) => {
+ if (!called) {
+ func(...args);
+ called = true;
+ }
+ };
+};
diff --git a/packages/core/helper-plugin/src/utils/request/index.js b/packages/core/helper-plugin/src/utils/request/index.js
index 40da1525e7..395101a711 100644
--- a/packages/core/helper-plugin/src/utils/request/index.js
+++ b/packages/core/helper-plugin/src/utils/request/index.js
@@ -1,6 +1,6 @@
import startsWith from 'lodash/startsWith';
import auth from '../auth';
-
+import { once } from '../once';
/**
* Parses the JSON returned by a network request
*
@@ -89,9 +89,13 @@ function serverRestartWatcher(response) {
});
}
+const warnOnce = once(console.warn);
+
/**
* Requests a URL, returning a promise
*
+ * @deprecated use `useFetchClient` instead.
+ *
* @param {string} url The URL we want to request
* @param {object} [options] The options we want to pass to "fetch"
*
@@ -101,6 +105,10 @@ export default function request(...args) {
let [url, options = {}, shouldWatchServerRestart, stringify = true, ...rest] = args;
let noAuth;
+ warnOnce(
+ 'The `request` function is deprecated and will be removed in the next major version. Please use `useFetchClient` instead.'
+ );
+
try {
[{ noAuth }] = rest;
} catch (err) {
diff --git a/packages/plugins/documentation/admin/src/pages/utils/api.js b/packages/plugins/documentation/admin/src/pages/utils/api.js
deleted file mode 100644
index ab4d3b9e7d..0000000000
--- a/packages/plugins/documentation/admin/src/pages/utils/api.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { request } from '@strapi/helper-plugin';
-import pluginId from '../../pluginId';
-
-const deleteDoc = ({ prefix, version }) => {
- return request(`${prefix}/deleteDoc/${version}`, { method: 'DELETE' });
-};
-
-const fetchDocumentationVersions = async (toggleNotification) => {
- try {
- const data = await request(`/${pluginId}/getInfos`, { method: 'GET' });
-
- return data;
- } catch (err) {
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
-
- // FIXME
- return null;
- }
-};
-
-const regenerateDoc = ({ prefix, version }) => {
- return request(`${prefix}/regenerateDoc`, { method: 'POST', body: { version } });
-};
-
-const updateSettings = ({ prefix, body }) =>
- request(`${prefix}/updateSettings`, { method: 'PUT', body });
-
-export { deleteDoc, fetchDocumentationVersions, regenerateDoc, updateSettings };
diff --git a/packages/plugins/documentation/admin/src/pages/utils/useReactQuery.js b/packages/plugins/documentation/admin/src/pages/utils/useReactQuery.js
index 79c5f525b6..430eb618a1 100644
--- a/packages/plugins/documentation/admin/src/pages/utils/useReactQuery.js
+++ b/packages/plugins/documentation/admin/src/pages/utils/useReactQuery.js
@@ -1,14 +1,28 @@
import { useQuery, useMutation, useQueryClient } from 'react-query';
-import { useNotification } from '@strapi/helper-plugin';
-import { fetchDocumentationVersions, deleteDoc, regenerateDoc, updateSettings } from './api';
+import { useNotification, useFetchClient } from '@strapi/helper-plugin';
+import pluginId from '../../pluginId';
import getTrad from '../../utils/getTrad';
const useReactQuery = () => {
const queryClient = useQueryClient();
const toggleNotification = useNotification();
- const { isLoading, data } = useQuery('get-documentation', () =>
- fetchDocumentationVersions(toggleNotification)
- );
+ const { isLoading, data } = useQuery(['get-documentation', pluginId], async () => {
+ try {
+ const { data } = await get(`/${pluginId}/getInfos`);
+
+ return data;
+ } catch (err) {
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+
+ // FIXME
+ return null;
+ }
+ });
+
+ const { del, post, put, get } = useFetchClient();
const handleError = (err) => {
toggleNotification({
@@ -25,20 +39,26 @@ const useReactQuery = () => {
});
};
- const deleteMutation = useMutation(deleteDoc, {
- onSuccess: () => handleSuccess('info', 'notification.delete.success'),
- onError: (error) => handleError(error),
- });
+ const deleteMutation = useMutation(
+ ({ prefix, version }) => del(`${prefix}/deleteDoc/${version}`),
+ {
+ onSuccess: () => handleSuccess('info', 'notification.delete.success'),
+ onError: (error) => handleError(error),
+ }
+ );
- const submitMutation = useMutation(updateSettings, {
+ const submitMutation = useMutation(({ prefix, body }) => put(`${prefix}/updateSettings`, body), {
onSuccess: () => handleSuccess('success', 'notification.update.success'),
onError: handleError,
});
- const regenerateDocMutation = useMutation(regenerateDoc, {
- onSuccess: () => handleSuccess('info', 'notification.generate.success'),
- onError: (error) => handleError(error),
- });
+ const regenerateDocMutation = useMutation(
+ ({ prefix, version }) => post(`${prefix}/regenerateDoc`, { version }),
+ {
+ onSuccess: () => handleSuccess('info', 'notification.generate.success'),
+ onError: (error) => handleError(error),
+ }
+ );
return { data, isLoading, deleteMutation, submitMutation, regenerateDocMutation };
};
diff --git a/packages/plugins/i18n/admin/src/hooks/useAddLocale/index.js b/packages/plugins/i18n/admin/src/hooks/useAddLocale/index.js
index eb34bcd477..cf93518b88 100644
--- a/packages/plugins/i18n/admin/src/hooks/useAddLocale/index.js
+++ b/packages/plugins/i18n/admin/src/hooks/useAddLocale/index.js
@@ -1,39 +1,28 @@
import { useState } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import { useDispatch } from 'react-redux';
import get from 'lodash/get';
import { getTrad } from '../../utils';
import { ADD_LOCALE } from '../constants';
-const addLocale = async ({ code, name, isDefault }, toggleNotification) => {
- const data = await request('/i18n/locales', {
- method: 'POST',
- body: {
- name,
- code,
- isDefault,
- },
- });
-
- toggleNotification({
- type: 'success',
- message: { id: getTrad('Settings.locales.modal.create.success') },
- });
-
- return data;
-};
-
const useAddLocale = () => {
const [isLoading, setLoading] = useState(false);
const dispatch = useDispatch();
const toggleNotification = useNotification();
+ const { post } = useFetchClient();
const persistLocale = async (locale) => {
setLoading(true);
try {
- const newLocale = await addLocale(locale, toggleNotification);
- dispatch({ type: ADD_LOCALE, newLocale });
+ const { data } = await post('/i18n/locales', locale);
+
+ toggleNotification({
+ type: 'success',
+ message: { id: getTrad('Settings.locales.modal.create.success') },
+ });
+
+ dispatch({ type: ADD_LOCALE, newLocale: data });
} catch (e) {
const message = get(e, 'response.payload.message', null);
diff --git a/packages/plugins/i18n/admin/src/hooks/useDefaultLocales/index.js b/packages/plugins/i18n/admin/src/hooks/useDefaultLocales/index.js
index 5c931f0c39..d308934759 100644
--- a/packages/plugins/i18n/admin/src/hooks/useDefaultLocales/index.js
+++ b/packages/plugins/i18n/admin/src/hooks/useDefaultLocales/index.js
@@ -1,32 +1,18 @@
import { useQuery } from 'react-query';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import { useNotifyAT } from '@strapi/design-system';
import { useIntl } from 'react-intl';
import { getTrad } from '../../utils';
-const fetchDefaultLocalesList = async (toggleNotification) => {
- try {
- const data = await request('/i18n/iso-locales', {
- method: 'GET',
- });
-
- return data;
- } catch (e) {
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
-
- return [];
- }
-};
-
const useDefaultLocales = () => {
const { formatMessage } = useIntl();
const { notifyStatus } = useNotifyAT();
const toggleNotification = useNotification();
- const { isLoading, data } = useQuery('default-locales', () =>
- fetchDefaultLocalesList(toggleNotification).then((data) => {
+ const { get } = useFetchClient();
+ const { isLoading, data } = useQuery(['plugin-i18n', 'locales'], async () => {
+ try {
+ const { data } = await get('/i18n/iso-locales');
+
notifyStatus(
formatMessage({
id: getTrad('Settings.locales.modal.locales.loaded'),
@@ -35,8 +21,15 @@ const useDefaultLocales = () => {
);
return data;
- })
- );
+ } catch (e) {
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+
+ return [];
+ }
+ });
return { defaultLocales: data, isLoading };
};
diff --git a/packages/plugins/i18n/admin/src/hooks/useDeleteLocale/index.js b/packages/plugins/i18n/admin/src/hooks/useDeleteLocale/index.js
index f6fb1df4c1..2d9fc364ee 100644
--- a/packages/plugins/i18n/admin/src/hooks/useDeleteLocale/index.js
+++ b/packages/plugins/i18n/admin/src/hooks/useDeleteLocale/index.js
@@ -1,43 +1,36 @@
import { useState } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import { useDispatch } from 'react-redux';
import { getTrad } from '../../utils';
import { DELETE_LOCALE } from '../constants';
-const deleteLocale = async (id, toggleNotification) => {
- try {
- const data = await request(`/i18n/locales/${id}`, {
- method: 'DELETE',
- });
-
- toggleNotification({
- type: 'success',
- message: { id: getTrad('Settings.locales.modal.delete.success') },
- });
-
- return data;
- } catch (e) {
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
-
- return e;
- }
-};
-
const useDeleteLocale = () => {
const [isLoading, setLoading] = useState(false);
const dispatch = useDispatch();
const toggleNotification = useNotification();
+ const { del } = useFetchClient();
+
const removeLocale = async (id) => {
- setLoading(true);
+ try {
+ setLoading(true);
- await deleteLocale(id, toggleNotification);
+ await del(`/i18n/locales/${id}`);
- dispatch({ type: DELETE_LOCALE, id });
- setLoading(false);
+ toggleNotification({
+ type: 'success',
+ message: { id: getTrad('Settings.locales.modal.delete.success') },
+ });
+
+ dispatch({ type: DELETE_LOCALE, id });
+ } catch {
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+ } finally {
+ setLoading(false);
+ }
};
return { isDeleting: isLoading, deleteLocale: removeLocale };
diff --git a/packages/plugins/i18n/admin/src/hooks/useEditLocale/index.js b/packages/plugins/i18n/admin/src/hooks/useEditLocale/index.js
index 112dd0e666..564e1fe72c 100644
--- a/packages/plugins/i18n/admin/src/hooks/useEditLocale/index.js
+++ b/packages/plugins/i18n/admin/src/hooks/useEditLocale/index.js
@@ -1,44 +1,35 @@
import { useState } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import { useDispatch } from 'react-redux';
import { getTrad } from '../../utils';
import { UPDATE_LOCALE } from '../constants';
-const editLocale = async (id, payload, toggleNotification) => {
- try {
- const data = await request(`/i18n/locales/${id}`, {
- method: 'PUT',
- body: payload,
- });
-
- toggleNotification({
- type: 'success',
- message: { id: getTrad('Settings.locales.modal.edit.success') },
- });
-
- return data;
- } catch {
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
-
- return null;
- }
-};
-
const useEditLocale = () => {
const [isLoading, setLoading] = useState(false);
const dispatch = useDispatch();
const toggleNotification = useNotification();
+ const { put } = useFetchClient();
const modifyLocale = async (id, payload) => {
- setLoading(true);
+ try {
+ setLoading(true);
- const editedLocale = await editLocale(id, payload, toggleNotification);
+ const { data } = await put(`/i18n/locales/${id}`, payload);
- dispatch({ type: UPDATE_LOCALE, editedLocale });
- setLoading(false);
+ toggleNotification({
+ type: 'success',
+ message: { id: getTrad('Settings.locales.modal.edit.success') },
+ });
+
+ dispatch({ type: UPDATE_LOCALE, editedLocale: data });
+ } catch {
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+ } finally {
+ setLoading(false);
+ }
};
return { isEditing: isLoading, editLocale: modifyLocale };
diff --git a/packages/plugins/i18n/admin/src/hooks/useLocales/index.js b/packages/plugins/i18n/admin/src/hooks/useLocales/index.js
index fbfff22bea..1b165b8323 100644
--- a/packages/plugins/i18n/admin/src/hooks/useLocales/index.js
+++ b/packages/plugins/i18n/admin/src/hooks/useLocales/index.js
@@ -1,36 +1,35 @@
import { useEffect } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import { useSelector, useDispatch } from 'react-redux';
import { RESOLVE_LOCALES } from '../constants';
-const fetchLocalesList = async (toggleNotification) => {
- try {
- const data = await request('/i18n/locales', {
- method: 'GET',
- });
-
- return data;
- } catch (e) {
- toggleNotification({
- type: 'warning',
- message: { id: 'notification.error' },
- });
-
- return e;
- }
-};
-
const useLocales = () => {
const dispatch = useDispatch();
const toggleNotification = useNotification();
const locales = useSelector((state) => state.i18n_locales.locales);
const isLoading = useSelector((state) => state.i18n_locales.isLoading);
+ const { get } = useFetchClient();
+
useEffect(() => {
- fetchLocalesList(toggleNotification).then((locales) =>
- dispatch({ type: RESOLVE_LOCALES, locales })
- );
- }, [dispatch, toggleNotification]);
+ get('/i18n/locales')
+ .then(({ data }) => dispatch({ type: RESOLVE_LOCALES, locales: data }))
+ .catch((err) => {
+ /**
+ * TODO: this should be refactored.
+ *
+ * In fact it should be refactored to use react-query?
+ */
+ if ('code' in err && err?.code === 'ERR_CANCELED') {
+ return;
+ }
+
+ toggleNotification({
+ type: 'warning',
+ message: { id: 'notification.error' },
+ });
+ });
+ }, [dispatch, get, toggleNotification]);
return { locales, isLoading };
};
diff --git a/packages/plugins/i18n/admin/src/middlewares/addCommonFieldsToInitialDataMiddleware.js b/packages/plugins/i18n/admin/src/middlewares/addCommonFieldsToInitialDataMiddleware.js
index f2f60a3356..544771670f 100644
--- a/packages/plugins/i18n/admin/src/middlewares/addCommonFieldsToInitialDataMiddleware.js
+++ b/packages/plugins/i18n/admin/src/middlewares/addCommonFieldsToInitialDataMiddleware.js
@@ -3,7 +3,7 @@ import merge from 'lodash/merge';
import cloneDeep from 'lodash/cloneDeep';
import { parse } from 'qs';
import {
- request,
+ getFetchClient,
formatContentTypeData,
contentManagementUtilRemoveFieldsFromData,
} from '@strapi/helper-plugin';
@@ -44,10 +44,10 @@ const addCommonFieldsToInitialDataMiddleware =
const defaultDataStructure = cloneDeep(contentTypeDataStructure);
try {
- const requestURL = `/${pluginId}/content-manager/actions/get-non-localized-fields`;
- const body = { model: currentLayout.contentType.uid, id: relatedEntityId, locale };
-
- const data = await request(requestURL, { method: 'POST', body });
+ const { data } = await getFetchClient().post(
+ `/${pluginId}/content-manager/actions/get-non-localized-fields`,
+ { model: currentLayout.contentType.uid, id: relatedEntityId, locale }
+ );
const { nonLocalizedFields, localizations } = data;
diff --git a/packages/plugins/i18n/admin/src/pages/SettingsPage/tests/SettingsPage.test.js b/packages/plugins/i18n/admin/src/pages/SettingsPage/tests/SettingsPage.test.js
index 60b56a0233..8dde473c1c 100644
--- a/packages/plugins/i18n/admin/src/pages/SettingsPage/tests/SettingsPage.test.js
+++ b/packages/plugins/i18n/admin/src/pages/SettingsPage/tests/SettingsPage.test.js
@@ -3,7 +3,7 @@
import React from 'react';
// import { createStore, combineReducers } from 'redux';
// import { Provider } from 'react-redux';
-import { request, useRBAC } from '@strapi/helper-plugin';
+// import { request, useRBAC } from '@strapi/helper-plugin';
// import { fireEvent, render, screen, within, waitFor } from '@testing-library/react';
// import { ThemeProvider } from 'styled-components';
// import { QueryClient, QueryClientProvider } from 'react-query';
@@ -81,27 +81,26 @@ jest.mock('react-intl', () => ({
describe('i18n settings page', () => {
beforeEach(() => {
- request.mockImplementation(() =>
- Promise.resolve([
- {
- id: 1,
- name: 'French',
- code: 'fr-FR',
- isDefault: false,
- },
- {
- id: 2,
- name: 'English',
- code: 'en-US',
- isDefault: true,
- },
- ])
- );
-
- useRBAC.mockImplementation(() => ({
- isLoading: false,
- allowedActions: { canRead: true, canUpdate: true, canCreate: true, canDelete: true },
- }));
+ // request.mockImplementation(() =>
+ // Promise.resolve([
+ // {
+ // id: 1,
+ // name: 'French',
+ // code: 'fr-FR',
+ // isDefault: false,
+ // },
+ // {
+ // id: 2,
+ // name: 'English',
+ // code: 'en-US',
+ // isDefault: true,
+ // },
+ // ])
+ // );
+ // useRBAC.mockImplementation(() => ({
+ // isLoading: false,
+ // allowedActions: { canRead: true, canUpdate: true, canCreate: true, canDelete: true },
+ // }));
});
afterEach(() => {
@@ -583,14 +582,14 @@ describe('i18n settings page', () => {
describe('create', () => {
beforeEach(() => {
- request.mockImplementation((url) =>
- url.includes('/i18n/locales')
- ? Promise.resolve([])
- : Promise.resolve([
- { code: 'fr-FR', name: 'Francais' },
- { code: 'en-EN', name: 'English' },
- ])
- );
+ // request.mockImplementation((url) =>
+ // url.includes('/i18n/locales')
+ // ? Promise.resolve([])
+ // : Promise.resolve([
+ // { code: 'fr-FR', name: 'Francais' },
+ // { code: 'en-EN', name: 'English' },
+ // ])
+ // );
});
test.todo('shows the default create modal layout');
// it('shows the default create modal layout', async () => {
diff --git a/packages/plugins/users-permissions/admin/src/hooks/useForm/index.js b/packages/plugins/users-permissions/admin/src/hooks/useForm/index.js
index 3b3ea7b5b1..35000194a4 100644
--- a/packages/plugins/users-permissions/admin/src/hooks/useForm/index.js
+++ b/packages/plugins/users-permissions/admin/src/hooks/useForm/index.js
@@ -1,5 +1,5 @@
import { useCallback, useEffect, useReducer, useRef } from 'react';
-import { useRBAC, request, useNotification } from '@strapi/helper-plugin';
+import { useRBAC, useFetchClient, useNotification } from '@strapi/helper-plugin';
import { getRequestURL } from '../../utils';
import reducer, { initialState } from './reducer';
@@ -9,8 +9,7 @@ const useUserForm = (endPoint, permissions) => {
const toggleNotification = useNotification();
const isMounted = useRef(true);
- const abortController = new AbortController();
- const { signal } = abortController;
+ const { get } = useFetchClient();
useEffect(() => {
const getData = async () => {
@@ -19,7 +18,7 @@ const useUserForm = (endPoint, permissions) => {
type: 'GET_DATA',
});
- const data = await request(getRequestURL(endPoint), { method: 'GET', signal });
+ const { data } = await get(getRequestURL(endPoint));
dispatch({
type: 'GET_DATA_SUCCEEDED',
@@ -45,11 +44,9 @@ const useUserForm = (endPoint, permissions) => {
}
return () => {
- abortController.abort();
isMounted.current = false;
};
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [isLoadingForPermissions, endPoint]);
+ }, [isLoadingForPermissions, endPoint, get, toggleNotification]);
const dispatchSubmitSucceeded = useCallback((data) => {
dispatch({
diff --git a/packages/plugins/users-permissions/admin/src/hooks/useRolesList/index.js b/packages/plugins/users-permissions/admin/src/hooks/useRolesList/index.js
index d760e60588..10e4d37ad9 100644
--- a/packages/plugins/users-permissions/admin/src/hooks/useRolesList/index.js
+++ b/packages/plugins/users-permissions/admin/src/hooks/useRolesList/index.js
@@ -1,5 +1,5 @@
-import { useEffect, useReducer, useRef } from 'react';
-import { request, useNotification } from '@strapi/helper-plugin';
+import { useCallback, useEffect, useReducer, useRef } from 'react';
+import { useFetchClient, useNotification } from '@strapi/helper-plugin';
import get from 'lodash/get';
import init from './init';
import pluginId from '../../pluginId';
@@ -12,28 +12,17 @@ const useRolesList = (shouldFetchData = true) => {
const toggleNotification = useNotification();
const isMounted = useRef(true);
- const abortController = new AbortController();
- const { signal } = abortController;
+ const fetchClient = useFetchClient();
- useEffect(() => {
- if (shouldFetchData) {
- fetchRolesList();
- }
-
- return () => {
- abortController.abort();
- isMounted.current = false;
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [shouldFetchData]);
-
- const fetchRolesList = async () => {
+ const fetchRolesList = useCallback(async () => {
try {
dispatch({
type: 'GET_DATA',
});
- const { roles } = await request(`/${pluginId}/roles`, { method: 'GET', signal });
+ const {
+ data: { roles },
+ } = await fetchClient.get(`/${pluginId}/roles`);
dispatch({
type: 'GET_DATA_SUCCEEDED',
@@ -55,7 +44,17 @@ const useRolesList = (shouldFetchData = true) => {
}
}
}
- };
+ }, [fetchClient, toggleNotification]);
+
+ useEffect(() => {
+ if (shouldFetchData) {
+ fetchRolesList();
+ }
+
+ return () => {
+ isMounted.current = false;
+ };
+ }, [shouldFetchData, fetchRolesList]);
return { roles, isLoading, getData: fetchRolesList };
};
diff --git a/packages/utils/eslint-config-custom/front.js b/packages/utils/eslint-config-custom/front.js
index 46840b4a28..7756c675de 100644
--- a/packages/utils/eslint-config-custom/front.js
+++ b/packages/utils/eslint-config-custom/front.js
@@ -49,6 +49,12 @@ module.exports = {
message:
"'Stack' has been deprecated. Please import 'Flex' from '@strapi/design-system' instead.",
},
+ {
+ name: '@strapi/helper-plugin',
+ importNames: ['request'],
+ message:
+ "'request' has been deprecated. Please import 'useFetchClient' from '@strapi/helper-plugin' instead.",
+ },
{
name: 'lodash',
message: 'Please use import [method] from lodash/[method]',
From 18ddcf22742d7b564c3fc9e13b3855879bf2f594 Mon Sep 17 00:00:00 2001
From: Simone Taeggi
Date: Thu, 20 Apr 2023 18:59:55 +0200
Subject: [PATCH 6/6] remove unused request
---
packages/core/helper-plugin/src/utils/hasPermissions/index.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/packages/core/helper-plugin/src/utils/hasPermissions/index.js b/packages/core/helper-plugin/src/utils/hasPermissions/index.js
index 64dd60dfc7..17340a9811 100644
--- a/packages/core/helper-plugin/src/utils/hasPermissions/index.js
+++ b/packages/core/helper-plugin/src/utils/hasPermissions/index.js
@@ -2,7 +2,6 @@ import isEmpty from 'lodash/isEmpty';
import pickBy from 'lodash/pickBy';
import transform from 'lodash/transform';
-import request from '../request';
import getFetchClient from '../getFetchClient';
const findMatchingPermissions = (userPermissions, permissions) => {