Skip to content

Commit

Permalink
Fix SightSlider icons & some Drive fixes (#728)
Browse files Browse the repository at this point in the history
* Disable login and inspection creation in Drive app

* Added HinL task in create inspection in Drive App

* Fixed SightSlider status icons
  • Loading branch information
souyahia-monk authored Apr 30, 2024
1 parent a17012a commit 41177b9
Show file tree
Hide file tree
Showing 28 changed files with 291 additions and 429 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

.error-message {
Expand Down
1 change: 1 addition & 0 deletions apps/drive-app/.env-cmdrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"PORT": "17200",
"HTTPS": "true",
"ESLINT_NO_DEV_ERRORS": "true",
"REACT_APP_ALLOW_CREATE_INSPECTION": "true",
"REACT_APP_ENVIRONMENT": "local",
"REACT_APP_API_DOMAIN": "api.preview.monk.ai/v1",
"REACT_APP_AUTH_DOMAIN": "idp.preview.monk.ai",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

.error-message {
text-align: center;
padding-bottom: 20px;
}

.retry-btn-container {
padding-top: 20px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,35 @@ import { useTranslation } from 'react-i18next';
import { useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import { Button, Spinner } from '@monkvision/common-ui-web';
import { useMonkApi } from '@monkvision/network';
import { CreateInspectionOptions, useMonkApi } from '@monkvision/network';
import { getEnvOrThrow, useLoadingState, useMonkAppParams } from '@monkvision/common';
import { useMonitoring } from '@monkvision/monitoring';
import { TaskName } from '@monkvision/types';
import { Page } from '../pages';
import styles from './CreateInspectionPage.module.css';

const options: CreateInspectionOptions = {
tasks: [
TaskName.DAMAGE_DETECTION,
TaskName.WHEEL_ANALYSIS,
{
name: TaskName.HUMAN_IN_THE_LOOP,
callbacks: [
{
url: 'https://webhook.site/15f8682f-91a8-4df0-8e73-74adc6c74ca4',
headers: {},
params: {},
},
],
},
],
};

enum CreateInspectionPageError {
CREATE_INSPECTION = 'create-inspection.errors.create-inspection',
MISSING_INSPECTION_ID = 'create-inspection.errors.missing-inspection-id',
}

export function CreateInspectionPage() {
const loading = useLoadingState();
const { t } = useTranslation();
Expand All @@ -21,21 +43,26 @@ export function CreateInspectionPage() {

const handleCreateInspection = () => {
loading.start();
createInspection({ tasks: [TaskName.DAMAGE_DETECTION, TaskName.WHEEL_ANALYSIS] })
createInspection(options)
.then((res) => {
loading.onSuccess();
setInspectionId(res.id);
})
.catch((err) => {
loading.onError(err);
loading.onError(CreateInspectionPageError.CREATE_INSPECTION);
handleError(err);
});
};

useEffect(() => {
if (!inspectionId) {
loading.start();
handleCreateInspection();
if (process.env['REACT_APP_ALLOW_CREATE_INSPECTION'] === 'true') {
// On local environment, we allow creating the inspection if the ID is not provided.
loading.start();
handleCreateInspection();
} else {
loading.onError(CreateInspectionPageError.MISSING_INSPECTION_ID);
}
}
}, [inspectionId]);

Expand All @@ -48,12 +75,14 @@ export function CreateInspectionPage() {
{loading.isLoading && <Spinner size={80} />}
{!loading.isLoading && loading.error && (
<>
<div className={styles['error-message']}>
{t('create-inspection.errors.create-inspection')}
</div>
<Button variant='outline' icon='refresh' onClick={handleCreateInspection}>
{t('create-inspection.errors.retry')}
</Button>
<div className={styles['error-message']}>{t(loading.error)}</div>
{loading.error === CreateInspectionPageError.CREATE_INSPECTION && (
<div className={styles['retry-btn-container']}>
<Button variant='outline' icon='refresh' onClick={handleCreateInspection}>
{t('create-inspection.errors.retry')}
</Button>
</div>
)}
</>
)}
</div>
Expand Down
12 changes: 10 additions & 2 deletions apps/drive-app/src/pages/LogInPage/LogInPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ function getLoginErrorMessage(err: unknown): string {
return 'login.errors.unknown';
}

const allowCreateInspection = process.env['REACT_APP_ALLOW_CREATE_INSPECTION'] === 'true';

export function LogInPage() {
const [isExpired, setIsExpired] = useState(false);
const loading = useLoadingState();
Expand All @@ -28,6 +30,11 @@ export function LogInPage() {
const navigate = useNavigate();

useEffect(() => {
if (!authToken && !allowCreateInspection) {
setAuthToken(null);
setIsExpired(false);
loading.onError('login.errors.missing-token');
}
if (authToken && !isUserAuthorized(authToken, REQUIRED_AUTHORIZATIONS)) {
loading.onError('login.errors.insufficient-authorization');
}
Expand Down Expand Up @@ -62,11 +69,12 @@ export function LogInPage() {
<div className={styles['error-message']}>{t('login.errors.token-expired')}</div>
)}
{loading.error && <div className={styles['error-message']}>{t(loading.error)}</div>}
{authToken ? (
{authToken && allowCreateInspection && (
<Button primaryColor='alert' loading={loading} onClick={logout}>
{t('login.actions.log-out')}
</Button>
) : (
)}
{!authToken && allowCreateInspection && (
<Button loading={loading} onClick={handleLogin}>
{t('login.actions.log-in')}
</Button>
Expand Down
6 changes: 4 additions & 2 deletions apps/drive-app/src/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
"popup-closed": "Huch! Wir konnten Sie nicht anmelden, weil das Popup geschlossen wurde. Versuchen wir es noch einmal!",
"token-expired": "Ihr Authentifizierungstoken ist abgelaufen. Bitte melden Sie sich erneut an.",
"insufficient-authorization": "Sie haben nicht die erforderlichen Berechtigungen, um diese Anwendung zu nutzen. Bitte melden Sie sich ab und verwenden Sie ein anderes Konto.",
"unknown": "Huch! Beim Einloggen ist ein unerwarteter Fehler aufgetreten. Versuchen wir es noch einmal!"
"unknown": "Huch! Beim Einloggen ist ein unerwarteter Fehler aufgetreten. Versuchen wir es noch einmal!",
"missing-token": "Die URL, auf die Sie zuzugreifen versuchen, ist ungültig."
}
},
"create-inspection": {
"errors": {
"retry": "Wiederholung",
"create-inspection": "Bei der Erstellung der Inspektion ist ein unerwarteter Fehler aufgetreten."
"create-inspection": "Bei der Erstellung der Inspektion ist ein unerwarteter Fehler aufgetreten.",
"missing-inspection-id": "Die URL, auf die Sie zuzugreifen versuchen, ist ungültig."
}
},
"inspection-complete": {
Expand Down
6 changes: 4 additions & 2 deletions apps/drive-app/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
"popup-closed": "Oops! We couldn't log you in because the popup was closed. Let's try again!",
"token-expired": "Your authentication token is expired. Please log-in again.",
"insufficient-authorization": "You do not have the required authorizations to use this application. Please log out and use a different account.",
"unknown": "Oops! An unexpected error occurred during the log in. Let's try again!"
"unknown": "Oops! An unexpected error occurred during the log in. Let's try again!",
"missing-token": "The URL you are trying to access is invalid."
}
},
"create-inspection": {
"errors": {
"retry": "Retry",
"create-inspection": "An unexpected error occurred while creating the inspection."
"create-inspection": "An unexpected error occurred while creating the inspection.",
"missing-inspection-id": "The URL you are trying to access is invalid."
}
},
"inspection-complete": {
Expand Down
6 changes: 4 additions & 2 deletions apps/drive-app/src/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
"popup-closed": "Oups ! Nous n'avons pas pu vous connecter car la pop-up s'est fermée. Essayons à nouveau !",
"token-expired": "Votre token d'authentification est expiré. Veuillez vous reconnecter.",
"insufficient-authorization": "Vous n'avez pas les autorisations nécessaires pour utiliser cette application. Veuillez vous déconnecter et utiliser un autre compte.",
"unknown": "Oups ! Une erreur inattendue est survenue lors de la connection. Essayons à nouveau !"
"unknown": "Oups ! Une erreur inattendue est survenue lors de la connection. Essayons à nouveau !",
"missing-token": "L'URL à laquelle vous essayez d'accéder est invalide."
}
},
"create-inspection": {
"errors": {
"retry": "Réessayer",
"create-inspection": "Une erreur inattendue est survenue lors de la création de l'inspection."
"create-inspection": "Une erreur inattendue est survenue lors de la création de l'inspection.",
"missing-inspection-id": "L'URL à laquelle vous essayez d'accéder est invalide."
}
},
"inspection-complete": {
Expand Down
57 changes: 4 additions & 53 deletions apps/drive-app/test/pages/CreateInspectionPage.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { render, screen, waitFor } from '@testing-library/react';
import { Navigate } from 'react-router-dom';
import { act } from 'react-dom/test-utils';
import { useLoadingState, useMonkAppParams } from '@monkvision/common';
import { expectPropsOnChildMock } from '@monkvision/test-utils';
import { useMonkApi } from '@monkvision/network';
import { TaskName } from '@monkvision/types';
import { Button } from '@monkvision/common-ui-web';
import { CreateInspectionPage, Page } from '../../src/pages';

const appParams = {
Expand All @@ -31,63 +27,18 @@ describe('CreateInspection page', () => {
unmount();
});

it('should create the inspection and then redirect to the PhotoCapture page if the inspectionId is not defined', async () => {
const id = 'test-id-test';
const createInspection = jest.fn(() => Promise.resolve({ id }));
(useMonkApi as jest.Mock).mockImplementation(() => ({ createInspection }));
(useMonkAppParams as jest.Mock).mockImplementation(() => appParams);
const { unmount } = render(<CreateInspectionPage />);

expect(createInspection).toHaveBeenCalledWith({
tasks: [TaskName.DAMAGE_DETECTION, TaskName.WHEEL_ANALYSIS],
});
await waitFor(() => {
expect(appParams.setInspectionId).toHaveBeenCalledWith(id);
});

unmount();
});

it('should display an error message if the API call fails', async () => {
const createInspection = jest.fn(() => Promise.reject());
(useMonkApi as jest.Mock).mockImplementation(() => ({ createInspection }));
(useMonkAppParams as jest.Mock).mockImplementation(() => appParams);
it('should display an error message if the inspection ID is not defined', async () => {
(useMonkAppParams as jest.Mock).mockImplementation(() => ({ inspectionId: null }));
const onError = jest.fn();
const error = 'test-error';
(useLoadingState as jest.Mock).mockImplementation(() => ({ onError, error, start: jest.fn() }));
const { unmount } = render(<CreateInspectionPage />);

await waitFor(() => {
expect(appParams.setInspectionId).not.toHaveBeenCalled();
expect(onError).toHaveBeenCalled();
expect(screen.queryByText('create-inspection.errors.create-inspection')).not.toBeNull();
expect(onError).toHaveBeenCalledWith('create-inspection.errors.missing-inspection-id');
expect(screen.getByText(error)).not.toBeNull();
});

unmount();
});

it('should display a retry button if the API call fails', async () => {
const createInspection = jest.fn(() => Promise.reject());
(useMonkApi as jest.Mock).mockImplementation(() => ({ createInspection }));
(useMonkAppParams as jest.Mock).mockImplementation(() => appParams);
(useLoadingState as jest.Mock).mockImplementation(() => ({
onError: jest.fn(),
error: 'test-error',
start: jest.fn(),
}));
const { unmount } = render(<CreateInspectionPage />);

expectPropsOnChildMock(Button, {
variant: 'outline',
icon: 'refresh',
onClick: expect.any(Function),
});
const { onClick } = (Button as unknown as jest.Mock).mock.calls[0][0];

createInspection.mockClear();
act(() => onClick());
expect(createInspection).toHaveBeenCalled();

unmount();
});
});
Loading

0 comments on commit 41177b9

Please sign in to comment.