Skip to content

Commit

Permalink
feat: better errors handler nouvelle initialisation de l'application #2
Browse files Browse the repository at this point in the history
  • Loading branch information
hrenaud committed Sep 6, 2024
1 parent 4f06661 commit 7facb42
Show file tree
Hide file tree
Showing 2 changed files with 216 additions and 152 deletions.
157 changes: 5 additions & 152 deletions src/renderer/MainWindow/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ConsoleApp } from '../components/console'
import { DarkModeSwitcher } from '../components/dark-mode-switcher'
import { Footer } from '../components/footer'
import { Header } from '../components/Header'
import { InitErrorAlerts } from '../components/initialization-error-alerts'
import { Input } from '../ui/input'
import { JsonPanMesure } from '../components/json-pan'
import { MySkeleton } from '../components/my-skeleton'
Expand Down Expand Up @@ -296,16 +297,6 @@ function TheApp() {
}
}

/**
* Handler to open URL of the official Node.js installer.
*/
const installNode = () => {
window.open(
`https://nodejs.org/en/download/prebuilt-installer`,
`_blank`
)
}

/**
* Handler to copy in clipboard the content of datasFromHost.
*/
Expand Down Expand Up @@ -597,148 +588,10 @@ function TheApp() {
<main className="flex h-screen flex-col justify-between gap-4 p-4">
<div className="flex flex-col items-center gap-4">
<Header />
{false && (
<div className="flex flex-col text-sm">
<div>appReady: {appReady ? 'true' : 'false'}</div>
<div>
isFirstStart: {isFirstStart ? 'true' : 'false'}
</div>
<div>
isNodeInstalled:{' '}
{isNodeInstalled ? 'true' : 'false'}
</div>
<div>
isLighthouseEcoindexPluginInstalled:{' '}
{isLighthouseEcoindexPluginInstalled
? 'true'
: 'false'}
</div>
<div>
isPuppeteerBrowserInstalled:{' '}
{isPuppeteerBrowserInstalled ? 'true' : 'false'}
</div>
<div>
isNodeVersionOK:{' '}
{isNodeVersionOK ? 'true' : 'false'}
</div>
<div>workDir: {workDir}</div>
<div>homeDir: {homeDir}</div>
<div>
PuppeteerBrowser: {puppeteerBrowserInstalled}
</div>
<div>
userCanWrite: {userCanWrite ? 'true' : 'false'}
</div>
</div>
)}
{!initializing && !appReady && isFirstStart && (
<AlertBox title={t('First launch')} variant="default">
<div className="flex items-center justify-between gap-4">
<span>
{t(
`It's the first time you are using the application, you must start the addons installation.`
)}
</span>
<Button
variant="default"
id="bt-install-node"
onClick={() => launchInitialization(true)}
>
{t('Install')}
</Button>
</div>
</AlertBox>
)}
{!initializing && !appReady && isNodeInstalled && (
<AlertBox title={t('Error on Node')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
'Node is not installed, install it (you must be admin of your computer)! After installation, restart application.'
)}
</span>
<Button
variant="destructive"
id="bt-install-node"
onClick={installNode}
>
{t('Install')}
</Button>
</div>
</AlertBox>
)}
{!initializing && !appReady && isNodeVersionOK && (
<AlertBox title={t('Error on Node Version')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
'Your Node installation is outdated, you must upgrade it to 20 or upper, upgrade it (you must be admin of your computer)! After upgrade, restart application.'
)}
</span>
<Button
variant="destructive"
onClick={installNode}
>
{t('Upgrade')}
</Button>
</div>
</AlertBox>
)}
{!initializing && !appReady && !userCanWrite && (
<AlertBox title={t('Permissions Error')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
`You must accept and enter your password, when prompted, in order to install the necessary elements.`
)}
</span>
<Button
variant="destructive"
onClick={forceRefresh}
>
{t('Retry')}
</Button>
</div>
</AlertBox>
)}
{!initializing &&
!appReady &&
!isFirstStart &&
(!isNodeInstalled || !isNodeVersionOK) && (
<AlertBox variant="bug" title={t('Report error')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
"You have an error but you think it's a bug. Report to the developper by clicking the button (datas are saved to your clipboard) and send theim by mail to "
)}
<a
href="mailto:[email protected]"
className="underline"
>
[email protected]
</a>{' '}
🙏
</span>
<SimpleTooltip
tooltipContent={
<p>
{t(
'Copy application informations to clipboard.'
)}
</p>
}
>
<Button
id="bt-report"
variant="default"
onClick={copyToClipBoard}
>
{t('Report')}
</Button>
</SimpleTooltip>
</div>
</AlertBox>
)}
<InitErrorAlerts
datasFromHost={datasFromHost}
launchInitialization={launchInitialization}
/>
{!appReady && <MySkeleton />}
{appReady && (
<>
Expand Down
211 changes: 211 additions & 0 deletions src/renderer/components/initialization-error-alerts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { useEffect, useState } from 'react'

import { AlertBox } from './Alert'
import { Button } from '../ui/button'
import { ConfigData } from '../../class/ConfigData'
import { SimpleTooltip } from './simple-tooltip'
import log from 'electron-log/renderer'
import { useTranslation } from 'react-i18next'

type ErrorAlert = {
launchInitialization: (force: boolean) => void
datasFromHost: object
}
const frontLog = log.scope(`front/initErrorAlert`)
export const InitErrorAlerts = ({
launchInitialization,
datasFromHost,
}: ErrorAlert) => {
const [isFirstStart, setIsFirstStart] = useState(false)
const [isNodeInError, setIsNodeInError] = useState(false)
const [isNodeVersionInError, setIsNodeVersionInError] = useState(false)
const [isWriteAccessInError, setIsWriteAccessInError] = useState(false)
const [isGenericInError, setIsGenericInError] = useState(false)
const [isWriteAccessCantFix, setIsWriteAccessCantFix] = useState(false)
const [isBrowserInError, setIsBrowserInError] = useState(false)
const [isNpmDirInError, setIsNpmDirInError] = useState(false)

const { t } = useTranslation()

/**
* Handler to open URL of the official Node.js installer.
*/
const installNode = () => {
window.open(
`https://nodejs.org/en/download/prebuilt-installer`,
`_blank`
)
}

/**
* Handlers, force window refresh
*/
const forceRefresh = () => {
// getMainWindow().webContents.reload()
window.location.reload()
}

/**
* Handler to copy in clipboard the content of datasFromHost.
*/
const copyToClipBoard = () => {
navigator.clipboard.writeText(JSON.stringify(datasFromHost, null, 2))
}

useEffect(() => {
/**
* Add "listeners" for initialisationAPI.sendConfigDatasToFront()
*/
window.initialisationAPI.sendConfigDatasToFront(
(configData: ConfigData) => {
frontLog.debug(`sendConfigDatasToFront`, configData)
if (configData.error) {
frontLog.error(configData)
window.alert(
`${configData.type} : ${configData.message ? configData.message : configData.error}`
)
}
if (configData.type !== ConfigData.APP_CAN_NOT_BE_LAUNCHED)
return
switch (configData.errorType) {
case ConfigData.ERROR_TYPE_FIRST_INSTALL:
setIsFirstStart(true)
break
case ConfigData.ERROR_TYPE_NO_NODE:
setIsNodeInError(true)
setIsGenericInError(true)
break
case ConfigData.ERROR_TYPE_NO_WRITE_ACCESS:
setIsWriteAccessInError(true)
setIsGenericInError(true)
break
case ConfigData.ERROR_TYPE_CANT_FIX_USER_RIGHTS:
setIsWriteAccessCantFix(true)
setIsGenericInError(true)
break
case ConfigData.ERROR_TYPE_BROWSER_NOT_INSTALLED:
setIsBrowserInError(true)
setIsGenericInError(true)
break
case ConfigData.ERROR_TYPE_NODE_VERSION_ERROR:
setIsNodeVersionInError(true)
setIsGenericInError(true)
break
case ConfigData.ERROR_TYPE_NO_NPM_DIR:
setIsNpmDirInError(true)
setIsGenericInError(true)
break

default:
alert(
`ConfigData.errorType=${configData.errorType} not handle in App.tsx`
)
}
}
)
}, [])

return (
<>
{isFirstStart && (
<AlertBox title={t('First launch')} variant="default">
<div className="flex items-center justify-between gap-4">
<span>
{t(
`It's the first time you are using the application, you must start the addons installation.`
)}
</span>
<Button
variant="default"
id="bt-install-node"
onClick={() => launchInitialization(true)}
>
{t('Install')}
</Button>
</div>
</AlertBox>
)}
{isNodeInError && (
<AlertBox title={t('Error on Node')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
'Node is not installed, install it (you must be admin of your computer)! After installation, restart application.'
)}
</span>
<Button
variant="destructive"
id="bt-install-node"
onClick={installNode}
>
{t('Install')}
</Button>
</div>
</AlertBox>
)}
{isNodeVersionInError && (
<AlertBox title={t('Error on Node Version')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
'Your Node installation is outdated, you must upgrade it to 20 or upper, upgrade it (you must be admin of your computer)! After upgrade, restart application.'
)}
</span>
<Button variant="destructive" onClick={installNode}>
{t('Upgrade')}
</Button>
</div>
</AlertBox>
)}
{isWriteAccessInError && (
<AlertBox title={t('Permissions Error')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
`You must accept and enter your password, when prompted, in order to install the necessary elements.`
)}
</span>
<Button variant="destructive" onClick={forceRefresh}>
{t('Retry')}
</Button>
</div>
</AlertBox>
)}
{isGenericInError && (
<AlertBox variant="bug" title={t('Report error')}>
<div className="flex items-center justify-between gap-4">
<span>
{t(
"You have an error but you think it's a bug. Report to the developper by clicking the button (datas are saved to your clipboard) and send theim by mail to "
)}
<a
href="mailto:[email protected]"
className="underline"
>
[email protected]
</a>{' '}
🙏
</span>
<SimpleTooltip
tooltipContent={
<p>
{t(
'Copy application informations to clipboard.'
)}
</p>
}
>
<Button
id="bt-report"
variant="default"
onClick={copyToClipBoard}
>
{t('Report')}
</Button>
</SimpleTooltip>
</div>
</AlertBox>
)}
</>
)
}

0 comments on commit 7facb42

Please sign in to comment.