Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion src/api/artifacts-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,35 @@ const artifactsApi = {
newConfig.params.iter = iter
}

return mainHttpClientV2.get(`/projects/${projectName}/artifacts/${artifactName}`, newConfig)
return Promise.resolve({
data: {
kind: 'dataset',
metadata: {
key: 'test3',
project: 'default',
tree: '3c9a5fe2-1ffc-4c4c-864b-a712a8899fe0',
description: '',
iter: null,
uid: 'c4dc3113a581a11ed69ef09258fdc0584d590f74',
updated: '2025-05-06 08:50:01.714000+00:00',
created: '2025-05-06 08:50:01.714000+00:00',
tag: 'latest'
},
spec: {
target_path: 'v3io:///asd/asd',
producer: {
kind: 'api',
name: 'UI',
uri: 'dashboard.default-tenant.app.vmdev63.lab.iguazeng.com'
},
db_key: 'test3'
},
status: {},
project: 'default'
}
})

// return mainHttpClientV2.get(`/projects/${projectName}/artifacts/${artifactName}`, newConfig)
},
getArtifacts: (project, filters, config, withExactName) => {
return fetchArtifacts(project, filters, config, false, withExactName)
Expand Down
2 changes: 1 addition & 1 deletion src/common/CopyToClipboard/CopyToClipboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const CopyToClipboard = ({
}

CopyToClipboard.propTypes = {
children: PropTypes.string,
children: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
className: PropTypes.string,
disabled: PropTypes.bool,
textToCopy: PropTypes.string,
Expand Down
9 changes: 9 additions & 0 deletions src/common/Search/Search.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const Search = ({
placeholder = '',
searchWhileTyping = false,
value = '',
withoutBorder = false,
wrapperClassName = ''
}) => {
const [searchValue, setSearchValue] = useState(value ?? '')
Expand Down Expand Up @@ -112,6 +113,12 @@ const Search = ({
}
}

useEffect(() => {
if (searchValue.length > 0 && value !== searchValue) {
setSearchValue(value)
}
}, [searchValue, value])

return (
<div
data-testid="search-container"
Expand Down Expand Up @@ -141,6 +148,7 @@ const Search = ({
}
}}
value={searchValue}
withoutBorder={withoutBorder}
/>
{matches.length > 0 && label.length > 0 && inputIsFocused && (
<PopUpDialog
Expand Down Expand Up @@ -196,6 +204,7 @@ Search.propTypes = {
placeholder: PropTypes.string,
searchWhileTyping: PropTypes.bool,
value: PropTypes.string,
withoutBorder: PropTypes.bool,
wrapperClassName: PropTypes.string
}

Expand Down
171 changes: 171 additions & 0 deletions src/common/SearchNavigator/SearchNavigator.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
Copyright 2019 Iguazio Systems Ltd.

Licensed under the Apache License, Version 2.0 (the "License") with
an addition restriction as set forth herein. You may not use this
file except in compliance with the License. You may obtain a copy of
the License at http://www.apache.org/licenses/LICENSE-2.0.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.

In addition, you may not use the software for any purposes that are
illegal under applicable law, and the grant of the foregoing license
under the Apache 2.0 license is conditioned upon your compliance with
such restriction.
*/
import { useCallback, useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'

import Search from '../Search/Search'
import { RoundedIcon } from 'igz-controls/components'

import Arrow from 'igz-controls/images/arrow.svg?react'
import Close from 'igz-controls/images/close.svg?react'

import './searchNavigator.scss'

const SearchNavigator = ({ promptTemplate, setSearchResult }) => {
const [matchCount, setMatchCount] = useState(0)
const [activeMatchIndex, setActiveMatchIndex] = useState(0)
const [matches, setMatches] = useState([])
const [searchValue, setSearchValue] = useState('')
const navigatorCounterClassNames = classnames(
'search-navigator__counter',
matchCount > 0 && 'search-navigator__counter_with-divider'
)

const clearResults = useCallback(() => {
setSearchResult(promptTemplate)
setMatches([])
setActiveMatchIndex(0)
setSearchValue('')
setMatchCount(0)
}, [promptTemplate, setSearchResult])

const searchOnChangeHandler = useCallback(
value => {
if (value.length === 0) {
return clearResults()
}

const regex = new RegExp(value, 'gi')
const allMatches = [...promptTemplate.matchAll(regex)]
const count = allMatches.length
let index = 0

const highlighted = promptTemplate.replace(regex, match => {
const marker = `<mark
data-index="${index}"
style="background: ${index === 0 ? '#FFAE4E' : '#FFE37E'}; color: #483f56;">${match}</mark>`

index++

return marker
})

setSearchResult(highlighted)
setMatchCount(count)
setMatches(allMatches)
setActiveMatchIndex(0)
setSearchValue(value)
},
[clearResults, promptTemplate, setSearchResult]
)

const highlightMatch = useCallback(
index => {
if (!matches.length) return

const regex = new RegExp(promptTemplate.match(matches[0])[0], 'gi')
let current = 0

const highlighted = promptTemplate.replace(regex, match => {
const marker = `<mark
data-index="${current}"
style="background: ${current === index ? '#FFAE4E' : '#FFE37E'}; color: #483f56;">${match}</mark>`

current++

return marker
})

setSearchResult(highlighted)
setActiveMatchIndex(index)
},
[matches, promptTemplate, setSearchResult]
)

const goToPrevMatch = () => {
if (!matches.length) return
const prevIndex = (activeMatchIndex - 1 + matchCount) % matchCount
highlightMatch(prevIndex)
}

const goToNextMatch = () => {
if (!matches.length) return
const nextIndex = (activeMatchIndex + 1) % matchCount
highlightMatch(nextIndex)
}

useEffect(() => {
const activeMark = document.querySelector(`mark[data-index="${activeMatchIndex}"]`)

if (activeMark) {
activeMark.scrollIntoView({
behavior: 'smooth',
block: 'center'
})
}
}, [activeMatchIndex])

return (
<div className="search-navigator">
<Search
onChange={searchOnChangeHandler}
placeholder="Find in prompt.."
value={searchValue}
withoutBorder
/>
<div className={navigatorCounterClassNames}>
{matchCount > 0 && `${activeMatchIndex + 1}/${matchCount}`}
</div>
{searchValue.length > 0 && (
<div className="search-navigator__buttons">
<RoundedIcon
className="search-navigator__button search-navigator__button_back"
onClick={goToPrevMatch}
disabled={matchCount === 0}
>
<Arrow />
</RoundedIcon>
<RoundedIcon
className="search-navigator__button search-navigator__button_next"
onClick={goToNextMatch}
disabled={matchCount === 0}
>
<Arrow />
</RoundedIcon>
<RoundedIcon
className="search-navigator__button search-navigator__button_cancel"
onClick={clearResults}
disabled={searchValue.length === 0}
>
<Close />
</RoundedIcon>
</div>
)}
</div>
)
}

SearchNavigator.propTypes = {
promptTemplate: PropTypes.string.isRequired,
setSearchResult: PropTypes.func.isRequired
}

export default SearchNavigator
58 changes: 58 additions & 0 deletions src/common/SearchNavigator/searchNavigator.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
@use 'igz-controls/scss/borders';
@use 'igz-controls/scss/colors';

.search-navigator {
display: flex;
align-items: center;
min-width: 280px;
border: borders.$primaryBorder;
border-radius: 4px;

&__counter {
display: flex;
font-size: 13px;
color: colors.$topaz;

&:after {
display: none;
content: '';
width: 5px;
height: 15px;
margin: 0 5px 0 8px;
border-right: borders.$primaryBorder;
}

&_with-divider {
&:after {
display: block;
}
}
}

&__buttons {
display: flex;
padding-right: 10px;
}

&__button {
.round-icon-cp__circle {
width: 26px;
height: 26px;
}

&_back {
rotate: -90deg;
}

&_next {
rotate: 90deg;
}

&_cancel {
.round-icon-cp__circle {
width: 24px;
height: 24px;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useCallback, useState } from 'react'
import { ARGUMENTS_TAB, PROMPT_TAB } from '../../../constants'
import PromptTab from './PromptTab'

import './detailsPromptTemplate.scss'

const DetailsPromptTemplate = () => {
const [selectedTab, setSelectedTab] = useState(PROMPT_TAB)
const tabs = [
{ id: PROMPT_TAB, label: 'Prompt' },
{ id: ARGUMENTS_TAB, label: 'Arguments' }
]

const handleTabChange = useCallback(tabName => {
setSelectedTab(tabName)
}, [])

return (
<div className="prompt-template">
{selectedTab === PROMPT_TAB ? (
<PromptTab handleTabChange={handleTabChange} tabs={tabs} selectedTab={selectedTab} />
) : null}
</div>
)
}

export default DetailsPromptTemplate
Loading