Skip to content

Commit 5dbb05d

Browse files
committed
PM-2136 - AI workflows sidebar - mobile view
1 parent 6abe321 commit 5dbb05d

File tree

6 files changed

+166
-37
lines changed

6 files changed

+166
-37
lines changed

src/apps/review/src/lib/components/AiReviewsTable/StatusLabel.module.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
.score {
3535
font-size: 14px;
36-
.failed-score {
36+
&.failed-score {
3737
color: #C1294F;
3838
}
3939
}

src/apps/review/src/lib/models/AiScorecardContext.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface AiScorecardContextModel extends ChallengeDetailContextModel {
88
submissionId: string
99
workflowId: string
1010
workflow?: AiWorkflow
11+
workflowRun?: AiWorkflowRun
1112
scorecard?: Scorecard
1213
workflowRuns: AiWorkflowRun[]
1314
}

src/apps/review/src/pages/ai-scorecards/AiScorecardContext/AiScorecardContextProvider.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,8 @@ export const AiScorecardContextProvider: FC<PropsWithChildren> = props => {
3434
challengeDetailsCtx.isLoadingChallengeSubmissions &&
3535
aiWorkflowRunsLoading
3636

37-
const workflow = useMemo(() => (
38-
workflowRuns.map(r => r.workflow).find(w => w.id === workflowId)
39-
), [workflowRuns, workflowId])
40-
37+
const workflowRun = useMemo(() => workflowRuns.find(w => w.workflow.id === workflowId), [workflowRuns, workflowId])
38+
const workflow = useMemo(() => workflowRun?.workflow, [workflowRuns, workflowId])
4139
const scorecard = useMemo(() => workflow?.scorecard, [workflow])
4240

4341
const value = useMemo<AiScorecardContextModel>(
@@ -46,6 +44,7 @@ export const AiScorecardContextProvider: FC<PropsWithChildren> = props => {
4644
submissionId,
4745
workflowId,
4846
workflowRuns,
47+
workflowRun,
4948
workflow,
5049
scorecard,
5150
isLoading: isLoadingCtxData,
@@ -55,6 +54,7 @@ export const AiScorecardContextProvider: FC<PropsWithChildren> = props => {
5554
submissionId,
5655
workflowId,
5756
workflowRuns,
57+
workflowRun,
5858
isLoadingCtxData,
5959
workflow,
6060
scorecard,

src/apps/review/src/pages/ai-scorecards/AiScorecardViewer/AiScorecardViewer.module.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,14 @@
1515
flex-shrink: 0;
1616
flex-basis: 256px;
1717
}
18+
19+
@include ltelg {
20+
flex-direction: column;
21+
gap: $sp-6;
22+
23+
> .sidebar {
24+
flex-basis: auto;
25+
width: 100%;
26+
}
27+
}
1828
}

src/apps/review/src/pages/ai-scorecards/components/AiWorkflowsSidebar/AiWorkflowsSidebar.module.scss

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,16 @@
3030
}
3131
}
3232

33+
3334
.runEntry {
3435
display: flex;
3536
flex-direction: row;
3637
align-items: center;
37-
justify-content: space-between;
38+
gap: $sp-4;
3839
padding: $sp-4;
3940
background-color: #f9fafa;
4041
cursor: pointer;
42+
position: relative;
4143

4244
font-family: "Nunito Sans", sans-serif;
4345
font-size: 16px;
@@ -80,6 +82,13 @@
8082
overflow: hidden;
8183
text-overflow: ellipsis;
8284
white-space: nowrap;
85+
86+
&Wrap {
87+
flex: 1 1 auto;
88+
}
89+
@include ltelg {
90+
max-width: calc(90vw - 140px);
91+
}
8392
}
8493

8594
.legend {
@@ -110,3 +119,83 @@
110119
}
111120
}
112121
}
122+
123+
.mobileTrigger {
124+
display: flex;
125+
align-items: center;
126+
gap: $sp-4;
127+
cursor: pointer;
128+
129+
.runEntry {
130+
flex: 1 1 auto;
131+
}
132+
133+
.workflowName {
134+
@include ltelg {
135+
max-width: calc(90vw - 205px);
136+
}
137+
}
138+
139+
@include gtexl {
140+
display: none;
141+
}
142+
}
143+
144+
.mobileMenuIcon {
145+
display: flex;
146+
width: 24px;
147+
height: 24px;
148+
align-items: center;
149+
justify-content: center;
150+
padding-left: $sp-4;
151+
border-left: 1px solid #D1DAE4;
152+
flex: 0 0 38px;
153+
154+
svg {
155+
display: block;
156+
}
157+
}
158+
159+
.contentsWrap {
160+
@include ltelg {
161+
display: none;
162+
position: relative;
163+
164+
flex-direction: column;
165+
background: #fff;
166+
position: fixed;
167+
top: 0;
168+
left: 0;
169+
width: 100vw;
170+
height: 100vh;
171+
z-index: 1000;
172+
padding: $sp-4;
173+
overflow: auto;
174+
175+
&.open {
176+
display: flex;
177+
}
178+
179+
.runsWrap {
180+
margin-bottom: $sp-4;
181+
}
182+
183+
.legend {
184+
margin-top: auto;
185+
}
186+
}
187+
}
188+
189+
.mobileCloseicon {
190+
display: flex;
191+
height: 24px;
192+
align-items: center;
193+
justify-content: flex-end;
194+
cursor: pointer;
195+
margin-bottom: $sp-4;
196+
197+
svg {
198+
display: block;
199+
color: #000;
200+
}
201+
}

src/apps/review/src/pages/ai-scorecards/components/AiWorkflowsSidebar/AiWorkflowsSidebar.tsx

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FC, useMemo } from 'react'
1+
import { FC, useCallback, useMemo, useState } from 'react'
22

33
import styles from './AiWorkflowsSidebar.module.scss'
44
import { useAiScorecardContext } from '../../AiScorecardContext'
@@ -7,48 +7,77 @@ import { AiWorkflowRunStatus } from '~/apps/review/src/lib/components/AiReviewsT
77
import classNames from 'classnames'
88
import { IconAiReview } from '~/apps/review/src/lib/assets/icons'
99
import StatusLabel from '~/apps/review/src/lib/components/AiReviewsTable/StatusLabel'
10-
import { IconOutline } from '~/libs/ui'
10+
import { IconOutline, IconSolid } from '~/libs/ui'
1111
import { Link } from 'react-router-dom'
1212

1313
interface AiWorkflowsSidebarProps {
1414
className?: string
1515
}
1616

1717
const AiWorkflowsSidebar: FC<AiWorkflowsSidebarProps> = props => {
18-
const { workflowRuns, workflowId, submissionId }: AiScorecardContextModel = useAiScorecardContext()
18+
const [isMobileOpen, setIsMobileOpen] = useState(false);
19+
const { workflow, workflowRun, workflowRuns, workflowId, submissionId }: AiScorecardContextModel = useAiScorecardContext()
20+
21+
const toggleOpen = useCallback(() => {
22+
setIsMobileOpen(wasOpen => !wasOpen);
23+
}, []);
24+
25+
const close = useCallback(() => {
26+
setIsMobileOpen(false);
27+
}, []);
1928

2029
return (
2130
<div className={classNames(props.className, styles.wrap)}>
22-
<div className={styles.runsWrap}>
23-
<ul>
24-
{workflowRuns.map(workflowRun => (
25-
<li className={classNames(styles.runEntry, workflowId === workflowRun.workflow.id && styles.active)} key={workflowRun.id}>
26-
<Link to={`../ai-scorecard/${submissionId}/${workflowRun.workflow.id}`} />
27-
<span>
28-
<IconAiReview />
29-
<span className={styles.workflowName}>{workflowRun.workflow.name}</span>
30-
</span>
31-
<AiWorkflowRunStatus run={workflowRun} showScore hideLabel />
32-
</li>
33-
))}
34-
</ul>
35-
</div>
31+
{workflow && workflowRun && (
32+
<div className={styles.mobileTrigger} onClick={toggleOpen}>
33+
<div className={classNames(styles.runEntry, styles.active)}>
34+
<span className={styles.workflowNameWrap}>
35+
<IconAiReview />
36+
<span className={styles.workflowName}>{workflow.name}</span>
37+
</span>
38+
<AiWorkflowRunStatus run={workflowRun} showScore hideLabel />
39+
<div className={styles.mobileMenuIcon}>
40+
<IconOutline.MenuIcon className='icon-xl' />
41+
</div>
42+
</div>
43+
</div>
44+
)}
3645

37-
<div className={styles.legend}>
38-
<div className={styles.legendLabel}>
39-
Legend
46+
<div className={classNames(styles.contentsWrap, isMobileOpen && styles.open)}>
47+
<div className={styles.mobileCloseicon} onClick={toggleOpen}>
48+
<IconSolid.XIcon className='icon-xxl' />
49+
</div>
50+
<div className={styles.runsWrap}>
51+
<ul>
52+
{workflowRuns.map(workflowRun => (
53+
<li className={classNames(styles.runEntry, workflowId === workflowRun.workflow.id && styles.active)} key={workflowRun.id}>
54+
<Link to={`../ai-scorecard/${submissionId}/${workflowRun.workflow.id}`} onClick={close} />
55+
<span className={styles.workflowNameWrap}>
56+
<IconAiReview />
57+
<span className={styles.workflowName}>{workflowRun.workflow.name}</span>
58+
</span>
59+
<AiWorkflowRunStatus run={workflowRun} showScore hideLabel />
60+
</li>
61+
))}
62+
</ul>
63+
</div>
64+
65+
<div className={styles.legend}>
66+
<div className={styles.legendLabel}>
67+
Legend
68+
</div>
69+
<ul>
70+
<li>
71+
<StatusLabel icon={<IconOutline.CheckIcon className='icon-xl' />} label='Passed' status="passed" />
72+
</li>
73+
<li>
74+
<StatusLabel icon={<IconOutline.MinusCircleIcon className='icon-xl' />} label='Failed' status="failed" />
75+
</li>
76+
<li>
77+
<StatusLabel icon={<IconOutline.MinusIcon className='icon-md' />} label='To be filled' status="pending" />
78+
</li>
79+
</ul>
4080
</div>
41-
<ul>
42-
<li>
43-
<StatusLabel icon={<IconOutline.CheckIcon className='icon-xl' />} label='Passed' status="passed" />
44-
</li>
45-
<li>
46-
<StatusLabel icon={<IconOutline.MinusCircleIcon className='icon-xl' />} label='Failed' status="failed" />
47-
</li>
48-
<li>
49-
<StatusLabel icon={<IconOutline.MinusIcon className='icon-md' />} label='To be filled' status="pending" />
50-
</li>
51-
</ul>
5281
</div>
5382
</div>
5483
)

0 commit comments

Comments
 (0)