Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/5.6' into 5.6
Browse files Browse the repository at this point in the history
  • Loading branch information
gastonfournier committed Nov 21, 2023
2 parents 496f6bb + dcda1dd commit c9a3f33
Show file tree
Hide file tree
Showing 35 changed files with 988 additions and 363 deletions.
593 changes: 551 additions & 42 deletions CHANGELOG.md

Large diffs are not rendered by default.

31 changes: 9 additions & 22 deletions frontend/src/component/admin/users/UsersList/UsersList.tsx
Expand Up @@ -53,8 +53,6 @@ const UsersList = () => {
const [delUser, setDelUser] = useState<IUser>();
const { planUsers, isBillingUsers } = useUsersPlan(users);

const accessOverviewEnabled = useUiFlag('accessOverview');

const [searchValue, setSearchValue] = useState('');

const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
Expand Down Expand Up @@ -271,26 +269,15 @@ const UsersList = () => {
onChange={setSearchValue}
/>
<PageHeader.Divider />

<ConditionallyRender
condition={
isEnterprise() &&
Boolean(accessOverviewEnabled)
}
show={() => (
<>
<Tooltip
title='Exports user access information'
arrow
describeChild
>
<IconButton onClick={downloadCSV}>
<Download />
</IconButton>
</Tooltip>
</>
)}
/>
<Tooltip
title='Exports user access information'
arrow
describeChild
>
<IconButton onClick={downloadCSV}>
<Download />
</IconButton>
</Tooltip>
<Button
variant='contained'
color='primary'
Expand Down
Expand Up @@ -63,11 +63,11 @@ export const ConstraintAccordionEditBody: React.FC<IConstraintAccordionBody> =
<StyledLeftButton
type='button'
onClick={onSubmit}
variant='contained'
variant='outlined'
color='primary'
data-testid='CONSTRAINT_SAVE_BUTTON'
>
Save
Done
</StyledLeftButton>
<StyledRightButton
onClick={() => {
Expand Down
26 changes: 12 additions & 14 deletions frontend/src/component/project/Project/ProjectForm/ProjectForm.tsx
Expand Up @@ -184,8 +184,8 @@ const ProjectForm: React.FC<IProjectForm> = ({
}
/>
<ConditionallyRender
condition={mode === 'Edit' && Boolean(setFeatureLimit)}
show={
condition={mode === 'Edit'}
show={() => (
<>
<Box
sx={{
Expand All @@ -202,17 +202,15 @@ const ProjectForm: React.FC<IProjectForm> = ({
Leave it empty if you don’t want to add a limit
</StyledSubtitle>
<StyledInputContainer>
{featureLimit && setFeatureLimit && (
<StyledInput
label={'Limit'}
name='value'
type={'number'}
value={featureLimit}
onChange={(e) =>
setFeatureLimit(e.target.value)
}
/>
)}
<StyledInput
label={'Limit'}
name='value'
type={'number'}
value={featureLimit!}
onChange={(e) =>
setFeatureLimit!(e.target.value)
}
/>
<ConditionallyRender
condition={
featureCount !== undefined &&
Expand All @@ -226,7 +224,7 @@ const ProjectForm: React.FC<IProjectForm> = ({
/>
</StyledInputContainer>
</>
}
)}
/>
<ConditionallyRender
condition={mode === 'Create' && isEnterprise()}
Expand Down
Expand Up @@ -82,7 +82,7 @@ const useProjectForm = (

const getFeatureLimitAsNumber = () => {
if (featureLimit === '') {
return undefined;
return null;
}
return Number(featureLimit);
};
Expand Down
@@ -1,7 +1,10 @@
import React, { useContext } from 'react';
import { CreateButton } from 'component/common/CreateButton/CreateButton';
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import { CREATE_SEGMENT } from 'component/providers/AccessProvider/permissions';
import {
CREATE_SEGMENT,
UPDATE_PROJECT_SEGMENT,
} from 'component/providers/AccessProvider/permissions';
import { useSegmentsApi } from 'hooks/api/actions/useSegmentsApi/useSegmentsApi';
import { useConstraintsValidation } from 'hooks/api/getters/useConstraintsValidation/useConstraintsValidation';
import { useSegments } from 'hooks/api/getters/useSegments/useSegments';
Expand Down Expand Up @@ -112,7 +115,8 @@ export const CreateSegment = ({ modal }: ICreateSegmentProps) => {
>
<CreateButton
name='segment'
permission={CREATE_SEGMENT}
permission={[CREATE_SEGMENT, UPDATE_PROJECT_SEGMENT]}
projectId={projectId}
disabled={!hasValidConstraints || overSegmentValuesLimit}
data-testid={SEGMENT_CREATE_BTN_ID}
/>
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/component/segments/EditSegment/EditSegment.tsx
@@ -1,5 +1,8 @@
import FormTemplate from 'component/common/FormTemplate/FormTemplate';
import { UPDATE_SEGMENT } from 'component/providers/AccessProvider/permissions';
import {
UPDATE_PROJECT_SEGMENT,
UPDATE_SEGMENT,
} from 'component/providers/AccessProvider/permissions';
import { useSegmentsApi } from 'hooks/api/actions/useSegmentsApi/useSegmentsApi';
import { useConstraintsValidation } from 'hooks/api/getters/useConstraintsValidation/useConstraintsValidation';
import { useSegment } from 'hooks/api/getters/useSegment/useSegment';
Expand Down Expand Up @@ -135,7 +138,8 @@ export const EditSegment = ({ modal }: IEditSegmentProps) => {
mode='edit'
>
<UpdateButton
permission={UPDATE_SEGMENT}
permission={[UPDATE_SEGMENT, UPDATE_PROJECT_SEGMENT]}
projectId={projectId}
disabled={!hasValidConstraints || overSegmentValuesLimit}
data-testid={SEGMENT_SAVE_BTN_ID}
>
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/component/segments/SegmentEmpty.tsx
@@ -1,9 +1,13 @@
import { styled, Typography } from '@mui/material';
import { Link } from 'react-router-dom';
import { CREATE_SEGMENT } from 'component/providers/AccessProvider/permissions';
import {
CREATE_SEGMENT,
UPDATE_PROJECT_SEGMENT,
} from 'component/providers/AccessProvider/permissions';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import AccessContext from 'contexts/AccessContext';
import { useContext } from 'react';
import { useOptionalPathParam } from 'hooks/useOptionalPathParam';

const StyledDiv = styled('div')(({ theme }) => ({
display: 'flex',
Expand Down Expand Up @@ -35,6 +39,7 @@ const StyledLink = styled(Link)(({ theme }) => ({
}));

export const SegmentEmpty = () => {
const projectId = useOptionalPathParam('projectId');
const { hasAccess } = useContext(AccessContext);

return (
Expand All @@ -46,7 +51,10 @@ export const SegmentEmpty = () => {
and can be reused.
</StyledParagraph>
<ConditionallyRender
condition={hasAccess(CREATE_SEGMENT)}
condition={hasAccess(
[CREATE_SEGMENT, UPDATE_PROJECT_SEGMENT],
projectId,
)}
show={
<StyledLink to='/segments/create'>
Create your first segment
Expand Down
1 change: 1 addition & 0 deletions frontend/src/component/segments/SegmentForm.tsx
Expand Up @@ -72,6 +72,7 @@ export const SegmentForm: React.FC<ISegmentProps> = ({
condition={currentStep === 2}
show={
<SegmentFormStepTwo
project={project}
constraints={constraints}
setConstraints={setConstraints}
setCurrentStep={setCurrentStep}
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/component/segments/SegmentFormStepTwo.tsx
Expand Up @@ -8,6 +8,7 @@ import { CreateUnleashContext } from 'component/context/CreateUnleashContext/Cre
import {
CREATE_CONTEXT_FIELD,
CREATE_SEGMENT,
UPDATE_PROJECT_SEGMENT,
UPDATE_SEGMENT,
} from 'component/providers/AccessProvider/permissions';
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
Expand All @@ -32,6 +33,7 @@ import { useSegmentLimits } from 'hooks/api/getters/useSegmentLimits/useSegmentL
import { GO_BACK } from 'constants/navigate';

interface ISegmentFormPartTwoProps {
project?: string;
constraints: IConstraint[];
setConstraints: React.Dispatch<React.SetStateAction<IConstraint[]>>;
setCurrentStep: React.Dispatch<React.SetStateAction<SegmentFormStep>>;
Expand Down Expand Up @@ -101,6 +103,7 @@ const StyledCancelButton = styled(Button)(({ theme }) => ({

export const SegmentFormStepTwo: React.FC<ISegmentFormPartTwoProps> = ({
children,
project,
constraints,
setConstraints,
setCurrentStep,
Expand All @@ -112,7 +115,10 @@ export const SegmentFormStepTwo: React.FC<ISegmentFormPartTwoProps> = ({
const { context = [] } = useUnleashContext();
const [open, setOpen] = useState(false);
const segmentValuesCount = useSegmentValuesCount(constraints);
const modePermission = mode === 'create' ? CREATE_SEGMENT : UPDATE_SEGMENT;
const modePermission =
mode === 'create'
? [CREATE_SEGMENT, UPDATE_PROJECT_SEGMENT]
: [UPDATE_SEGMENT, UPDATE_PROJECT_SEGMENT];
const { segmentValuesLimit } = useSegmentLimits();

const overSegmentValuesLimit: boolean = Boolean(
Expand Down Expand Up @@ -197,7 +203,7 @@ export const SegmentFormStepTwo: React.FC<ISegmentFormPartTwoProps> = ({
ref={constraintsAccordionListRef}
constraints={constraints}
setConstraints={
hasAccess(modePermission)
hasAccess(modePermission, project)
? setConstraints
: undefined
}
Expand Down
82 changes: 81 additions & 1 deletion frontend/src/hooks/api/actions/useApi/useApi.ts
Expand Up @@ -24,6 +24,13 @@ type ApiErrorHandler = (
requestId: string,
) => void;

type ApiCaller = () => Promise<Response>;
type RequestFunction = (
apiCaller: ApiCaller,
requestId: string,
loadingOn?: boolean,
) => Promise<Response>;

interface IUseAPI {
handleBadRequest?: ApiErrorHandler;
handleNotFound?: ApiErrorHandler;
Expand All @@ -33,6 +40,29 @@ interface IUseAPI {
propagateErrors?: boolean;
}

const timeApiCallStart = (requestId: string) => {
// Store the start time in milliseconds
console.log(`Starting timing for request: ${requestId}`);
return Date.now();
};

const timeApiCallEnd = (startTime: number, requestId: string) => {
// Calculate the end time and subtract the start time
const endTime = Date.now();
const duration = endTime - startTime;
console.log(`Timing for request ${requestId}: ${duration} ms`);

if (duration > 500) {
console.error(
'API call took over 500ms. This may indicate a rendering performance problem in your React component.',
requestId,
duration,
);
}

return duration;
};

const useAPI = ({
handleBadRequest,
handleNotFound,
Expand Down Expand Up @@ -157,6 +187,27 @@ const useAPI = ({
],
);

const requestWithTimer = (requestFunction: RequestFunction) => {
return async (
apiCaller: () => Promise<Response>,
requestId: string,
loadingOn: boolean = true,
) => {
const start = timeApiCallStart(
requestId || `Unknown request happening on ${apiCaller}`,
);

const res = await requestFunction(apiCaller, requestId, loadingOn);

timeApiCallEnd(
start,
requestId || `Unknown request happening on ${apiCaller}`,
);

return res;
};
};

const makeRequest = useCallback(
async (
apiCaller: () => Promise<Response>,
Expand Down Expand Up @@ -187,6 +238,27 @@ const useAPI = ({
[handleResponses],
);

const makeLightRequest = useCallback(
async (
apiCaller: () => Promise<Response>,
requestId: string,
loadingOn: boolean = true,
): Promise<Response> => {
try {
const res = await apiCaller();

if (!res.ok) {
throw new Error();
}

return res;
} catch (e) {
throw new Error('Could not make request | makeLightRequest');
}
},
[],
);

const createRequest = useCallback(
(path: string, options: any, requestId: string = '') => {
const defaultOptions: RequestInit = {
Expand All @@ -207,9 +279,17 @@ const useAPI = ({
[],
);

const makeRequestWithTimer = requestWithTimer(makeRequest);
const makeLightRequestWithTimer = requestWithTimer(makeLightRequest);

const isDevelopment = process.env.NODE_ENV === 'development';

return {
loading,
makeRequest,
makeRequest: isDevelopment ? makeRequestWithTimer : makeRequest,
makeLightRequest: isDevelopment
? makeLightRequestWithTimer
: makeLightRequest,
createRequest,
errors,
};
Expand Down
1 change: 0 additions & 1 deletion frontend/src/interfaces/uiConfig.ts
Expand Up @@ -65,7 +65,6 @@ export type UiFlags = {
doraMetrics?: boolean;
variantTypeNumber?: boolean;
privateProjects?: boolean;
accessOverview?: boolean;
dependentFeatures?: boolean;
banners?: boolean;
disableEnvsOnRevive?: boolean;
Expand Down

0 comments on commit c9a3f33

Please sign in to comment.