diff --git a/jupyter_drives/manager.py b/jupyter_drives/manager.py index 5af78db..705eba4 100644 --- a/jupyter_drives/manager.py +++ b/jupyter_drives/manager.py @@ -319,7 +319,7 @@ async def mount_drive(self, drive_name, provider): except Exception as e: raise tornado.web.HTTPError( status_code= httpx.codes.BAD_REQUEST, - reason= f"The following error occured when mouting the drive: {e}" + reason= f"{e}" ) return @@ -771,7 +771,7 @@ async def _get_drive_location(self, drive_name): except Exception as e: raise tornado.web.HTTPError( status_code= httpx.codes.BAD_REQUEST, - reason=f"The following error occured when retriving the drive location: {e}", + reason=f"{e}", ) return location diff --git a/src/plugins/drivelistmanager.tsx b/src/plugins/drivelistmanager.tsx index fc47290..5cc718a 100644 --- a/src/plugins/drivelistmanager.tsx +++ b/src/plugins/drivelistmanager.tsx @@ -9,7 +9,8 @@ import { excludeDrive, getDrivesList, getExcludedDrives, - includeDrive + includeDrive, + mountDrive } from '../requests'; import { ISignal, Signal } from '@lumino/signaling'; import { driveBrowserIcon, addIcon, removeIcon } from '../icons'; @@ -27,6 +28,8 @@ export interface IDriveInputProps { onSubmit: () => void; isPublic: boolean; setIsPublic: (value: boolean) => void; + mountError: string; + resetMountError: () => void; } export function DriveInputComponent({ @@ -36,7 +39,9 @@ export function DriveInputComponent({ setRegion, onSubmit, isPublic, - setIsPublic + setIsPublic, + mountError, + resetMountError }: IDriveInputProps) { return (
@@ -45,6 +50,7 @@ export function DriveInputComponent({ className="drive-search-input" onInput={(event: any) => { setPublicDrive(event.target.value); + resetMountError(); }} placeholder="Enter drive name" value={driveValue} @@ -69,12 +75,18 @@ export function DriveInputComponent({ className="drive-region-input" onInput={(event: any) => { setRegion(event.target.value); + resetMountError(); }} placeholder="Region (e.g.: us-east-1)" value={regionValue} /> )}
+ {mountError && ( +
+

{mountError}

+
+ )} ); } @@ -183,6 +195,7 @@ export function DriveListManagerComponent({ model }: IProps) { ); const [isPublic, setIsPublic] = useState(false); const [driveRegion, setDriveRegion] = useState(''); + const [mountError, setMountError] = useState(''); // Called after mounting. React.useEffect(() => { @@ -197,14 +210,24 @@ export function DriveListManagerComponent({ model }: IProps) { }, [model]); const onAddedPublicDrive = async () => { - if (isPublic) { - await addPublicDrive(publicDrive); + // Check if user has access to drive. + const result = await mountDrive(publicDrive, { + provider: 's3' + }); + if (result && result.error) { + // Show error in case of failure. + setMountError(result.error.message); } else { - await addExternalDrive(publicDrive, driveRegion); + // Proceed with adding the drive otherwise. + if (isPublic) { + await addPublicDrive(publicDrive); + } else { + await addExternalDrive(publicDrive, driveRegion); + setDriveRegion(''); + } setDriveRegion(''); + await model.refresh(); } - setPublicDrive(''); - await model.refresh(); }; return ( @@ -239,6 +262,8 @@ export function DriveListManagerComponent({ model }: IProps) { isPublic={isPublic} setIsPublic={setIsPublic} onSubmit={onAddedPublicDrive} + mountError={mountError} + resetMountError={() => setMountError('')} /> diff --git a/src/requests.ts b/src/requests.ts index 1ed57d7..8891eb5 100644 --- a/src/requests.ts +++ b/src/requests.ts @@ -73,7 +73,15 @@ export async function mountDrive( drive_name: driveName, provider: options.provider }; - return await requestAPI('drives', 'POST', body); + try { + await requestAPI('drives', 'POST', body); + } catch (error: any) { + return { + error: error + }; + } + + return; } /** diff --git a/style/base.css b/style/base.css index da490ae..204e0f5 100644 --- a/style/base.css +++ b/style/base.css @@ -157,3 +157,8 @@ li { fill: var(--jp-ui-inverse-font-color0) !important; color: var(--jp-ui-inverse-font-color0) !important; } + +.error { + color: var(--md-red-600); + font-size: 0.7rem; +}