mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
fix: linter rule for hooks (#9660)
This commit is contained in:
parent
a9490e6fe4
commit
6e947a8ba6
15
biome.json
15
biome.json
@ -11,7 +11,8 @@
|
|||||||
"noUnsafeOptionalChaining": "off",
|
"noUnsafeOptionalChaining": "off",
|
||||||
"useExhaustiveDependencies": "off",
|
"useExhaustiveDependencies": "off",
|
||||||
"noUnusedImports": "warn",
|
"noUnusedImports": "warn",
|
||||||
"useJsxKeyInIterable": "off"
|
"useJsxKeyInIterable": "off",
|
||||||
|
"useHookAtTopLevel": "error"
|
||||||
},
|
},
|
||||||
"complexity": {
|
"complexity": {
|
||||||
"noBannedTypes": "off",
|
"noBannedTypes": "off",
|
||||||
@ -100,5 +101,17 @@
|
|||||||
"formatter": {
|
"formatter": {
|
||||||
"indentWidth": 2
|
"indentWidth": 2
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"include": ["src/**"],
|
||||||
|
"linter": {
|
||||||
|
"rules": {
|
||||||
|
"correctness": {
|
||||||
|
"useHookAtTopLevel": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
@ -45,8 +45,7 @@ export const BillingDetailsPAYG = ({
|
|||||||
const billableUsers = Math.max(eligibleUsers.length, minSeats);
|
const billableUsers = Math.max(eligibleUsers.length, minSeats);
|
||||||
const usersCost = seatPrice * billableUsers;
|
const usersCost = seatPrice * billableUsers;
|
||||||
|
|
||||||
const includedTraffic = BILLING_INCLUDED_REQUESTS;
|
const overageCost = useOverageCost(BILLING_INCLUDED_REQUESTS);
|
||||||
const overageCost = useOverageCost(includedTraffic);
|
|
||||||
|
|
||||||
const totalCost = usersCost + overageCost;
|
const totalCost = usersCost + overageCost;
|
||||||
|
|
||||||
|
@ -52,8 +52,7 @@ export const BillingDetailsPro = ({
|
|||||||
const freeAssigned = Math.min(eligibleUsers.length, seats);
|
const freeAssigned = Math.min(eligibleUsers.length, seats);
|
||||||
const paidAssigned = eligibleUsers.length - freeAssigned;
|
const paidAssigned = eligibleUsers.length - freeAssigned;
|
||||||
const paidAssignedPrice = seatPrice * paidAssigned;
|
const paidAssignedPrice = seatPrice * paidAssigned;
|
||||||
const includedTraffic = BILLING_INCLUDED_REQUESTS;
|
const overageCost = useOverageCost(BILLING_INCLUDED_REQUESTS);
|
||||||
const overageCost = useOverageCost(includedTraffic);
|
|
||||||
|
|
||||||
const totalCost = planPrice + paidAssignedPrice + overageCost;
|
const totalCost = planPrice + paidAssignedPrice + overageCost;
|
||||||
|
|
||||||
|
@ -9,10 +9,6 @@ import { BILLING_TRAFFIC_PRICE } from './BillingPlan';
|
|||||||
import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
|
import { useInstanceStatus } from 'hooks/api/getters/useInstanceStatus/useInstanceStatus';
|
||||||
|
|
||||||
export const useOverageCost = (includedTraffic: number) => {
|
export const useOverageCost = (includedTraffic: number) => {
|
||||||
if (!includedTraffic) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const formatDate = (date: Date) => format(date, 'yyyy-MM-dd');
|
const formatDate = (date: Date) => format(date, 'yyyy-MM-dd');
|
||||||
const from = formatDate(startOfMonth(now));
|
const from = formatDate(startOfMonth(now));
|
||||||
|
@ -12,7 +12,10 @@ import type {
|
|||||||
} from '../../changeRequest.types';
|
} from '../../changeRequest.types';
|
||||||
import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip';
|
import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip';
|
||||||
import ErrorIcon from '@mui/icons-material/Error';
|
import ErrorIcon from '@mui/icons-material/Error';
|
||||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
import {
|
||||||
|
type ILocationSettings,
|
||||||
|
useLocationSettings,
|
||||||
|
} from 'hooks/useLocationSettings';
|
||||||
import { formatDateYMDHMS } from 'utils/formatDate';
|
import { formatDateYMDHMS } from 'utils/formatDate';
|
||||||
|
|
||||||
export type ISuggestChangeTimelineProps =
|
export type ISuggestChangeTimelineProps =
|
||||||
@ -99,6 +102,7 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
|
|||||||
data = steps;
|
data = steps;
|
||||||
}
|
}
|
||||||
const activeIndex = data.findIndex((item) => item === state);
|
const activeIndex = data.findIndex((item) => item === state);
|
||||||
|
const { locationSettings } = useLocationSettings();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledPaper elevation={0}>
|
<StyledPaper elevation={0}>
|
||||||
@ -106,7 +110,10 @@ export const ChangeRequestTimeline: FC<ISuggestChangeTimelineProps> = ({
|
|||||||
<StyledTimeline>
|
<StyledTimeline>
|
||||||
{data.map((title, index) => {
|
{data.map((title, index) => {
|
||||||
if (schedule && title === 'Scheduled') {
|
if (schedule && title === 'Scheduled') {
|
||||||
return createTimelineScheduleItem(schedule);
|
return createTimelineScheduleItem(
|
||||||
|
schedule,
|
||||||
|
locationSettings,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const color = determineColor(
|
const color = determineColor(
|
||||||
@ -195,9 +202,10 @@ export const getScheduleProps = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTimelineScheduleItem = (schedule: ChangeRequestSchedule) => {
|
const createTimelineScheduleItem = (
|
||||||
const { locationSettings } = useLocationSettings();
|
schedule: ChangeRequestSchedule,
|
||||||
|
locationSettings: ILocationSettings,
|
||||||
|
) => {
|
||||||
const time = formatDateYMDHMS(
|
const time = formatDateYMDHMS(
|
||||||
new Date(schedule.scheduledAt),
|
new Date(schedule.scheduledAt),
|
||||||
locationSettings?.locale,
|
locationSettings?.locale,
|
||||||
|
@ -169,9 +169,8 @@ export const RecentlyVisitedFeatureButton = ({
|
|||||||
featureId: string;
|
featureId: string;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const onItemClick = () => {
|
|
||||||
const { trackEvent } = usePlausibleTracker();
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
const onItemClick = () => {
|
||||||
trackEvent('command-bar', {
|
trackEvent('command-bar', {
|
||||||
props: {
|
props: {
|
||||||
eventType: `click`,
|
eventType: `click`,
|
||||||
|
@ -5,5 +5,6 @@ const SearchHighlightContext = createContext('');
|
|||||||
export const SearchHighlightProvider = SearchHighlightContext.Provider;
|
export const SearchHighlightProvider = SearchHighlightContext.Provider;
|
||||||
|
|
||||||
export const useSearchHighlightContext = (): { searchQuery: string } => {
|
export const useSearchHighlightContext = (): { searchQuery: string } => {
|
||||||
return { searchQuery: useContext(SearchHighlightContext) };
|
const searchQuery = useContext(SearchHighlightContext);
|
||||||
|
return { searchQuery };
|
||||||
};
|
};
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { screen } from '@testing-library/react';
|
import { screen } from '@testing-library/react';
|
||||||
import { render } from 'utils/testRenderer';
|
import { render } from 'utils/testRenderer';
|
||||||
import { FeatureOverviewCell as makeFeatureOverviewCell } from './FeatureOverviewCell';
|
import { createFeatureOverviewCell } from './FeatureOverviewCell';
|
||||||
|
|
||||||
const noOp = () => {};
|
const noOp = () => {};
|
||||||
|
|
||||||
test('Display full overview information', () => {
|
test('Display full overview information', () => {
|
||||||
const FeatureOverviewCell = makeFeatureOverviewCell(noOp, noOp);
|
const FeatureOverviewCell = createFeatureOverviewCell(noOp, noOp);
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<FeatureOverviewCell
|
<FeatureOverviewCell
|
||||||
@ -43,7 +43,7 @@ test('Display full overview information', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Display minimal overview information', () => {
|
test('Display minimal overview information', () => {
|
||||||
const FeatureOverviewCell = makeFeatureOverviewCell(noOp, noOp);
|
const FeatureOverviewCell = createFeatureOverviewCell(noOp, noOp);
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<FeatureOverviewCell
|
<FeatureOverviewCell
|
||||||
@ -69,7 +69,7 @@ test('Display minimal overview information', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('show archived information', () => {
|
test('show archived information', () => {
|
||||||
const FeatureOverviewCell = makeFeatureOverviewCell(noOp, noOp);
|
const FeatureOverviewCell = createFeatureOverviewCell(noOp, noOp);
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<FeatureOverviewCell
|
<FeatureOverviewCell
|
||||||
|
@ -436,7 +436,7 @@ const SecondaryFeatureInfo: FC<{
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FeatureOverviewCell =
|
export const createFeatureOverviewCell =
|
||||||
(
|
(
|
||||||
onTagClick: (tag: string) => void,
|
onTagClick: (tag: string) => void,
|
||||||
onFlagTypeClick: (type: string) => void,
|
onFlagTypeClick: (type: string) => void,
|
||||||
|
@ -6,12 +6,7 @@ const allFilterKeys = ['from', 'to', 'createdBy', 'type', 'project', 'feature'];
|
|||||||
allFilterKeys.sort();
|
allFilterKeys.sort();
|
||||||
|
|
||||||
test('When you have no projects or flags, you should not get a project or flag filters', () => {
|
test('When you have no projects or flags, you should not get a project or flag filters', () => {
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() => useEventLogFilters([], []));
|
||||||
useEventLogFilters(
|
|
||||||
() => ({ projects: [] }),
|
|
||||||
() => ({ features: [] }),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
const filterKeys = result.current.map((filter) => filter.filterKey);
|
const filterKeys = result.current.map((filter) => filter.filterKey);
|
||||||
filterKeys.sort();
|
filterKeys.sort();
|
||||||
|
|
||||||
@ -22,9 +17,9 @@ test('When you have no projects or flags, you should not get a project or flag f
|
|||||||
test('When you have no projects, you should not get a project filter', () => {
|
test('When you have no projects, you should not get a project filter', () => {
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useEventLogFilters(
|
useEventLogFilters(
|
||||||
() => ({ projects: [] }),
|
[],
|
||||||
// @ts-expect-error: omitting other properties we don't need
|
// @ts-expect-error: omitting other properties we don't need
|
||||||
() => ({ features: [{ name: 'flag' }] }),
|
[{ name: 'flag' }],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const filterKeys = result.current.map((filter) => filter.filterKey);
|
const filterKeys = result.current.map((filter) => filter.filterKey);
|
||||||
@ -35,10 +30,7 @@ test('When you have no projects, you should not get a project filter', () => {
|
|||||||
|
|
||||||
test('When you have only one project, you should not get a project filter', () => {
|
test('When you have only one project, you should not get a project filter', () => {
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useEventLogFilters(
|
useEventLogFilters([{ id: 'a', name: 'A' }], []),
|
||||||
() => ({ projects: [{ id: 'a', name: 'A' }] }),
|
|
||||||
() => ({ features: [] }),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
const filterKeys = result.current.map((filter) => filter.filterKey);
|
const filterKeys = result.current.map((filter) => filter.filterKey);
|
||||||
filterKeys.sort();
|
filterKeys.sort();
|
||||||
@ -49,13 +41,11 @@ test('When you have only one project, you should not get a project filter', () =
|
|||||||
test('When you have two one project, you should not get a project filter', () => {
|
test('When you have two one project, you should not get a project filter', () => {
|
||||||
const { result } = renderHook(() =>
|
const { result } = renderHook(() =>
|
||||||
useEventLogFilters(
|
useEventLogFilters(
|
||||||
() => ({
|
[
|
||||||
projects: [
|
|
||||||
{ id: 'a', name: 'A' },
|
{ id: 'a', name: 'A' },
|
||||||
{ id: 'b', name: 'B' },
|
{ id: 'b', name: 'B' },
|
||||||
],
|
],
|
||||||
}),
|
[],
|
||||||
() => ({ features: [] }),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const filterKeys = result.current.map((filter) => filter.filterKey);
|
const filterKeys = result.current.map((filter) => filter.filterKey);
|
||||||
|
@ -6,24 +6,15 @@ import {
|
|||||||
} from 'component/filter/Filters/Filters';
|
} from 'component/filter/Filters/Filters';
|
||||||
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
||||||
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
||||||
import {
|
import { EventSchemaType, type FeatureSearchResponseSchema } from 'openapi';
|
||||||
EventSchemaType,
|
|
||||||
type FeatureSearchResponseSchema,
|
|
||||||
type SearchFeaturesParams,
|
|
||||||
} from 'openapi';
|
|
||||||
import type { ProjectSchema } from 'openapi';
|
import type { ProjectSchema } from 'openapi';
|
||||||
import { useEventCreators } from 'hooks/api/getters/useEventCreators/useEventCreators';
|
import { useEventCreators } from 'hooks/api/getters/useEventCreators/useEventCreators';
|
||||||
|
|
||||||
export const useEventLogFilters = (
|
export const useEventLogFilters = (
|
||||||
projectsHook: () => { projects: ProjectSchema[] },
|
projects: ProjectSchema[],
|
||||||
featuresHook: (params: SearchFeaturesParams) => {
|
features: FeatureSearchResponseSchema[],
|
||||||
features: FeatureSearchResponseSchema[];
|
|
||||||
},
|
|
||||||
) => {
|
) => {
|
||||||
const { projects } = projectsHook();
|
|
||||||
const { features } = featuresHook({});
|
|
||||||
const { eventCreators } = useEventCreators();
|
const { eventCreators } = useEventCreators();
|
||||||
|
|
||||||
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
|
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const projectOptions =
|
const projectOptions =
|
||||||
@ -124,22 +115,6 @@ export const useEventLogFilters = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
type LogType = 'flag' | 'project' | 'global';
|
type LogType = 'flag' | 'project' | 'global';
|
||||||
const useEventLogFiltersFromLogType = (logType: LogType) => {
|
|
||||||
switch (logType) {
|
|
||||||
case 'flag':
|
|
||||||
return useEventLogFilters(
|
|
||||||
() => ({ projects: [] }),
|
|
||||||
() => ({ features: [] }),
|
|
||||||
);
|
|
||||||
case 'project':
|
|
||||||
return useEventLogFilters(
|
|
||||||
() => ({ projects: [] }),
|
|
||||||
useFeatureSearch,
|
|
||||||
);
|
|
||||||
case 'global':
|
|
||||||
return useEventLogFilters(useProjects, useFeatureSearch);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
type EventLogFiltersProps = {
|
type EventLogFiltersProps = {
|
||||||
logType: LogType;
|
logType: LogType;
|
||||||
@ -154,7 +129,14 @@ export const EventLogFilters: FC<EventLogFiltersProps> = ({
|
|||||||
state,
|
state,
|
||||||
onChange,
|
onChange,
|
||||||
}) => {
|
}) => {
|
||||||
const availableFilters = useEventLogFiltersFromLogType(logType);
|
const { features } = useFeatureSearch({});
|
||||||
|
const { projects } = useProjects();
|
||||||
|
const featuresToFilter = logType !== 'flag' ? features : [];
|
||||||
|
const projectsToFilter = logType === 'global' ? projects : [];
|
||||||
|
const availableFilters = useEventLogFilters(
|
||||||
|
projectsToFilter,
|
||||||
|
featuresToFilter,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Filters
|
<Filters
|
||||||
|
@ -89,14 +89,14 @@ export const EnvironmentAccordionBody = ({
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!featureEnvironment) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pageSize = 20;
|
const pageSize = 20;
|
||||||
const { page, pages, setPageIndex, pageIndex } =
|
const { page, pages, setPageIndex, pageIndex } =
|
||||||
usePagination<IFeatureStrategy>(strategies, pageSize);
|
usePagination<IFeatureStrategy>(strategies, pageSize);
|
||||||
|
|
||||||
|
if (!featureEnvironment) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const onReorder = async (payload: { id: string; sortOrder: number }[]) => {
|
const onReorder = async (payload: { id: string; sortOrder: number }[]) => {
|
||||||
try {
|
try {
|
||||||
await setStrategiesSortOrder(
|
await setStrategiesSortOrder(
|
||||||
|
@ -101,14 +101,14 @@ const EnvironmentAccordionBody = ({
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!featureEnvironment) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pageSize = 20;
|
const pageSize = 20;
|
||||||
const { page, pages, setPageIndex, pageIndex } =
|
const { page, pages, setPageIndex, pageIndex } =
|
||||||
usePagination<IFeatureStrategy>(strategies, pageSize);
|
usePagination<IFeatureStrategy>(strategies, pageSize);
|
||||||
|
|
||||||
|
if (!featureEnvironment) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const onReorder = async (payload: { id: string; sortOrder: number }[]) => {
|
const onReorder = async (payload: { id: string; sortOrder: number }[]) => {
|
||||||
try {
|
try {
|
||||||
await setStrategiesSortOrder(
|
await setStrategiesSortOrder(
|
||||||
|
@ -11,7 +11,7 @@ import { TagTypeSelect } from './TagTypeSelect';
|
|||||||
import { type TagOption, TagsInput } from './TagsInput';
|
import { type TagOption, TagsInput } from './TagsInput';
|
||||||
import useTags from 'hooks/api/getters/useTags/useTags';
|
import useTags from 'hooks/api/getters/useTags/useTags';
|
||||||
import useTagTypes from 'hooks/api/getters/useTagTypes/useTagTypes';
|
import useTagTypes from 'hooks/api/getters/useTagTypes/useTagTypes';
|
||||||
import type { ITag, ITagType } from 'interfaces/tags';
|
import type { ITagType } from 'interfaces/tags';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import useTagApi from 'hooks/api/actions/useTagApi/useTagApi';
|
import useTagApi from 'hooks/api/actions/useTagApi/useTagApi';
|
||||||
import type { TagSchema } from 'openapi';
|
import type { TagSchema } from 'openapi';
|
||||||
|
@ -35,7 +35,7 @@ import { useDefaultColumnVisibility } from './hooks/useDefaultColumnVisibility';
|
|||||||
import { TableEmptyState } from './TableEmptyState/TableEmptyState';
|
import { TableEmptyState } from './TableEmptyState/TableEmptyState';
|
||||||
import { useRowActions } from './hooks/useRowActions';
|
import { useRowActions } from './hooks/useRowActions';
|
||||||
import { useSelectedData } from './hooks/useSelectedData';
|
import { useSelectedData } from './hooks/useSelectedData';
|
||||||
import { FeatureOverviewCell } from 'component/common/Table/cells/FeatureOverviewCell/FeatureOverviewCell';
|
import { createFeatureOverviewCell } from 'component/common/Table/cells/FeatureOverviewCell/FeatureOverviewCell';
|
||||||
import {
|
import {
|
||||||
useProjectFeatureSearch,
|
useProjectFeatureSearch,
|
||||||
useProjectFeatureSearchActions,
|
useProjectFeatureSearchActions,
|
||||||
@ -213,7 +213,7 @@ export const ProjectFeatureToggles = ({
|
|||||||
columnHelper.accessor('name', {
|
columnHelper.accessor('name', {
|
||||||
id: 'name',
|
id: 'name',
|
||||||
header: 'Name',
|
header: 'Name',
|
||||||
cell: FeatureOverviewCell(onTagClick, onFlagTypeClick),
|
cell: createFeatureOverviewCell(onTagClick, onFlagTypeClick),
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('createdAt', {
|
columnHelper.accessor('createdAt', {
|
||||||
|
@ -2,7 +2,6 @@ import { useMemo, useState, type VFC } from 'react';
|
|||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import { ManageBulkTagsDialog } from 'component/feature/FeatureView/FeatureOverview/ManageTagsDialog/ManageBulkTagsDialog';
|
import { ManageBulkTagsDialog } from 'component/feature/FeatureView/FeatureOverview/ManageTagsDialog/ManageBulkTagsDialog';
|
||||||
import type { FeatureSchema, TagSchema } from 'openapi';
|
import type { FeatureSchema, TagSchema } from 'openapi';
|
||||||
import type { ITag } from 'interfaces/tags';
|
|
||||||
import useTagApi from 'hooks/api/actions/useTagApi/useTagApi';
|
import useTagApi from 'hooks/api/actions/useTagApi/useTagApi';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
|
@ -38,10 +38,10 @@ interface IProjectStatsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ProjectInsightsStats = ({ stats }: IProjectStatsProps) => {
|
export const ProjectInsightsStats = ({ stats }: IProjectStatsProps) => {
|
||||||
|
const projectId = useRequiredPathParam('projectId');
|
||||||
if (Object.keys(stats).length === 0) {
|
if (Object.keys(stats).length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const projectId = useRequiredPathParam('projectId');
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
avgTimeToProdCurrentWindow,
|
avgTimeToProdCurrentWindow,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useContext, useMemo, useState, type VFC } from 'react';
|
import { useContext, useMemo, useState, type VFC as FC } from 'react';
|
||||||
import { type HeaderGroup, useGlobalFilter, useTable } from 'react-table';
|
import { type HeaderGroup, useGlobalFilter, useTable } from 'react-table';
|
||||||
import { Alert, Box, styled, Typography } from '@mui/material';
|
import { Alert, Box, styled, Typography } from '@mui/material';
|
||||||
import {
|
import {
|
||||||
@ -41,8 +41,9 @@ const StyledBox = styled(Box)(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const ChangeRequestTable: VFC = () => {
|
export const ChangeRequestTable: FC = () => {
|
||||||
const { trackEvent } = usePlausibleTracker();
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
const { hasAccess } = useContext(AccessContext);
|
||||||
const [dialogState, setDialogState] = useState<{
|
const [dialogState, setDialogState] = useState<{
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
enableEnvironment: string;
|
enableEnvironment: string;
|
||||||
@ -139,13 +140,8 @@ export const ChangeRequestTable: VFC = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Header: 'Required approvals',
|
Header: 'Required approvals',
|
||||||
Cell: ({ row: { original } }: any) => {
|
Cell: ({ row: { original } }: any) =>
|
||||||
const { hasAccess } = useContext(AccessContext);
|
original.changeRequestEnabled ? (
|
||||||
|
|
||||||
return (
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={original.changeRequestEnabled}
|
|
||||||
show={
|
|
||||||
<StyledBox data-loading>
|
<StyledBox data-loading>
|
||||||
<GeneralSelect
|
<GeneralSelect
|
||||||
sx={{ width: '140px', marginLeft: 1 }}
|
sx={{ width: '140px', marginLeft: 1 }}
|
||||||
@ -166,16 +162,11 @@ export const ChangeRequestTable: VFC = () => {
|
|||||||
projectId,
|
projectId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
IconComponent={
|
IconComponent={KeyboardArrowDownOutlined}
|
||||||
KeyboardArrowDownOutlined
|
|
||||||
}
|
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</StyledBox>
|
</StyledBox>
|
||||||
}
|
) : null,
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
width: 100,
|
width: 100,
|
||||||
disableGlobalFilter: true,
|
disableGlobalFilter: true,
|
||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user