Skip to content

Commit

Permalink
refactor: implement an event timeline context and provider
Browse files Browse the repository at this point in the history
  • Loading branch information
nunogois committed Oct 1, 2024
1 parent fe5e2ae commit 1474976
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 118 deletions.
28 changes: 4 additions & 24 deletions frontend/src/component/events/EventTimeline/EventTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { startOfDay, sub } from 'date-fns';
import { useEventSearch } from 'hooks/api/getters/useEventSearch/useEventSearch';
import { EventTimelineEventGroup } from './EventTimelineEventGroup/EventTimelineEventGroup';
import { EventTimelineHeader } from './EventTimelineHeader/EventTimelineHeader';
import type { TimeSpanOption } from './useEventTimeline';
import { useMemo } from 'react';
import { useSignalQuery } from 'hooks/api/getters/useSignalQuery/useSignalQuery';
import type { ISignalQuerySignal } from 'interfaces/signal';
import type { IEnvironment } from 'interfaces/environments';
import { useEventTimelineContext } from './EventTimelineContext';

export type TimelineEventType = 'signal' | EventSchemaType;

Expand Down Expand Up @@ -157,21 +157,8 @@ const getTimelineEvent = (
}
};

interface IEventTimelineProps {
timeSpan: TimeSpanOption;
environment: IEnvironment | undefined;
setTimeSpan: (timeSpan: TimeSpanOption) => void;
setEnvironment: (environment: IEnvironment) => void;
setOpen: (open: boolean) => void;
}

export const EventTimeline = ({
timeSpan,
environment,
setTimeSpan,
setEnvironment,
setOpen,
}: IEventTimelineProps) => {
export const EventTimeline = () => {
const { timeSpan, environment } = useEventTimelineContext();
const endDate = new Date();
const startDate = sub(endDate, timeSpan.value);
const endTime = endDate.getTime();
Expand Down Expand Up @@ -246,14 +233,7 @@ export const EventTimeline = ({
return (
<>
<StyledRow>
<EventTimelineHeader
totalEvents={events.length}
timeSpan={timeSpan}
setTimeSpan={setTimeSpan}
environment={environment}
setEnvironment={setEnvironment}
setOpen={setOpen}
/>
<EventTimelineHeader totalEvents={events.length} />
</StyledRow>
<StyledTimelineBody>
<StyledTimelineContainer>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createContext, useContext } from 'react';
import type { IEventTimelineContext } from './EventTimelineProvider';

export const EventTimelineContext = createContext<
IEventTimelineContext | undefined
>(undefined);

export const useEventTimelineContext = (): IEventTimelineContext => {
const context = useContext(EventTimelineContext);

if (!context) {
throw new Error(
'useEventTimelineContext must be used within a EventTimelineProvider',
);
}

return context;
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import {
} from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
import type { IEnvironment } from 'interfaces/environments';
import { useEffect, useMemo } from 'react';
import { type TimeSpanOption, timeSpanOptions } from '../useEventTimeline';
import { timeSpanOptions } from '../EventTimelineProvider';
import CloseIcon from '@mui/icons-material/Close';
import { useEventTimelineContext } from '../EventTimelineContext';

const StyledCol = styled('div')(({ theme }) => ({
display: 'flex',
Expand All @@ -36,21 +36,13 @@ const StyledTimelineEventsCount = styled('span')(({ theme }) => ({

interface IEventTimelineHeaderProps {
totalEvents: number;
timeSpan: TimeSpanOption;
setTimeSpan: (timeSpan: TimeSpanOption) => void;
environment: IEnvironment | undefined;
setEnvironment: (environment: IEnvironment) => void;
setOpen: (open: boolean) => void;
}

export const EventTimelineHeader = ({
totalEvents,
timeSpan,
setTimeSpan,
environment,
setEnvironment,
setOpen,
}: IEventTimelineHeaderProps) => {
const { timeSpan, environment, setOpen, setTimeSpan, setEnvironment } =
useEventTimelineContext();
const { environments } = useEnvironments();

const activeEnvironments = useMemo(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
import type { ReactNode } from 'react';
import { EventTimelineContext } from './EventTimelineContext';
import { useLocalStorageState } from 'hooks/useLocalStorageState';
import type { IEnvironment } from 'interfaces/environments';

export type TimeSpanOption = {
type TimeSpanOption = {
key: string;
label: string;
value: Duration;
markers: string[];
};

type EventTimelineState = {
open: boolean;
timeSpan: TimeSpanOption;
environment?: IEnvironment;
signalsAlertSeen?: boolean;
};

type EventTimelineStateSetters = {
setOpen: (open: boolean) => void;
setTimeSpan: (timeSpan: TimeSpanOption) => void;
setEnvironment: (environment: IEnvironment) => void;
setSignalsAlertSeen: (seen: boolean) => void;
};

export interface IEventTimelineContext
extends EventTimelineState,
EventTimelineStateSetters {}

export const timeSpanOptions: TimeSpanOption[] = [
{
key: '30m',
Expand Down Expand Up @@ -57,18 +77,18 @@ export const timeSpanOptions: TimeSpanOption[] = [
},
];

type EventTimelineState = {
open: boolean;
timeSpan: TimeSpanOption;
environment?: IEnvironment;
};

const defaultState: EventTimelineState = {
open: false,
timeSpan: timeSpanOptions[0],
};

export const useEventTimeline = () => {
interface IEventTimelineProviderProps {
children: ReactNode;
}

export const EventTimelineProvider = ({
children,
}: IEventTimelineProviderProps) => {
const [state, setState] = useLocalStorageState<EventTimelineState>(
'event-timeline:v1',
defaultState,
Expand All @@ -81,12 +101,20 @@ export const useEventTimeline = () => {
setState((prevState) => ({ ...prevState, [key]: value }));
};

return {
const contextValue: IEventTimelineContext = {
...state,
setOpen: (open: boolean) => setField('open', open),
setTimeSpan: (timeSpan: TimeSpanOption) =>
setField('timeSpan', timeSpan),
setEnvironment: (environment: IEnvironment) =>
setField('environment', environment),
setSignalsAlertSeen: (seen: boolean) =>
setField('signalsAlertSeen', seen),
};

return (
<EventTimelineContext.Provider value={contextValue}>
{children}
</EventTimelineContext.Provider>
);
};
40 changes: 7 additions & 33 deletions frontend/src/component/layout/MainLayout/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import { DraftBanner } from './DraftBanner/DraftBanner';
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
import { NavigationSidebar } from './NavigationSidebar/NavigationSidebar';
import { useUiFlag } from 'hooks/useUiFlag';
import { useEventTimeline } from 'component/events/EventTimeline/useEventTimeline';
import { MainLayoutEventTimeline } from './MainLayoutEventTimeline';
import { EventTimelineProvider } from 'component/events/EventTimeline/EventTimelineProvider';

interface IMainLayoutProps {
children: ReactNode;
Expand Down Expand Up @@ -112,20 +112,11 @@ const MainLayoutContentContainer = styled('div')(({ theme }) => ({

export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
({ children }, ref) => {
const { uiConfig, isOss } = useUiConfig();
const { uiConfig } = useUiConfig();
const projectId = useOptionalPathParam('projectId');
const { isChangeRequestConfiguredInAnyEnv } = useChangeRequestsEnabled(
projectId || '',
);
const eventTimeline = useUiFlag('eventTimeline') && !isOss();
const {
open: showTimeline,
timeSpan,
environment,
setOpen: setShowTimeline,
setTimeSpan,
setEnvironment,
} = useEventTimeline();

const sidebarNavigationEnabled = useUiFlag('navigationSidebar');
const StyledMainLayoutContent = sidebarNavigationEnabled
Expand All @@ -135,22 +126,12 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
const isSmallScreen = useMediaQuery(theme.breakpoints.down('lg'));

return (
<>
<EventTimelineProvider>
<SkipNavLink />
<ConditionallyRender
condition={sidebarNavigationEnabled}
show={
<Header
showTimeline={showTimeline}
setShowTimeline={setShowTimeline}
/>
}
elseShow={
<OldHeader
showTimeline={showTimeline}
setShowTimeline={setShowTimeline}
/>
}
show={<Header />}
elseShow={<OldHeader />}
/>

<SkipNavTarget />
Expand Down Expand Up @@ -185,14 +166,7 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
minWidth: 0,
}}
>
<MainLayoutEventTimeline
open={eventTimeline && showTimeline}
setOpen={setShowTimeline}
timeSpan={timeSpan}
setTimeSpan={setTimeSpan}
environment={environment}
setEnvironment={setEnvironment}
/>
<MainLayoutEventTimeline />

<StyledMainLayoutContent>
<MainLayoutContentContainer ref={ref}>
Expand Down Expand Up @@ -222,7 +196,7 @@ export const MainLayout = forwardRef<HTMLDivElement, IMainLayoutProps>(
</MainLayoutContentWrapper>
<Footer />
</MainLayoutContainer>
</>
</EventTimelineProvider>
);
},
);
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Box, styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { EventTimeline } from 'component/events/EventTimeline/EventTimeline';
import type { TimeSpanOption } from 'component/events/EventTimeline/useEventTimeline';
import type { IEnvironment } from 'interfaces/environments';
import { useEventTimelineContext } from 'component/events/EventTimeline/EventTimelineContext';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useUiFlag } from 'hooks/useUiFlag';
import { useEffect, useState } from 'react';

const StyledEventTimelineSlider = styled(Box)(({ theme }) => ({
Expand All @@ -17,25 +18,14 @@ const StyledEventTimelineWrapper = styled(Box)(({ theme }) => ({
padding: theme.spacing(1.5, 2),
}));

interface IMainLayoutEventTimelineProps {
open: boolean;
timeSpan: TimeSpanOption;
environment: IEnvironment | undefined;
setTimeSpan: (timeSpan: TimeSpanOption) => void;
setEnvironment: (environment: IEnvironment) => void;
setOpen: (open: boolean) => void;
}

export const MainLayoutEventTimeline = ({
open,
timeSpan,
environment,
setTimeSpan,
setEnvironment,
setOpen,
}: IMainLayoutEventTimelineProps) => {
export const MainLayoutEventTimeline = () => {
const { isOss } = useUiConfig();
const { open: showTimeline } = useEventTimelineContext();
const eventTimelineEnabled = useUiFlag('eventTimeline') && !isOss();
const [isInitialLoad, setIsInitialLoad] = useState(true);

const open = showTimeline && eventTimelineEnabled;

useEffect(() => {
setIsInitialLoad(false);
}, []);
Expand All @@ -52,15 +42,7 @@ export const MainLayoutEventTimeline = ({
<StyledEventTimelineWrapper>
<ConditionallyRender
condition={open}
show={
<EventTimeline
timeSpan={timeSpan}
environment={environment}
setTimeSpan={setTimeSpan}
setEnvironment={setEnvironment}
setOpen={setOpen}
/>
}
show={<EventTimeline />}
/>
</StyledEventTimelineWrapper>
</StyledEventTimelineSlider>
Expand Down
10 changes: 4 additions & 6 deletions frontend/src/component/menu/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import InviteLinkButton from './InviteLink/InviteLinkButton/InviteLinkButton';
import { useUiFlag } from 'hooks/useUiFlag';
import { CommandBar } from 'component/commandBar/CommandBar';
import LinearScaleIcon from '@mui/icons-material/LinearScale';
import { useEventTimelineContext } from 'component/events/EventTimeline/EventTimelineContext';

const HeaderComponent = styled(AppBar)(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
Expand Down Expand Up @@ -97,12 +98,7 @@ const StyledIconButton = styled(IconButton)<{
},
}));

interface IHeaderProps {
showTimeline: boolean;
setShowTimeline: (show: boolean) => void;
}

const Header = ({ showTimeline, setShowTimeline }: IHeaderProps) => {
const Header = () => {
const { onSetThemeMode, themeMode } = useThemeMode();
const theme = useTheme();

Expand All @@ -113,6 +109,8 @@ const Header = ({ showTimeline, setShowTimeline }: IHeaderProps) => {
const toggleDrawer = () => setOpenDrawer((prev) => !prev);
const celebatoryUnleash = useUiFlag('celebrateUnleash');
const eventTimeline = useUiFlag('eventTimeline') && !isOss();
const { open: showTimeline, setOpen: setShowTimeline } =
useEventTimelineContext();

const routes = getRoutes();
const adminRoutes = useAdminRoutes();
Expand Down
10 changes: 4 additions & 6 deletions frontend/src/component/menu/Header/OldHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { useAdminRoutes } from 'component/admin/useAdminRoutes';
import InviteLinkButton from './InviteLink/InviteLinkButton/InviteLinkButton';
import { useUiFlag } from 'hooks/useUiFlag';
import LinearScaleIcon from '@mui/icons-material/LinearScale';
import { useEventTimelineContext } from 'component/events/EventTimeline/EventTimelineContext';

const HeaderComponent = styled(AppBar)(({ theme }) => ({
backgroundColor: theme.palette.background.paper,
Expand Down Expand Up @@ -131,12 +132,7 @@ const StyledIconButton = styled(IconButton)<{
},
}));

interface IOldHeaderProps {
showTimeline: boolean;
setShowTimeline: (show: boolean) => void;
}

const OldHeader = ({ showTimeline, setShowTimeline }: IOldHeaderProps) => {
const OldHeader = () => {
const { onSetThemeMode, themeMode } = useThemeMode();
const theme = useTheme();
const adminId = useId();
Expand All @@ -153,6 +149,8 @@ const OldHeader = ({ showTimeline, setShowTimeline }: IOldHeaderProps) => {
const onConfigureClose = () => setConfigRef(null);
const celebatoryUnleash = useUiFlag('celebrateUnleash');
const eventTimeline = useUiFlag('eventTimeline') && !isOss();
const { open: showTimeline, setOpen: setShowTimeline } =
useEventTimelineContext();

const routes = getRoutes();
const adminRoutes = useAdminRoutes();
Expand Down

0 comments on commit 1474976

Please sign in to comment.