From 39eafa214037a65ae005fc52d376cc4f4c60208e 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 563afa58c..95a9ab4f3 100644 --- a/frontend/src/app/sessions/service/session.service.ts +++ b/frontend/src/app/sessions/service/session.service.ts @@ -101,6 +101,7 @@ export class SessionService { let text = state; let css = 'warning'; + let icon = 'pending'; let success = false; switch (state) { case 'Created': @@ -111,54 +112,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 @@ -171,53 +184,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, }; } @@ -226,5 +250,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 d5ce376fa..f1fce5cde 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 25c6e4a41..304c2d2bb 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 @@ -132,6 +132,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: [