Skip to content

Commit

Permalink
feat(logs): button update time format (#404)
Browse files Browse the repository at this point in the history
  • Loading branch information
RemiBonnet committed Dec 13, 2022
1 parent b4f8e29 commit 0968851
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 24 deletions.
7 changes: 5 additions & 2 deletions libs/pages/logs/deployment/src/lib/ui/row/row.tsx
@@ -1,6 +1,7 @@
import { EnvironmentLogs } from 'qovery-typescript-axios'
import { useContext } from 'react'
import { LogsType } from '@qovery/shared/enums'
import { CopyToClipboard, Tooltip } from '@qovery/shared/ui'
import { CopyToClipboard, Tooltip, UpdateTimeContext } from '@qovery/shared/ui'
import { dateFullFormat } from '@qovery/shared/utils'

export interface RowProps {
Expand All @@ -11,6 +12,8 @@ export interface RowProps {
export function Row(props: RowProps) {
const { index, data } = props

const { utc } = useContext(UpdateTimeContext)

const type = data.type
const step = data.details?.stage?.step

Expand Down Expand Up @@ -74,7 +77,7 @@ export function Row(props: RowProps) {
)}
</div>
<div data-testid="cell-date" className={`py-1 px-2 font-code shrink-0 w-[154px] ${colorsCellClassName()}`}>
{dateFullFormat(data.timestamp)}
{dateFullFormat(data.timestamp, utc ? 'UTC' : undefined)}
</div>
<div
data-testid="cell-scope"
Expand Down
1 change: 1 addition & 0 deletions libs/shared/ui/src/index.ts
@@ -1,3 +1,4 @@
export * from './lib/components/layouts/layout-logs/update-time-context/update-time-context'
export * from './lib/components/scroll-shadow-wrapper/scroll-shadow-wrapper'
export * from './lib/components/modal-alert/use-modal-alert/use-modal-alert'
export * from './lib/components/modal-alert/modal-alert'
Expand Down
Expand Up @@ -19,6 +19,7 @@ export enum ButtonStyle {
TAB = 'tab',
ERROR = 'error',
CONFIRM = 'confirm',
DARK = 'dark',
}

export interface ButtonProps {
Expand Down
Expand Up @@ -6,15 +6,29 @@ import {
EnvironmentLogsError,
Log,
} from 'qovery-typescript-axios'
import { MouseEvent, ReactNode, useEffect, useRef } from 'react'
import { MouseEvent, ReactNode, useEffect, useRef, useState } from 'react'
import { Link } from 'react-router-dom'
import { useParams } from 'react-router-dom'
import { IconEnum, RunningStatus } from '@qovery/shared/enums'
import { ApplicationEntity, EnvironmentEntity, LoadingStatus } from '@qovery/shared/interfaces'
import { APPLICATION_LOGS_URL, DEPLOYMENT_LOGS_URL } from '@qovery/shared/router'
import { ButtonIcon, ButtonIconStyle, ButtonSize, Icon, IconAwesomeEnum, StatusChip, Tooltip } from '@qovery/shared/ui'
import {
Button,
ButtonIcon,
ButtonIconStyle,
ButtonSize,
ButtonStyle,
Icon,
IconAwesomeEnum,
Menu,
MenuAlign,
MenuData,
StatusChip,
Tooltip,
} from '@qovery/shared/ui'
import { scrollParentToChild } from '@qovery/shared/utils'
import TabsLogs from './tabs-logs/tabs-logs'
import { UpdateTimeContext, defaultUpdateTimeContext } from './update-time-context/update-time-context'

export interface LayoutLogsDataProps {
loadingStatus: LoadingStatus
Expand Down Expand Up @@ -57,6 +71,8 @@ export function LayoutLogs(props: LayoutLogsProps) {

const refScrollSection = useRef<HTMLDivElement>(null)

const [updateTimeContextValue, setUpdateTimeContext] = useState(defaultUpdateTimeContext)

const { organizationId = '', projectId = '', environmentId = '', applicationId = '' } = useParams()

const forcedScroll = (down?: boolean) => {
Expand Down Expand Up @@ -90,6 +106,34 @@ export function LayoutLogs(props: LayoutLogsProps) {
if (row) scrollParentToChild(section, row, 100)
}

const menusTimeFormat: MenuData = [
{
title: 'Time format',
items: [
{
name: 'Local browser time',
contentLeft: (
<Icon
name={IconAwesomeEnum.CHECK}
className={`text-success-500 ${!updateTimeContextValue.utc ? 'opacity-100' : 'opacity-0'}`}
/>
),
onClick: () => setUpdateTimeContext({ utc: false }),
},
{
name: 'UTC',
contentLeft: (
<Icon
name={IconAwesomeEnum.CHECK}
className={`text-success-500 ${updateTimeContextValue.utc ? 'opacity-100' : 'opacity-0'}`}
/>
),
onClick: () => setUpdateTimeContext({ utc: true }),
},
],
},
]

return (
<div className="overflow-hidden flex relative h-[calc(100vh-4rem)]">
{withLogsNavigation && (
Expand Down Expand Up @@ -165,8 +209,22 @@ export function LayoutLogs(props: LayoutLogsProps) {
</p>
)}
<div className="flex">
<Menu
menus={menusTimeFormat}
arrowAlign={MenuAlign.END}
trigger={
<Button
className="mr-2"
size={ButtonSize.TINY}
style={ButtonStyle.DARK}
iconRight={IconAwesomeEnum.ANGLE_DOWN}
>
Time format
</Button>
}
/>
{setPauseLogs && (
<Tooltip side="top" content="Paused, show next logs" open={pauseLogs}>
<Tooltip side="top" content="Resume real-time logs" open={pauseLogs}>
<div>
<ButtonIcon
icon={!pauseLogs ? IconAwesomeEnum.PAUSE : IconAwesomeEnum.PLAY}
Expand Down Expand Up @@ -205,7 +263,14 @@ export function LayoutLogs(props: LayoutLogsProps) {
: ''
} ${withLogsNavigation ? 'mt-[76px]' : 'mt-[36px]'}`}
>
<div className="relative z-10">{children}</div>
<UpdateTimeContext.Provider
value={{
...updateTimeContextValue,
setUpdateTimeContext,
}}
>
<div className="relative z-10">{children}</div>
</UpdateTimeContext.Provider>
</div>
{tabInformation && <TabsLogs scrollToError={scrollToError} tabInformation={tabInformation} errors={errors} />}
</>
Expand Down
@@ -0,0 +1,51 @@
import { fireEvent, getByRole, render } from '@testing-library/react'
import { useContext } from 'react'
import { UpdateTimeContext } from './update-time-context'

const setUpdateTime = jest.fn()

function Content() {
const { utc, setUpdateTimeContext } = useContext(UpdateTimeContext)

return (
<div>
<button onClick={() => setUpdateTimeContext && setUpdateTimeContext({ utc: true })}>
Click {utc.toString()}
</button>
</div>
)
}

describe('UpdateTimeContext', () => {
it('should render successfully', () => {
const { baseElement } = render(
<UpdateTimeContext.Provider
value={{
...{ utc: false },
setUpdateTimeContext: setUpdateTime,
}}
>
<Content />
</UpdateTimeContext.Provider>
)
expect(baseElement).toBeTruthy()
})

it('should change context UTC boolean', async () => {
const { baseElement } = render(
<UpdateTimeContext.Provider
value={{
...{ utc: false },
setUpdateTimeContext: setUpdateTime,
}}
>
<Content />
</UpdateTimeContext.Provider>
)

const button = getByRole(baseElement, 'button')
fireEvent.click(button)

expect(baseElement.textContent).toBe('Click false')
})
})
@@ -0,0 +1,12 @@
import { createContext } from 'react'

interface UpdateTimeContextProps {
utc: boolean
setUpdateTimeContext?: (data: { utc: boolean }) => void
}

export const defaultUpdateTimeContext = {
utc: false,
}

export const UpdateTimeContext = createContext<UpdateTimeContextProps>(defaultUpdateTimeContext)
19 changes: 4 additions & 15 deletions libs/shared/ui/src/lib/components/modal/modal-root.spec.tsx
@@ -1,25 +1,14 @@
import {
fireEvent,
getByRole,
getByTestId,
queryByRole,
queryByTestId,
render,
screen,
waitFor,
} from '@testing-library/react'
import exp from 'constants'
import { useContext, useEffect } from 'react'
import { useEventSource } from 'react-use-websocket'
import ModalRoot, { ModalContext } from './modal-root'
import { fireEvent, getByRole, getByTestId, queryByTestId, render, waitFor } from '@testing-library/react'
import { useEffect } from 'react'
import ModalRoot from './modal-root'
import useModal from './use-modal/use-modal'

function Content(props: { shouldConfirm?: boolean }) {
const { openModal, enableAlertClickOutside } = useModal()

useEffect(() => {
enableAlertClickOutside(props.shouldConfirm || false)
}, [enableAlertClickOutside])
}, [enableAlertClickOutside, props.shouldConfirm])

return (
<div>
Expand Down
7 changes: 6 additions & 1 deletion libs/shared/ui/src/lib/styles/components/button.scss
Expand Up @@ -33,7 +33,12 @@
}

.btn--dark {
@apply bg-element-light-darker-100 text-text-100 hover:bg-element-light-darker-200;
@apply bg-element-light-darker-100 text-text-100 dark:text-text-300;

&.is-active,
&:hover {
@apply bg-element-light-darker-200 dark:bg-brand-500 dark:text-text-100;
}
}

.btn--tab {
Expand Down
5 changes: 3 additions & 2 deletions libs/shared/utils/src/lib/tools/date.tsx
Expand Up @@ -43,8 +43,9 @@ export function dateYearMonthDayHourMinuteSecond(date: Date, withTime = true) {
}

// 15 Sep, 10:23:20:20
export const dateFullFormat = (date: string) => {
return formatInTimeZone(new Date(date), 'dd MMM, HH:mm:ss:SS', 'Europe/Paris')
export const dateFullFormat = (date: string, timeZone?: string) => {
const localTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
return formatInTimeZone(new Date(date), 'dd MMM, HH:mm:ss:SS', timeZone ? timeZone : localTimeZone)
}

export const dateToFormat = (date: string, format: string) => {
Expand Down

0 comments on commit 0968851

Please sign in to comment.