Skip to content

Commit 1a34958

Browse files
committed
Fix by code review
1 parent 6483f3a commit 1a34958

File tree

29 files changed

+190
-680
lines changed

29 files changed

+190
-680
lines changed

src/common/Breadcrumbs/Breadcrumbs.jsx

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,20 @@ import React, { useMemo, useRef, useState } from 'react'
2121
import PropTypes from 'prop-types'
2222
import { useLocation, useParams } from 'react-router-dom'
2323
import { useSelector } from 'react-redux'
24-
import { startCase } from 'lodash'
24+
import { capitalize } from 'lodash'
2525

2626
import BreadcrumbsStep from './BreadcrumbsStep/BreadcrumbsStep'
2727

28-
import { generateMlrunScreens, generateTabsList } from './breadcrumbs.util'
29-
import { MONITORING_APP_PAGE, PROJECTS_PAGE_PATH } from '../../constants'
28+
import { generateMlrunScreens } from './breadcrumbs.util'
29+
import { PROJECTS_PAGE_PATH } from '../../constants'
3030
import { generateProjectsList } from '../../utils/projects'
3131
import { useMode } from '../../hooks/mode.hook'
3232

33+
import { BREADCRUMBS_STEP_ITEM_TYPE, BREADCRUMBS_STEP_PROJECT_TYPE, BREADCRUMBS_STEP_SCREEN_TYPE } from '../../constants'
34+
3335
import './breadcrumbs.scss'
3436

35-
const Breadcrumbs = ({ onClick = () => { } }) => {
37+
const Breadcrumbs = ({ itemName = '', onClick = () => { } }) => {
3638
const [searchValue, setSearchValue] = useState('')
3739
const [showScreensList, setShowScreensList] = useState(false)
3840
const [showProjectsList, setShowProjectsList] = useState(false)
@@ -44,47 +46,45 @@ const Breadcrumbs = ({ onClick = () => { } }) => {
4446
const projectStore = useSelector(state => state.projectStore)
4547

4648
const projectsList = useMemo(() => {
47-
return generateProjectsList(projectStore.projectsNames.data)
48-
}, [projectStore.projectsNames.data])
49+
const projectsList = generateProjectsList(projectStore.projectsNames.data, params.projectName,)
50+
return projectsList.map(project => ({
51+
...project,
52+
link: location.pathname.replace(params.projectName, project.id)
53+
}))
54+
}, [projectStore.projectsNames.data, location.pathname, params.projectName])
4955

5056
const mlrunScreens = useMemo(() => {
5157
return generateMlrunScreens(params?.projectName ?? '', isDemoMode).filter(screen => !screen.hidden)
5258
}, [isDemoMode, params?.projectName])
53-
const projectTabs = useMemo(() => {
54-
return generateTabsList()
55-
}, [])
59+
60+
5661
const urlParts = useMemo(() => {
57-
if (params.projectName) {
58-
const [projects, projectName, screenName, innerScreenName] = location.pathname.split('/').slice(1, 5)
59-
const screen = mlrunScreens.find(screen => screen.id === (innerScreenName)) ?? mlrunScreens.find(screen => screen.id === (screenName))
60-
let tab = projectTabs.find(tab =>
61-
location.pathname
62-
.split('/')
63-
.slice(3)
64-
.find(pathItem => pathItem === tab.id)
65-
)
66-
67-
if (screen?.id === MONITORING_APP_PAGE) {
68-
tab = {}
69-
}
62+
const [projects, projectName, page, innerScreenName] = location.pathname.split('/').slice(1, 5)
63+
const screen = mlrunScreens.find(screen => screen.id === (page)) || mlrunScreens.find(screen => screen.id === (innerScreenName))
64+
65+
const pathItems = [
66+
{ id: projects, label: capitalize(projects), link: `/${PROJECTS_PAGE_PATH}` },
67+
{ id: projectName, label: projectName, link: `/projects/${projectName}`, type: BREADCRUMBS_STEP_PROJECT_TYPE },
68+
{ id: screen?.id, label: screen?.label, link: screen?.link, type: BREADCRUMBS_STEP_SCREEN_TYPE }
69+
]
7070

71+
itemName && pathItems.push({ id: itemName, label: itemName, type: BREADCRUMBS_STEP_ITEM_TYPE })
72+
73+
74+
if (params.projectName) {
7175
return {
72-
pathItems: [projects, projectName, screen?.label],
76+
pathItems,
7377
screen,
74-
tab: { ...tab, label: startCase(tab?.label?.replace('-', ' ')) || '' },
75-
itemName: params.artifactName || params.funcName || params.jobName || params.workflowProjectName || params.appName || params.name || params.alertName || null,
7678
}
7779
} else {
78-
const [page] = location.pathname.split('/').slice(3, 4)
79-
const screen = mlrunScreens.find(screen => screen.id === page)
80-
8180
return {
82-
pathItems: [PROJECTS_PAGE_PATH, screen?.label || page],
81+
pathItems: pathItems.filter(item => item.type !== BREADCRUMBS_STEP_PROJECT_TYPE),
8382
screen,
84-
itemName: params.artifactName || params.name || params.jobName || params.workflowProjectName || params.alertName || null,
8583
}
8684
}
87-
}, [location.pathname, params, mlrunScreens, projectTabs])
85+
86+
87+
}, [itemName, location.pathname, params, mlrunScreens])
8888

8989
return (
9090
<nav data-testid="breadcrumbs" className="breadcrumbs" ref={breadcrumbsRef}>
@@ -94,6 +94,7 @@ const Breadcrumbs = ({ onClick = () => { } }) => {
9494
<BreadcrumbsStep
9595
key={index}
9696
index={index}
97+
itemName={itemName}
9798
mlrunScreens={mlrunScreens}
9899
onClick={onClick}
99100
params={params}
@@ -105,7 +106,7 @@ const Breadcrumbs = ({ onClick = () => { } }) => {
105106
setShowScreensList={setShowScreensList}
106107
showProjectsList={showProjectsList}
107108
showScreensList={showScreensList}
108-
urlPart={urlPart}
109+
pathItem={urlPart}
109110
urlParts={urlParts}
110111
/>
111112
)
@@ -116,6 +117,7 @@ const Breadcrumbs = ({ onClick = () => { } }) => {
116117
}
117118

118119
Breadcrumbs.propTypes = {
120+
itemName: PropTypes.string,
119121
onClick: PropTypes.func
120122
}
121123

src/common/Breadcrumbs/BreadcrumbsStep/BreadcrumbsStep.jsx

Lines changed: 66 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import classnames from 'classnames'
2525
import BreadcrumbsDropdown from '../../../elements/BreadcrumbsDropdown/BreadcrumbsDropdown'
2626
import { RoundedIcon } from 'igz-controls/components'
2727

28+
import { BREADCRUMBS_STEP_ITEM_TYPE, BREADCRUMBS_STEP_PROJECT_TYPE, BREADCRUMBS_STEP_SCREEN_TYPE } from '../../../constants'
2829
import { scrollToElement } from '../../../utils/scroll.util'
2930

3031
import ArrowIcon from 'igz-controls/images/arrow.svg?react'
@@ -45,7 +46,7 @@ const BreadcrumbsStep = React.forwardRef(
4546
setShowScreensList,
4647
showProjectsList,
4748
showScreensList,
48-
urlPart,
49+
pathItem,
4950
urlParts
5051
},
5152
ref
@@ -54,28 +55,11 @@ const BreadcrumbsStep = React.forwardRef(
5455
const screenListRef = useRef()
5556
const separatorRef = useRef()
5657

57-
const isParam = useMemo(() => Object.values(params ?? {}).includes(urlPart), [urlPart, params])
58-
const label = useMemo(
59-
() => (isParam ? urlPart : urlPart.charAt(0).toUpperCase() + urlPart.slice(1)),
60-
[urlPart, isParam]
61-
)
62-
63-
const to = useMemo(
64-
() => `/${urlParts.pathItems.slice(0, index + 1).join('/')}`,
65-
[index, urlParts.pathItems]
66-
)
6758
const isLastStep = useMemo(
6859
() => index === urlParts.pathItems.length - 1,
6960
[index, urlParts.pathItems.length]
7061
)
7162

72-
const separatorClassNames = classnames(
73-
'breadcrumbs__separator',
74-
((urlParts.pathItems[index + 1] === urlParts.screen?.id && !isParam) ||
75-
urlParts.pathItems[index + 1] === params.projectName) &&
76-
'breadcrumbs__separator_tumbler'
77-
)
78-
7963
const handleSelectDropdownItem = separatorRef => {
8064
if (showProjectsList) setShowProjectsList(false)
8165

@@ -136,117 +120,94 @@ const BreadcrumbsStep = React.forwardRef(
136120
}, [handleCloseDropdown])
137121

138122
const handleSeparatorClick = (nextItem, separatorRef) => {
139-
const nextItemIsScreen = Boolean(mlrunScreens.find(screen => screen.label === nextItem))
123+
if (nextItem.type === 'screen' || nextItem.type === 'project') {
140124

141-
if (nextItemIsScreen || nextItem === params.projectName) {
142125
const [activeSeparator] = document.getElementsByClassName('breadcrumbs__separator_active')
143126

144-
if (
145-
activeSeparator &&
146-
!separatorRef.current.classList.contains('breadcrumbs__separator_active')
147-
) {
148-
activeSeparator.classList.remove('breadcrumbs__separator_active')
127+
if (nextItem.type === BREADCRUMBS_STEP_PROJECT_TYPE) {
128+
setShowProjectsList(state => !state)
129+
130+
if (showScreensList) {
131+
setShowScreensList(false)
132+
}
149133
}
150134

151-
if (nextItemIsScreen) {
135+
if (nextItem.type === BREADCRUMBS_STEP_SCREEN_TYPE) {
152136
setShowScreensList(state => !state)
153137

154138
if (showProjectsList) {
155139
setShowProjectsList(false)
156140
}
157141
}
158142

159-
if (nextItem === params.projectName) {
160-
setShowProjectsList(state => !state)
161-
162-
if (showScreensList) {
163-
setShowScreensList(false)
164-
}
143+
if (
144+
activeSeparator &&
145+
!separatorRef.current.classList.contains('breadcrumbs__separator_active')
146+
) {
147+
activeSeparator.classList.remove('breadcrumbs__separator_active')
165148
}
166149

167150
separatorRef.current.classList.toggle('breadcrumbs__separator_active')
168151
}
169152
}
170153

171154
return isLastStep ? (
172-
<>
173-
{urlParts.itemName ? (
174-
<>
175-
<li
176-
data-testid="breadcrumbs-last-item"
177-
className="breadcrumbs__item"
178-
key={`${index}${urlPart}`}
155+
<li
156+
data-testid="breadcrumbs-last-item"
157+
className="breadcrumbs__item"
158+
key={pathItem.id}
159+
>
160+
{pathItem.label}
161+
</li>
162+
)
163+
: (
164+
<>
165+
<li key={pathItem.id} className="breadcrumbs__item">
166+
<Link to={pathItem.link} onClick={onClick}>
167+
{pathItem.label}
168+
</Link>
169+
</li>
170+
<li key={index} className="breadcrumbs__item">
171+
{urlParts.pathItems[index + 1]?.type === BREADCRUMBS_STEP_ITEM_TYPE ? (<div className='breadcrumbs__separator'><ArrowIcon /></div >) : <RoundedIcon
172+
className='breadcrumbs__separator'
173+
id={`separator-${index}`}
174+
ref={separatorRef}
175+
onClick={() => handleSeparatorClick(urlParts.pathItems[index + 1], separatorRef)}
179176
>
180-
<Link to={urlParts.screen?.link} onClick={onClick}>
181-
{urlParts.screen?.label || label}
182-
</Link>
183-
184-
</li>
185-
<li className="breadcrumbs__separator">
186177
<ArrowIcon />
187-
</li>
188-
<li data-testid="breadcrumbs-tab" className="breadcrumbs__item">
189-
{urlParts.itemName}
190-
</li>
191-
</>
192-
) : (
193-
<li
194-
data-testid="breadcrumbs-last-item"
195-
className="breadcrumbs__item"
196-
key={`${index}${urlPart}`}
197-
>
198-
{urlParts.screen?.label || label}
199-
</li>
200-
)}
201-
</>
202-
) : (
203-
<>
204-
<li key={`${index}${urlPart}`} className="breadcrumbs__item">
205-
<Link to={to} onClick={onClick}>
206-
{label}
207-
</Link>
208-
</li>
209-
<li key={index} className="breadcrumbs__item">
210-
<RoundedIcon
211-
className={separatorClassNames}
212-
id={`separator-${index}`}
213-
ref={separatorRef}
214-
onClick={() => handleSeparatorClick(urlParts.pathItems[index + 1], separatorRef)}
215-
>
216-
<ArrowIcon />
217-
</RoundedIcon>
218-
{showScreensList && urlParts.pathItems[index + 1] === urlParts.screen?.label && (
219-
<BreadcrumbsDropdown
220-
id="breadcrumbs-screens-dropdown"
221-
link={to}
222-
list={mlrunScreens}
223-
onClick={() => handleSelectDropdownItem(separatorRef)}
224-
ref={screenListRef}
225-
selectedItem={urlParts.screen?.id}
226-
searchValue={searchValue}
227-
setSearchValue={setSearchValue}
228-
/>
229-
)}
230-
{showProjectsList && urlParts.pathItems[index + 1] === params.projectName && (
231-
<>
178+
</RoundedIcon>}
179+
{showScreensList && urlParts.pathItems[index + 1].type === BREADCRUMBS_STEP_SCREEN_TYPE && (
232180
<BreadcrumbsDropdown
233-
id="breadcrumbs-projects-dropdown"
234-
link={to}
235-
list={projectsList}
181+
id="breadcrumbs-screens-dropdown"
182+
link={pathItem.link}
183+
list={mlrunScreens}
236184
onClick={() => handleSelectDropdownItem(separatorRef)}
237-
ref={projectListRef}
238-
selectedItem={params.projectName}
185+
ref={screenListRef}
186+
selectedItem={urlParts.screen?.id}
239187
searchValue={searchValue}
240188
setSearchValue={setSearchValue}
241-
urlParts={urlParts}
242-
withSearch
243-
withAllProjects
244189
/>
245-
</>
246-
)}
247-
</li>
248-
</>
249-
)
190+
)}
191+
{showProjectsList && urlParts.pathItems[index + 1].type === BREADCRUMBS_STEP_PROJECT_TYPE && (
192+
<>
193+
<BreadcrumbsDropdown
194+
id="breadcrumbs-projects-dropdown"
195+
link={pathItem.link}
196+
list={projectsList}
197+
onClick={() => handleSelectDropdownItem(separatorRef)}
198+
ref={projectListRef}
199+
selectedItem={params.projectName}
200+
searchValue={searchValue}
201+
setSearchValue={setSearchValue}
202+
urlParts={urlParts}
203+
withSearch
204+
withAllProjects
205+
/>
206+
</>
207+
)}
208+
</li>
209+
</>
210+
)
250211
}
251212
)
252213

@@ -257,27 +218,21 @@ BreadcrumbsStep.propTypes = {
257218
mlrunScreens: PropTypes.arrayOf(PropTypes.object).isRequired,
258219
onClick: PropTypes.func,
259220
params: PropTypes.object.isRequired,
221+
pathItem: PropTypes.object.isRequired,
260222
projectsList: PropTypes.arrayOf(PropTypes.object).isRequired,
261223
searchValue: PropTypes.string.isRequired,
262224
setSearchValue: PropTypes.func.isRequired,
263225
setShowProjectsList: PropTypes.func.isRequired,
264226
setShowScreensList: PropTypes.func.isRequired,
265227
showProjectsList: PropTypes.bool.isRequired,
266228
showScreensList: PropTypes.bool.isRequired,
267-
urlPart: PropTypes.string.isRequired,
268229
urlParts: PropTypes.shape({
269-
pathItems: PropTypes.arrayOf(PropTypes.string).isRequired,
230+
pathItems: PropTypes.arrayOf(PropTypes.object).isRequired,
270231
screen: PropTypes.shape({
271232
id: PropTypes.string,
272233
label: PropTypes.string,
273234
link: PropTypes.string
274235
}),
275-
tab: PropTypes.shape({
276-
id: PropTypes.string,
277-
label: PropTypes.string
278-
279-
}),
280-
itemName: PropTypes.string
281236
}).isRequired
282237
}
283238

src/common/Breadcrumbs/BreadcrumbsStep/breadcrumbsStep.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@
2020
transition: transform 0.2s linear;
2121
user-select: none;
2222

23-
&_tumbler {
24-
cursor: pointer;
25-
}
26-
2723
&_active {
2824
transform: rotate(90deg);
2925
}

src/common/Breadcrumbs/breadcrumbs.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@use 'igz-controls/scss/mixins';
2-
@use 'igz-controls/scss/colors';
32

43
.breadcrumbs {
54
@include mixins.resetSpaces;

0 commit comments

Comments
 (0)