Skip to content

Commit

Permalink
Merge branch 'develop' into reduce-any
Browse files Browse the repository at this point in the history
  • Loading branch information
jamil314 authored Dec 11, 2024
2 parents 2ae2693 + 1efd261 commit f9182be
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 330 deletions.
261 changes: 111 additions & 150 deletions packages/client/src/components/form/FetchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
*
* Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS.
*/
import * as React from 'react'
import React, { useState } from 'react'
import styled from 'styled-components'
import { ApolloError, ApolloQueryResult, ApolloConsumer } from '@apollo/client'
import { ApolloError, ApolloConsumer, ApolloClient } from '@apollo/client'
// eslint-disable-next-line no-restricted-imports
import * as Sentry from '@sentry/react'
import type { GQLQuery } from '@client/utils/gateway-deprecated-do-not-use'
import {
WrappedComponentProps as IntlShapeProps,
injectIntl,
Expand All @@ -24,7 +23,7 @@ import { Spinner } from '@opencrvs/components/lib/Spinner'
import { PrimaryButton } from '@opencrvs/components/lib/buttons'
import { Success, Error } from '@opencrvs/components/lib/icons'
import { IQuery } from '@opencrvs/client/src/forms'
import { isNavigatorOnline } from '@client/utils'
import { useOnlineStatus } from '@client/utils'

interface IFetchButtonProps {
id: string
Expand All @@ -38,16 +37,6 @@ interface IFetchButtonProps {
isDisabled?: boolean
}

interface IFetchButtonState {
response?: ApolloQueryResult<GQLQuery>
error?: boolean
success?: boolean
loading?: boolean
show?: boolean
isDisconnected: boolean
networkError?: boolean
}

type IFullProps = IFetchButtonProps & IntlShapeProps

const Container = styled.div`
Expand Down Expand Up @@ -114,75 +103,63 @@ const StyledPrimaryButton = styled(PrimaryButton)`
}`
}}
`
class FetchButton extends React.Component<IFullProps, IFetchButtonState> {
constructor(props: IFullProps) {
super(props)
this.state = {
loading: false,
error: false,
isDisconnected: false
}
}

componentDidMount() {
this.handleConnectionChange()
window.addEventListener('online', this.handleConnectionChange)
window.addEventListener('offline', this.handleConnectionChange)
}

componentWillUnmount() {
window.removeEventListener('online', this.handleConnectionChange)
window.removeEventListener('offline', this.handleConnectionChange)
}

handleConnectionChange = () => {
const condition = isNavigatorOnline() ? 'online' : 'offline'
if (condition === 'online') {
return this.setState({ isDisconnected: false })
}

return this.setState({ isDisconnected: true })
const FetchButton = (props: IFullProps) => {
const {
intl,
label,
modalTitle,
successTitle,
errorTitle,
queryData,
isDisabled,
onFetch
} = props
const [loading, setLoading] = useState(false)
const [error, setError] = useState(false)
const [success, setSuccess] = useState(false)
const [show, setShow] = useState(false)
const [networkError, setNetworkError] = useState(false)
const isOnline = useOnlineStatus()

const hideModal = () => {
setShow(false)
setLoading(false)
setError(false)
setNetworkError(false)
}

hideModal = () => {
this.setState({
show: false,
loading: false,
error: false,
networkError: false,
response: undefined
})
}
performQuery = async (client: any) => {
const { query, variables, responseTransformer } = this.props
.queryData as IQuery
const performQuery = async (client: ApolloClient<any>) => {

Check warning on line 132 in packages/client/src/components/form/FetchButton.tsx

View workflow job for this annotation

GitHub Actions / test (packages/client)

Unexpected any. Specify a different type
const { query, variables, responseTransformer } = queryData as IQuery
try {
this.setState({ show: true, loading: true, success: false, error: false })
setShow(true)
setLoading(true)
setSuccess(false)
setError(false)
const response = await client.query({
query,
variables
})
this.setState({ success: true, loading: false, error: false })
if (responseTransformer && this.props.onFetch) {
setSuccess(true)
setLoading(false)
setError(false)
if (responseTransformer && onFetch) {
const transformedResponse = responseTransformer(response)
this.props.onFetch(transformedResponse)
onFetch(transformedResponse)
}
} catch (error) {
Sentry.captureException(error)
this.setState({
error: true,
loading: false,
success: false,
networkError:
error instanceof ApolloError && Boolean(error.networkError)
? true
: false
})
setError(true)
setLoading(false)
setSuccess(false)
setNetworkError(
error instanceof ApolloError && Boolean(error.networkError)
)
}
}

getModalInfo = (intl: IntlShape) => {
const { variables, modalInfoText } = this.props.queryData as IQuery
const getModalInfo = (intl: IntlShape) => {
const { variables, modalInfoText } = queryData as IQuery
return (
<>
{modalInfoText && <Info>{intl.formatMessage(modalInfoText)}</Info>}
Expand All @@ -191,89 +168,73 @@ class FetchButton extends React.Component<IFullProps, IFetchButtonState> {
)
}

render() {
const {
intl,
label,
modalTitle,
successTitle,
errorTitle,
queryData,
isDisabled
} = this.props
const { loading, error, success, show, isDisconnected, networkError } =
this.state

return (
<Container {...this.props}>
<ApolloConsumer>
{(client) => {
return (
<div>
<StyledPrimaryButton
type={'button'}
disabled={isDisabled || isDisconnected}
onClick={async (event: React.MouseEvent<HTMLElement>) => {
this.performQuery(client)
event.preventDefault()
}}
>
{label}
</StyledPrimaryButton>
{show && (
<Backdrop>
<ModalContent>
{success && (
<>
<Heading>{successTitle}</Heading>
{this.getModalInfo(intl)}
<StyledSuccess id="loader-button-success" />
</>
)}

{error && (
<>
<Heading>{errorTitle}</Heading>
{this.getModalInfo(intl)}
<StyledError id="loader-button-error" />
{queryData && (
<Info>
{!networkError
? intl.formatMessage(queryData.errorText)
: intl.formatMessage(
queryData.networkErrorText
)}
</Info>
)}
</>
)}

{loading && (
<>
<Heading>{modalTitle}</Heading>
{this.getModalInfo(intl)}
<StyledSpinner id="loader-button-spinner" />
<ConfirmButton onClick={this.hideModal}>
{intl.formatMessage(buttonMessages.cancel)}
</ConfirmButton>
</>
)}

{!loading && (
<ConfirmButton onClick={this.hideModal}>
{intl.formatMessage(buttonMessages.back)}
return (
<Container {...props}>
<ApolloConsumer>
{(client: ApolloClient<any>) => {

Check warning on line 174 in packages/client/src/components/form/FetchButton.tsx

View workflow job for this annotation

GitHub Actions / test (packages/client)

Unexpected any. Specify a different type
return (
<div>
<StyledPrimaryButton
type={'button'}
disabled={isDisabled || !isOnline}
onClick={async (event: React.MouseEvent<HTMLElement>) => {
performQuery(client)
event.preventDefault()
}}
>
{label}
</StyledPrimaryButton>
{show && (
<Backdrop>
<ModalContent>
{success && (
<>
<Heading>{successTitle}</Heading>
{getModalInfo(intl)}
<StyledSuccess id="loader-button-success" />
</>
)}

{error && (
<>
<Heading>{errorTitle}</Heading>
{getModalInfo(intl)}
<StyledError id="loader-button-error" />
{queryData && (
<Info>
{!networkError
? intl.formatMessage(queryData.errorText)
: intl.formatMessage(queryData.networkErrorText)}
</Info>
)}
</>
)}

{loading && (
<>
<Heading>{modalTitle}</Heading>
{getModalInfo(intl)}
<StyledSpinner id="loader-button-spinner" />
<ConfirmButton onClick={hideModal}>
{intl.formatMessage(buttonMessages.cancel)}
</ConfirmButton>
)}
</ModalContent>
</Backdrop>
)}
</div>
)
}}
</ApolloConsumer>
</Container>
)
}
</>
)}

{!loading && (
<ConfirmButton onClick={hideModal}>
{intl.formatMessage(buttonMessages.back)}
</ConfirmButton>
)}
</ModalContent>
</Backdrop>
)}
</div>
)
}}
</ApolloConsumer>
</Container>
)
}

export const FetchButtonField = injectIntl<'intl', IFullProps>(FetchButton)
29 changes: 19 additions & 10 deletions packages/client/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import { storage } from '@client/storage'
import { APPLICATION_VERSION, LANG_EN } from '@client/utils/constants'
import { IUserData } from '@client/declarations'
import React from 'react'
import React, { useEffect, useState } from 'react'
import { GetSystemRolesQuery, Role } from '@client/utils/gateway'

export async function validateApplicationVersion() {
Expand All @@ -35,17 +35,26 @@ export function isNavigatorOnline() {
return navigator.onLine
}

const ONLINE = 'online'
const OFFLINE = 'offline'

export function useOnlineStatus() {
const [isOnline, setOnline] = React.useState(isNavigatorOnline())
const ONLINE_CHECK_INTERVAL = 500
React.useEffect(() => {
const intervalID = setInterval(
() => setOnline(isNavigatorOnline()),
ONLINE_CHECK_INTERVAL
)

return () => clearInterval(intervalID)
const [isOnline, setOnline] = useState(isNavigatorOnline())

useEffect(() => {
const handleConnectionChange = () => {
setOnline(isNavigatorOnline())
}

window.addEventListener(ONLINE, handleConnectionChange)
window.addEventListener(OFFLINE, handleConnectionChange)

return () => {
window.removeEventListener(ONLINE, handleConnectionChange)
window.removeEventListener(OFFLINE, handleConnectionChange)
}
}, [])

return isOnline
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function BookmarkAdvancedSearchModal({
const isOnline = useOnlineStatus()
const dispatch = useDispatch()
const userDetails = useSelector(getUserDetails)
const { searchId, ...advancedSearchParams } = useSelector(
const { searchId, bookmarkName, ...advancedSearchParams } = useSelector(
getAdvancedSearchParamsState
)
//remove null and empty properties
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/views/UserAudit/UserAuditHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ function UserAuditHistoryComponent(props: Props) {
<Pagination
currentPage={state.currentPageNumber}
totalPages={Math.ceil(totalItems / DEFAULT_LIST_SIZE)}
onPageChange={(page: any) =>
onPageChange={(page: number) =>
setState((prevState) => ({
...prevState,
currentPageNumber: page
Expand Down
Loading

0 comments on commit f9182be

Please sign in to comment.