From f0990ee972ad88cf47fec06178a5eb8df1a5bbe0 Mon Sep 17 00:00:00 2001 From: Quentin Aubert Date: Mon, 19 Feb 2024 14:39:04 +0100 Subject: [PATCH] manage expertMode in globalContext --- .../tenants/TenantAdminList.tsx | 23 ++++++------- .../components/backoffice/apis/TeamApi.tsx | 9 ++--- .../backoffice/apis/TeamApiGroup.tsx | 4 +-- .../backoffice/apis/TeamApiPricings.tsx | 6 ++-- .../backoffice/assets/AssetsList.tsx | 15 ++++---- .../components/frontend/api/ApiGroupHome.tsx | 11 +++--- .../src/components/frontend/api/ApiHome.tsx | 11 +++--- .../components/frontend/api/ApiPricing.tsx | 21 ++++++++---- .../src/components/frontend/api/ApiRedoc.tsx | 7 ++-- .../components/frontend/api/ApiSwagger.tsx | 7 ++-- .../src/components/utils/permissions/Can.tsx | 10 +++--- .../src/components/utils/sidebar/SideBar.tsx | 2 +- .../javascript/src/contexts/globalContext.tsx | 34 +++++++++++-------- .../javascript/src/contexts/navContext.tsx | 6 ++-- daikoku/javascript/src/services/index.ts | 30 +++++++--------- daikoku/javascript/src/types/context.ts | 2 -- 16 files changed, 98 insertions(+), 100 deletions(-) diff --git a/daikoku/javascript/src/components/adminbackoffice/tenants/TenantAdminList.tsx b/daikoku/javascript/src/components/adminbackoffice/tenants/TenantAdminList.tsx index 076d2ba43..850e97188 100644 --- a/daikoku/javascript/src/components/adminbackoffice/tenants/TenantAdminList.tsx +++ b/daikoku/javascript/src/components/adminbackoffice/tenants/TenantAdminList.tsx @@ -1,23 +1,22 @@ -import React, { useState, useEffect, useContext } from 'react'; -import Select from 'react-select'; -import { toast } from 'sonner'; -import values from 'lodash/values'; import sortBy from 'lodash/sortBy'; +import values from 'lodash/values'; +import { useContext, useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; +import Select from 'react-select'; +import { toast } from 'sonner'; +import { I18nContext, ModalContext, useDaikokuBackOffice, useTenantBackOffice } from '../../../contexts'; +import { GlobalContext } from '../../../contexts/globalContext'; import * as Services from '../../../services'; +import { ITeamSimple, ITenantFull, IUser, isError } from '../../../types'; import { - Can, - manage, - tenant as TENANT, - PaginatedComponent, AvatarWithAction, + Can, Option, + PaginatedComponent, + tenant as TENANT, + manage, } from '../../utils'; -import { I18nContext } from '../../../contexts'; -import { ModalContext, useDaikokuBackOffice, useTenantBackOffice } from '../../../contexts'; -import { isError, IState, IStateContext, ITeamSimple, ITenantFull, IUser, IUserSimple } from '../../../types'; -import { GlobalContext } from '../../../contexts/globalContext'; const AdminList = () => { const context = useContext(GlobalContext); diff --git a/daikoku/javascript/src/components/backoffice/apis/TeamApi.tsx b/daikoku/javascript/src/components/backoffice/apis/TeamApi.tsx index d40db758a..43f7a91e7 100644 --- a/daikoku/javascript/src/components/backoffice/apis/TeamApi.tsx +++ b/daikoku/javascript/src/components/backoffice/apis/TeamApi.tsx @@ -22,9 +22,9 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import { I18nContext } from '../../../contexts'; -import { IState, IStateContext, ITeamSimple } from '../../../types'; -import { IApi, IUsagePlan, isError } from '../../../types/api'; import { GlobalContext } from '../../../contexts/globalContext'; +import { ITeamSimple } from '../../../types'; +import { IApi, IUsagePlan, isError } from '../../../types/api'; import { TeamBackOfficeProps } from '../TeamBackOffice'; const reservedCharacters = [';', '/', '?', ':', '@', '&', '=', '+', '$', ',']; @@ -96,7 +96,7 @@ export const TeamApi = (props: TeamBackOfficeProps<{ creation: boolean }>) => { const navigate = useNavigate(); const match = useMatch('/:teamId/settings/apis/:apiId/:version/stats/plan/:planId'); - const { tenant } = useContext(GlobalContext); + const { tenant, expertMode, toggleExpertMode } = useContext(GlobalContext); const { translate } = useContext(I18nContext); const { openApiDocumentationSelectModal } = useContext(ModalContext); @@ -293,7 +293,7 @@ export const TeamApi = (props: TeamBackOfficeProps<{ creation: boolean }>) => { {props.creation ? (

{api.name}

) : (

{api.name} {additionalHeader ? ` - ${additionalHeader}` : ''}

)} - @@ -323,6 +323,7 @@ export const TeamApi = (props: TeamBackOfficeProps<{ creation: boolean }>) => { importAuthorized={!!versionsRequest.data && !!versionsRequest.data.length} />)} {tab === 'plans' && ( queryClient.invalidateQueries({ queryKey: ['api'] })} setDefaultPlan={plan => setDefaultPlan(api, plan)} diff --git a/daikoku/javascript/src/components/backoffice/apis/TeamApiGroup.tsx b/daikoku/javascript/src/components/backoffice/apis/TeamApiGroup.tsx index a2b970850..7adb30993 100644 --- a/daikoku/javascript/src/components/backoffice/apis/TeamApiGroup.tsx +++ b/daikoku/javascript/src/components/backoffice/apis/TeamApiGroup.tsx @@ -28,7 +28,7 @@ export const TeamApiGroup = (props: TeamBackOfficeProps) => { const navigate = useNavigate(); const match = useMatch('/:teamId/settings/apigroups/:apiGroupId/stats/plan/:planId'); - const { tenant } = useContext(GlobalContext); + const { tenant, expertMode, toggleExpertMode } = useContext(GlobalContext); const state: LocationState = location.state as LocationState const creation = state?.newApiGroup; @@ -253,7 +253,7 @@ export const TeamApiGroup = (props: TeamBackOfficeProps) => { {creation ? (

{apiGroup.name}

) : (

{apiGroup.name}{additionalHeader ? ` - ${additionalHeader}` : ''}

)} - diff --git a/daikoku/javascript/src/components/backoffice/apis/TeamApiPricings.tsx b/daikoku/javascript/src/components/backoffice/apis/TeamApiPricings.tsx index 0b5f20c31..c516e15ee 100644 --- a/daikoku/javascript/src/components/backoffice/apis/TeamApiPricings.tsx +++ b/daikoku/javascript/src/components/backoffice/apis/TeamApiPricings.tsx @@ -19,9 +19,10 @@ import { toast } from 'sonner'; import React from 'react'; import { I18nContext, ModalContext } from '../../../contexts'; +import { GlobalContext } from '../../../contexts/globalContext'; import * as Services from '../../../services'; import { currencies } from '../../../services/currencies'; -import { IState, IStateContext, ITeamSimple } from '../../../types'; +import { ITeamSimple } from '../../../types'; import { IApi, IDocumentation, isError, isValidationStepEmail, isValidationStepHttpRequest, isValidationStepPayment, isValidationStepTeamAdmin, IUsagePlan, IValidationStep, IValidationStepEmail, IValidationStepHttpRequest, IValidationStepTeamAdmin, IValidationStepType, UsagePlanVisibility } from '../../../types/api'; import { IOtoroshiSettings, ITenant, ITenantFull, IThirdPartyPaymentSettings } from '../../../types/tenant'; import { @@ -33,11 +34,10 @@ import { import { addArrayIf, insertArrayIndex } from '../../utils/array'; import { FixedItem, SortableItem, SortableList } from '../../utils/dnd/SortableList'; import { Help } from '../apikeys'; +import { TeamBackOfficeProps } from '../TeamBackOffice'; import { TeamApiDocumentation } from './TeamApiDocumentation'; import { TeamApiSwagger } from './TeamApiSwagger'; import { TeamApiTesting } from './TeamApiTesting'; -import { GlobalContext } from '../../../contexts/globalContext'; -import { TeamBackOfficeProps } from '../TeamBackOffice'; const SUBSCRIPTION_PLAN_TYPES = { FreeWithoutQuotas: { diff --git a/daikoku/javascript/src/components/backoffice/assets/AssetsList.tsx b/daikoku/javascript/src/components/backoffice/assets/AssetsList.tsx index 3ce0e242c..1b7af533d 100644 --- a/daikoku/javascript/src/components/backoffice/assets/AssetsList.tsx +++ b/daikoku/javascript/src/components/backoffice/assets/AssetsList.tsx @@ -1,16 +1,15 @@ /* eslint-disable react/display-name */ -import React, { useState, useEffect, useContext, useRef } from 'react'; -import { toast } from 'sonner'; import { constraints, format, type } from '@maif/react-forms'; +import { useContext, useEffect, useRef, useState } from 'react'; +import { toast } from 'sonner'; -import * as Services from '../../../services'; -import { Table, TableRef } from '../../inputs'; -import { Can, manage, asset, tenant as TENANT } from '../../utils'; -import { I18nContext } from '../../../contexts'; -import { ModalContext } from '../../../contexts'; import { createColumnHelper } from '@tanstack/react-table'; -import { IAsset, IState, IStateContext, ITeamSimple } from '../../../types'; +import { I18nContext, ModalContext } from '../../../contexts'; import { GlobalContext } from '../../../contexts/globalContext'; +import * as Services from '../../../services'; +import { IAsset, ITeamSimple } from '../../../types'; +import { Table, TableRef } from '../../inputs'; +import { Can, tenant as TENANT, asset, manage } from '../../utils'; const mimeTypes = [ diff --git a/daikoku/javascript/src/components/frontend/api/ApiGroupHome.tsx b/daikoku/javascript/src/components/frontend/api/ApiGroupHome.tsx index e25a6551d..02cc986cb 100644 --- a/daikoku/javascript/src/components/frontend/api/ApiGroupHome.tsx +++ b/daikoku/javascript/src/components/frontend/api/ApiGroupHome.tsx @@ -1,12 +1,13 @@ import { getApolloContext } from '@apollo/client'; import { useContext, useEffect, useState } from 'react'; -import { toast } from 'sonner'; import { useMatch, useNavigate, useParams } from 'react-router-dom'; +import { toast } from 'sonner'; -import { useApiGroupFrontOffice } from '../../../contexts'; -import { I18nContext } from '../../../contexts'; +import classNames from 'classnames'; +import { I18nContext, useApiGroupFrontOffice } from '../../../contexts'; +import { GlobalContext } from '../../../contexts/globalContext'; import * as Services from '../../../services'; -import { IState, IStateContext, ISubscription, ISubscriptionDemand, ITeamSimple, IUsagePlan, IUserSimple, isError } from '../../../types'; +import { ISubscription, ISubscriptionDemand, ITeamSimple, IUsagePlan, isError } from '../../../types'; import { formatPlanType } from '../../utils/formatters'; import { ApiDescription, @@ -18,8 +19,6 @@ import { ApiPost, ApiPricing, } from './'; -import classNames from 'classnames'; -import { GlobalContext } from '../../../contexts/globalContext'; export const ApiGroupHome = () => { const [apiGroup, setApiGroup] = useState(); diff --git a/daikoku/javascript/src/components/frontend/api/ApiHome.tsx b/daikoku/javascript/src/components/frontend/api/ApiHome.tsx index 0c412589d..7237b33c5 100644 --- a/daikoku/javascript/src/components/frontend/api/ApiHome.tsx +++ b/daikoku/javascript/src/components/frontend/api/ApiHome.tsx @@ -1,23 +1,22 @@ import { getApolloContext } from '@apollo/client'; import hljs from 'highlight.js'; import { useContext, useEffect, useState } from 'react'; -import { toast } from 'sonner'; +import Navigation from 'react-feather/dist/icons/navigation'; import { useMatch, useNavigate, useParams } from 'react-router-dom'; import Select from 'react-select'; -import Navigation from 'react-feather/dist/icons/navigation'; +import { toast } from 'sonner'; import { ApiDocumentation, ApiIssue, ApiPost, ApiPricing, ApiRedoc, ApiSwagger } from '.'; -import { ModalContext, useApiFrontOffice } from '../../../contexts'; -import { I18nContext } from '../../../contexts'; +import { I18nContext, ModalContext, useApiFrontOffice } from '../../../contexts'; import * as Services from '../../../services'; import { converter } from '../../../services/showdown'; -import { IApi, IState, IStateContext, ISubscription, ISubscriptionDemand, ITeamSimple, IUsagePlan, TeamPermission, TeamType, isError } from '../../../types'; +import { IApi, ISubscription, ISubscriptionDemand, ITeamSimple, IUsagePlan, isError } from '../../../types'; import { ActionWithTeamSelector, Can, CanIDoAction, Option, apikey, manage } from '../../utils'; import { formatPlanType } from '../../utils/formatters'; import StarsButton from './StarsButton'; -import 'highlight.js/styles/monokai.css'; import classNames from 'classnames'; +import 'highlight.js/styles/monokai.css'; import { GlobalContext } from '../../../contexts/globalContext'; (window as any).hljs = hljs; diff --git a/daikoku/javascript/src/components/frontend/api/ApiPricing.tsx b/daikoku/javascript/src/components/frontend/api/ApiPricing.tsx index f6505d232..34388c3db 100644 --- a/daikoku/javascript/src/components/frontend/api/ApiPricing.tsx +++ b/daikoku/javascript/src/components/frontend/api/ApiPricing.tsx @@ -7,24 +7,31 @@ import React, { useContext, useEffect } from 'react'; import { Link, useMatch, useNavigate } from 'react-router-dom'; import { I18nContext, ModalContext } from '../../../contexts'; +import { GlobalContext } from '../../../contexts/globalContext'; import * as Services from '../../../services'; import { currencies } from '../../../services/currencies'; import { - IApi, IBaseUsagePlan, isError, - isMiniFreeWithQuotas, IState, IStateContext, ISubscription, - ISubscriptionDemand, ISubscriptionWithApiInfo, isValidationStepTeamAdmin, - ITeamSimple, IUsagePlan + IApi, IBaseUsagePlan, + ISubscription, + ISubscriptionDemand, ISubscriptionWithApiInfo, + ITeamSimple, IUsagePlan, + isError, + isMiniFreeWithQuotas, + isValidationStepTeamAdmin } from '../../../types'; import { + Can, + Option, + Spinner, access, - apikey, Can, isPublish, isSubscriptionProcessIsAutomatic, - Option, queryClient, renderPlanInfo, renderPricing, Spinner + apikey, + isPublish, isSubscriptionProcessIsAutomatic, + queryClient, renderPlanInfo, renderPricing } from '../../utils'; import { formatPlanType } from '../../utils/formatters'; import { ApiDocumentation } from './ApiDocumentation'; import { ApiRedoc } from './ApiRedoc'; import { ApiSwagger } from './ApiSwagger'; -import { GlobalContext } from '../../../contexts/globalContext'; export const currency = (plan?: IBaseUsagePlan) => { if (!plan) { diff --git a/daikoku/javascript/src/components/frontend/api/ApiRedoc.tsx b/daikoku/javascript/src/components/frontend/api/ApiRedoc.tsx index 627d91ee4..866505e67 100644 --- a/daikoku/javascript/src/components/frontend/api/ApiRedoc.tsx +++ b/daikoku/javascript/src/components/frontend/api/ApiRedoc.tsx @@ -1,11 +1,10 @@ import { useContext } from 'react'; import { RedocStandalone, SideNavStyleEnum } from 'redoc'; -import { ModalContext } from '../../../contexts'; -import { I18nContext } from '../../../contexts'; -import { IState, IStateContext, ISwagger } from '../../../types'; -import { Option } from '../../utils/Option'; +import { I18nContext, ModalContext } from '../../../contexts'; import { GlobalContext } from '../../../contexts/globalContext'; +import { ISwagger } from '../../../types'; +import { Option } from '../../utils/Option'; type ApiRedocProps = { swaggerUrl: string, diff --git a/daikoku/javascript/src/components/frontend/api/ApiSwagger.tsx b/daikoku/javascript/src/components/frontend/api/ApiSwagger.tsx index acd4a09b7..929fa9cc7 100644 --- a/daikoku/javascript/src/components/frontend/api/ApiSwagger.tsx +++ b/daikoku/javascript/src/components/frontend/api/ApiSwagger.tsx @@ -2,12 +2,11 @@ import { useContext, useEffect, useState } from 'react'; import { useParams } from 'react-router-dom'; import { SwaggerUIBundle } from 'swagger-ui-dist'; -import { ModalContext } from '../../../contexts'; -import { I18nContext } from '../../../contexts'; -import { IState, IStateContext, ISwagger, ITesting } from '../../../types'; +import { I18nContext, ModalContext } from '../../../contexts'; +import { GlobalContext } from '../../../contexts/globalContext'; +import { ISwagger, ITesting } from '../../../types'; import 'swagger-ui-dist/swagger-ui.css'; -import { GlobalContext } from '../../../contexts/globalContext'; type ApiSwaggerProps = { diff --git a/daikoku/javascript/src/components/utils/permissions/Can.tsx b/daikoku/javascript/src/components/utils/permissions/Can.tsx index b3fc35f86..80d42dc84 100644 --- a/daikoku/javascript/src/components/utils/permissions/Can.tsx +++ b/daikoku/javascript/src/components/utils/permissions/Can.tsx @@ -1,9 +1,10 @@ import { ReactNode, useContext } from 'react'; +import { toast } from 'sonner'; import { Option } from '..'; +import { I18nContext } from '../../../contexts'; +import { GlobalContext } from '../../../contexts/globalContext'; import { - IState, - IStateContext, ITeamSimple, ITenant, IUserSimple, @@ -11,11 +12,8 @@ import { TeamUser } from '../../../types'; import { doNothing } from './actions'; -import { permissions, TPermission, TPermissions } from './permissions'; +import { TPermission, TPermissions, permissions } from './permissions'; import { tenant } from './subjects'; -import { GlobalContext } from '../../../contexts/globalContext'; -import { toast } from 'sonner'; -import { I18nContext } from '../../../contexts'; export const CanIDoAction = ( user: IUserSimple, diff --git a/daikoku/javascript/src/components/utils/sidebar/SideBar.tsx b/daikoku/javascript/src/components/utils/sidebar/SideBar.tsx index 0bc642998..d68249f57 100644 --- a/daikoku/javascript/src/components/utils/sidebar/SideBar.tsx +++ b/daikoku/javascript/src/components/utils/sidebar/SideBar.tsx @@ -25,7 +25,7 @@ export const SideBar = () => { const [panelState, setPanelState] = useState(state.closed); const [panelContent, setPanelContent] = useState(); - const { tenant, connectedUser, impersonator, unreadNotificationsCount, isTenantAdmin } = useContext(GlobalContext); + const { tenant, connectedUser, impersonator, isTenantAdmin } = useContext(GlobalContext); const location = useLocation(); const { totalUnread } = useContext(MessagesContext); diff --git a/daikoku/javascript/src/contexts/globalContext.tsx b/daikoku/javascript/src/contexts/globalContext.tsx index 34bfe6ffe..aee16f3ef 100644 --- a/daikoku/javascript/src/contexts/globalContext.tsx +++ b/daikoku/javascript/src/contexts/globalContext.tsx @@ -1,22 +1,14 @@ import { useQuery } from "@tanstack/react-query" -import React, { PropsWithChildren } from "react" +import React, { PropsWithChildren, useState } from "react" import { queryClient } from "../components" import { Spinner } from "../components/utils/Spinner" import * as Services from '../services/index' -import { AuthProvider, DaikokuMode, Display, ITenant, IUserSimple, TenanMode, isError } from "../types" +import { AuthProvider, DaikokuMode, Display, IStateContext, TenanMode, isError } from "../types" -export interface IStateContext { - impersonator?: IUserSimple; - connectedUser: IUserSimple; - tenant: ITenant; - isTenantAdmin: boolean; - apiCreationPermitted: boolean; -} -export type TContext = IStateContext & { reloadContext: () => Promise } - -const initContext: TContext = { +type TGlobalContext = IStateContext & { reloadContext: () => void, toggleExpertMode: () => void } +const initContext: TGlobalContext = { connectedUser: { _id: "", _humanReadableId: "", @@ -46,17 +38,23 @@ const initContext: TContext = { }, isTenantAdmin: false, apiCreationPermitted: false, - reloadContext: () => Promise.resolve() + reloadContext: () => Promise.resolve(), + expertMode: JSON.parse(localStorage.getItem('expertMode') || 'false'), + toggleExpertMode: () => { } } -export const GlobalContext = React.createContext(initContext) +export const GlobalContext = React.createContext(initContext) export const useCurrentUserContext = () => { return React.useContext(GlobalContext) } export const CurrentUserContextProvider = (props: PropsWithChildren) => { + const getExpertMode = (): boolean => JSON.parse(localStorage.getItem('expertMode') || 'false') + + const [expertMode, setExpertMode] = useState(getExpertMode()) + const currentUserQuery = useQuery({ queryKey: ['context'], queryFn: () => Services.getUserContext(), @@ -73,8 +71,14 @@ export const CurrentUserContextProvider = (props: PropsWithChildren) => { const reloadContext = () => queryClient.invalidateQueries({ queryKey: ["context"] }) + const toggleExpertMode = () => { + localStorage.setItem('expertMode', (!expertMode).toLocaleString()) + setExpertMode(!expertMode) + }; + + return ( - + {props.children} ) diff --git a/daikoku/javascript/src/contexts/navContext.tsx b/daikoku/javascript/src/contexts/navContext.tsx index 96a5308f7..2168c021a 100644 --- a/daikoku/javascript/src/contexts/navContext.tsx +++ b/daikoku/javascript/src/contexts/navContext.tsx @@ -1,14 +1,14 @@ +import { useQuery } from '@tanstack/react-query'; import merge from 'lodash/merge'; import React, { useContext, useEffect, useState } from 'react'; import { Link, useMatch, useNavigate, useParams } from 'react-router-dom'; -import { useQuery } from '@tanstack/react-query'; import { api as API, Can, manage, queryClient } from '../components/utils'; import { I18nContext } from '../contexts'; -import { IApi, IState, IStateContext, IStoreState, ITeamSimple, ITenant, IUserSimple, isError } from '../types'; -import { ModalContext } from './modalContext'; import * as Services from '../services/index'; +import { IApi, ITeamSimple, ITenant, isError } from '../types'; import { GlobalContext } from './globalContext'; +import { ModalContext } from './modalContext'; export enum navMode { diff --git a/daikoku/javascript/src/services/index.ts b/daikoku/javascript/src/services/index.ts index 365c73b84..c5e936d9d 100644 --- a/daikoku/javascript/src/services/index.ts +++ b/daikoku/javascript/src/services/index.ts @@ -1,14 +1,16 @@ import { gql } from '@apollo/client'; import { - IFastApiSubscription, IAsset, IAuditTrail, + IFastApiSubscription, IMailingTranslation, INotification, IOtoroshiSettings, IQuotas, ISafeSubscription, ISession, + ISimpleOtoroshiSettings, + IStateContext, ISubscriptionInformation, ITeamFull, ITeamSimple, @@ -18,33 +20,27 @@ import { ITranslation, IUser, IUserSimple, - ISimpleOtoroshiSettings, - IStateContext, } from '../types'; import { - ResponseError, IApi, + IApiExtended, + IApiPost, + IConsumption, IDocDetail, IDocPage, + IDocumentation, + IImportingDocumentation, + IOtoroshiApiKey, ISubscription, - ResponseDone, - IApiPost, - ISubscriptionWithApiInfo, - IUsagePlan, ISubscriptionDemand, - IConsumption, ISubscriptionExtended, - IApiExtended, - IDocumentation, - IImportingDocumentation, + ISubscriptionWithApiInfo, ITestingConfig, - IApiKey, - IOtoroshiApiKey, + IUsagePlan, + ResponseDone, + ResponseError } from '../types/api'; -import { Option } from '../components/utils/Option' -import { TContext } from '../contexts/globalContext'; - const HEADERS = { Accept: 'application/json', 'Content-Type': 'application/json', diff --git a/daikoku/javascript/src/types/context.ts b/daikoku/javascript/src/types/context.ts index d967814d1..b3f994cc9 100644 --- a/daikoku/javascript/src/types/context.ts +++ b/daikoku/javascript/src/types/context.ts @@ -16,8 +16,6 @@ export interface IStateModal { export interface IStateContext { impersonator?: IUserSimple; connectedUser: IUserSimple; - currentTeam: ITeamSimple; - unreadNotificationsCount: number; tenant: ITenant; isTenantAdmin: boolean; apiCreationPermitted: boolean;