From 56b73acd04c3bcc470acf9d6428f8113f8e4c563 Mon Sep 17 00:00:00 2001 From: Tobias Messner Date: Fri, 16 Aug 2024 12:28:02 +0200 Subject: [PATCH] feat: Add icons to session indicator for a11y Using color for the session indicator makes it more difficult to read for colorblind people. This PR adds icons which help with quickly identifying the session state. Corresponding stories are also added to showcase the new icons. Closes #1709 --- .../app/sessions/service/session.service.ts | 25 ++++ .../active-sessions.component.html | 5 +- .../active-sessions.stories.ts | 136 ++++++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/sessions/service/session.service.ts b/frontend/src/app/sessions/service/session.service.ts index 715b4f05e7..d4e90b6af5 100644 --- a/frontend/src/app/sessions/service/session.service.ts +++ b/frontend/src/app/sessions/service/session.service.ts @@ -106,6 +106,7 @@ export class SessionService { let text = state; let css = 'warning'; + let icon = 'pending'; let success = false; switch (state) { case 'Created': @@ -116,54 +117,66 @@ export class SessionService { text = 'Session started'; css = 'success'; success = true; + icon = 'check'; break; case 'Failed': case 'FailedCreatePodContainer': text = 'Failed to create session'; css = 'error'; + icon = 'error'; break; case 'Killing': text = 'Stopping session'; css = 'error'; + icon = 'close'; break; case 'Preempting': text = 'Session is waiting in the queue'; css = 'error'; + icon = 'timer_pause'; break; case 'BackOff': text = 'Session crashed unexpectedly'; css = 'error'; + icon = 'error'; break; case 'ExceededGracePeriod': text = 'The session stopped.'; css = 'error'; + icon = 'cancel'; break; case 'FailedKillPod': text = 'Failed to stop session'; css = 'error'; + icon = 'error'; break; case 'NetworkNotReady': text = 'Backend network issues'; css = 'error'; + icon = 'cloud_off'; break; case 'Pulling': text = 'Preparation of the session'; css = 'warning'; + icon = 'downloading'; break; case 'Pulled': text = 'Preparation finished'; css = 'warning'; + icon = 'download_done'; break; // Some additional reasons that came up case 'Scheduled': text = 'Your session is scheduled'; css = 'warning'; + icon = 'schedule'; break; case 'FailedScheduling': text = 'High demand. Please wait a moment.'; css = 'warning'; + icon = 'timer_pause'; break; // OpenShift specific @@ -176,53 +189,64 @@ export class SessionService { case 'Pending': text = 'Your session is scheduled'; css = 'warning'; + icon = 'schedule'; break; case 'Running': text = 'Session is running'; css = 'success'; success = true; + icon = 'check'; break; // Cases for starting containers case 'START_LOAD_MODEL': text = 'Modelloading started'; css = 'warning'; + icon = 'downloading'; break; case 'FINISH_LOAD_MODEL': text = 'Modelloading finished'; css = 'warning'; + icon = 'download_done'; break; case 'FAILURE_LOAD_MODEL': text = 'Error during loading of the model'; css = 'error'; + icon = 'error'; break; case 'START_PREPARE_WORKSPACE': text = 'Started workspace preparation'; css = 'warning'; + icon = 'downloading'; break; case 'FINISH_PREPARE_WORKSPACE': text = 'Workspace preparation finished'; css = 'warning'; + icon = 'download_done'; break; case 'FAILURE_PREPARE_WORKSPACE': text = 'Error during workspace preparation'; css = 'error'; + icon = 'error'; break; case 'START_SESSION': text = 'Session started'; css = 'success'; success = true; + icon = 'check'; break; case 'unknown': case 'Unknown': text = 'Unknown State'; css = 'primary'; + icon = 'help'; break; } return { text: text || '', css: css, + icon: icon, success: success, }; } @@ -231,5 +255,6 @@ export class SessionService { export interface SessionState { text: string; css: string; + icon: string; success: boolean; } diff --git a/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.component.html b/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.component.html index d5ce376fa4..f1fce5cded 100644 --- a/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.component.html +++ b/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.component.html @@ -47,9 +47,12 @@

Read-only session

+ {{ + sessionService.beautifyState(session.state).icon + }} {{ sessionService.beautifyState(session.state).text }}

diff --git a/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.stories.ts b/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.stories.ts index ad4861bff2..da700e807a 100644 --- a/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.stories.ts +++ b/frontend/src/app/sessions/user-sessions-wrapper/active-sessions/active-sessions.stories.ts @@ -134,6 +134,142 @@ export const SessionErrorStateStory: Story = { ], }; +export const SessionKillingStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('Killing'), + ), + }, + ], + }), + ], +}; + +export const SessionStoppedStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('ExceededGracePeriod'), + ), + }, + ], + }), + ], +}; + +export const SessionQueuedStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('Preempting'), + ), + }, + ], + }), + ], +}; + +export const SessionNetworkIssuesStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('NetworkNotReady'), + ), + }, + ], + }), + ], +}; + +export const SessionPullingStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('Pulling'), + ), + }, + ], + }), + ], +}; + +export const SessionPulledStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('Pulled'), + ), + }, + ], + }), + ], +}; + +export const SessionScheduledStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('Scheduled'), + ), + }, + ], + }), + ], +}; + +export const SessionFailedSchedulingStateStory: Story = { + args: {}, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: UserSessionService, + useFactory: () => + new MockUserSessionService( + createPersistentSessionWithState('FailedScheduling'), + ), + }, + ], + }), + ], +}; + export const SessionUnknownStateStory: Story = { args: {}, decorators: [