mirror of https://github.com/harness/drone.git
feat: [code-2177]: add regex icon in keyword search (#2340)
* fix: [code-2177]: fix jumping issue * feat: [code-2177]: fix padding * fix: [code-2177]: fix icons * fix: [code-2177]: fix issue when message box is not there * fix: [code-2177]: remove search for repo dropdown * feat: [code-2177]: fix issue on recursive toggle in repolvlsrch * fix: [code-2177]: fix issue on not showing * fix: [code-2177]: fix comments * feat: [code-2177]: update to mocks and fix some issues * feat: [code-2177]: add regex icon in keyword searchpull/3545/head
parent
497c426a01
commit
4680192ba6
|
@ -30,6 +30,23 @@
|
|||
.searchContainer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.searchCtn {
|
||||
&[data-search-mode='keyword'] {
|
||||
.toggleRegexIconContainer {
|
||||
position: absolute;
|
||||
right: -23px !important;
|
||||
top: 3.8px !important;
|
||||
z-index: 1;
|
||||
|
||||
.img {
|
||||
position: unset !important;
|
||||
right: unset;
|
||||
top: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.searchIcon {
|
||||
|
|
|
@ -17,13 +17,16 @@
|
|||
/* eslint-disable */
|
||||
// This is an auto-generated file
|
||||
export declare const backdrop: string
|
||||
export declare const img: string
|
||||
export declare const layout: string
|
||||
export declare const portal: string
|
||||
export declare const sampleKeywordSearchQuery: string
|
||||
export declare const sampleSemanticSearchQuery: string
|
||||
export declare const searchBox: string
|
||||
export declare const searchContainer: string
|
||||
export declare const searchCtn: string
|
||||
export declare const searchIcon: string
|
||||
export declare const searchModal: string
|
||||
export declare const sectionHeader: string
|
||||
export declare const selected: string
|
||||
export declare const toggleRegexIconContainer: string
|
||||
|
|
|
@ -15,20 +15,18 @@
|
|||
*/
|
||||
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import cx from 'classnames'
|
||||
import { Container, Dialog, Layout, Text, Utils } from '@harnessio/uicore'
|
||||
import { Color } from '@harnessio/design-system'
|
||||
import { Filter, LongArrowDownLeft } from 'iconoir-react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import { noop } from 'lodash-es'
|
||||
import cx from 'classnames'
|
||||
|
||||
import { useAppContext } from 'AppContext'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
||||
import { ButtonRoleProps } from 'utils/Utils'
|
||||
import type { GitInfoProps } from 'utils/GitUtils'
|
||||
|
||||
import { SearchInputWithSpinner } from 'components/SearchInputWithSpinner/SearchInputWithSpinner'
|
||||
import CodeSearchBar from 'components/CodeSearchBar/CodeSearchBar'
|
||||
import svg from './search-background.svg?url'
|
||||
|
@ -51,7 +49,7 @@ const CodeSearch = ({ repoMetadata }: CodeSearchProps) => {
|
|||
const [showSearchModal, setShowSearchModal] = useState(false)
|
||||
const [searchSampleQueryIndex, setSearchSampleQueryIndex] = useState<number>(0)
|
||||
const [searchMode, setSearchMode] = useState(SEARCH_MODE.KEYWORD)
|
||||
|
||||
const [regexEnabled, setRegexEnabled] = useState<boolean>(false)
|
||||
const performSearch = useCallback(
|
||||
(q: string, mode: SEARCH_MODE) => {
|
||||
if (repoMetadata?.path) {
|
||||
|
@ -59,18 +57,18 @@ const CodeSearch = ({ repoMetadata }: CodeSearchProps) => {
|
|||
pathname: routes.toCODERepositorySearch({
|
||||
repoPath: repoMetadata.path as string
|
||||
}),
|
||||
search: `q=${q}&mode=${mode}`
|
||||
search: `q=${q}&mode=${mode}®ex=${regexEnabled}`
|
||||
})
|
||||
} else {
|
||||
history.push({
|
||||
pathname: routes.toCODESpaceSearch({
|
||||
space
|
||||
}),
|
||||
search: `q=${q}`
|
||||
search: `q=${q}®ex=${regexEnabled}`
|
||||
})
|
||||
}
|
||||
},
|
||||
[history, repoMetadata?.path, routes, searchMode]
|
||||
[history, repoMetadata?.path, routes, searchMode, regexEnabled]
|
||||
)
|
||||
const onSearch = useCallback(() => {
|
||||
if (search?.trim()) {
|
||||
|
@ -138,6 +136,8 @@ const CodeSearch = ({ repoMetadata }: CodeSearchProps) => {
|
|||
<Layout.Horizontal className={css.layout}>
|
||||
<Container className={css.searchContainer}>
|
||||
<CodeSearchBar
|
||||
setRegexEnabled={setRegexEnabled}
|
||||
regexEnabled={regexEnabled}
|
||||
searchMode={searchMode}
|
||||
setSearchMode={setSearchMode}
|
||||
value={search}
|
||||
|
|
|
@ -15,23 +15,20 @@
|
|||
*/
|
||||
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import cx from 'classnames'
|
||||
import { Container, Dialog, Layout, Text, Utils } from '@harnessio/uicore'
|
||||
import { Color } from '@harnessio/design-system'
|
||||
import { Filter } from 'iconoir-react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import { noop } from 'lodash-es'
|
||||
import cx from 'classnames'
|
||||
|
||||
import { useAppContext } from 'AppContext'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { useGetSpaceParam } from 'hooks/useGetSpaceParam'
|
||||
import { ButtonRoleProps } from 'utils/Utils'
|
||||
import type { GitInfoProps } from 'utils/GitUtils'
|
||||
|
||||
import { SearchInputWithSpinner } from 'components/SearchInputWithSpinner/SearchInputWithSpinner'
|
||||
import KeywordSearchbar from 'components/KeywordSearchbar/KeywordSearchbar'
|
||||
|
||||
import css from './KeywordSearch.module.scss'
|
||||
|
||||
interface KeywordSearchProps {
|
||||
|
@ -43,6 +40,7 @@ const KeywordSearch = ({ repoMetadata }: KeywordSearchProps) => {
|
|||
const { routes } = useAppContext()
|
||||
const space = useGetSpaceParam()
|
||||
const history = useHistory()
|
||||
const [regexEnabled, setRegexEnabled] = useState<boolean>(false)
|
||||
|
||||
const [search, setSearch] = useState('')
|
||||
const [showSearchModal, setShowSearchModal] = useState(false)
|
||||
|
@ -55,18 +53,18 @@ const KeywordSearch = ({ repoMetadata }: KeywordSearchProps) => {
|
|||
pathname: routes.toCODERepositorySearch({
|
||||
repoPath: repoMetadata.path as string
|
||||
}),
|
||||
search: `q=${q}`
|
||||
search: `q=${q}®ex=${regexEnabled}`
|
||||
})
|
||||
} else {
|
||||
history.push({
|
||||
pathname: routes.toCODESpaceSearch({
|
||||
space
|
||||
}),
|
||||
search: `q=${q}`
|
||||
search: `q=${q}®ex=${regexEnabled}`
|
||||
})
|
||||
}
|
||||
},
|
||||
[history, repoMetadata?.path, routes]
|
||||
[history, repoMetadata?.path, routes, regexEnabled]
|
||||
)
|
||||
const onSearch = useCallback(() => {
|
||||
if (search?.trim()) {
|
||||
|
@ -112,6 +110,8 @@ const KeywordSearch = ({ repoMetadata }: KeywordSearchProps) => {
|
|||
value={search}
|
||||
onChange={setSearch}
|
||||
onSearch={onSearch}
|
||||
regexEnabled={regexEnabled}
|
||||
setRegexEnabled={setRegexEnabled}
|
||||
onKeyDown={e => {
|
||||
if (!search?.trim()) {
|
||||
switch (e.key) {
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
color: transparent !important;
|
||||
caret-color: var(--black);
|
||||
}
|
||||
.toggleRegexIconContainer {
|
||||
right: 39px !important;
|
||||
top: 4.5px !important;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&[data-search-mode='semantic'] {
|
||||
|
@ -64,7 +69,7 @@
|
|||
|
||||
.toggleBtn {
|
||||
position: absolute;
|
||||
right: 31px;
|
||||
right: 62px;
|
||||
top: 7px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
@ -72,7 +77,7 @@
|
|||
.toggleHiddenBtn {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
right: 41px !important;
|
||||
right: 66px !important;
|
||||
top: 8px;
|
||||
border-radius: 8px;
|
||||
right: 49px;
|
||||
|
@ -94,15 +99,28 @@
|
|||
}
|
||||
.toggleTitle {
|
||||
position: absolute;
|
||||
right: 81px;
|
||||
right: 105px;
|
||||
top: 7px;
|
||||
}
|
||||
|
||||
.toggleRegexIconContainer {
|
||||
position: absolute;
|
||||
right: 39px !important;
|
||||
top: 4.5px !important;
|
||||
z-index: 1;
|
||||
}
|
||||
.toggleRegexIconContainer:hover {
|
||||
fill: var(--primary-7) !important;
|
||||
}
|
||||
.toggleLogo {
|
||||
position: absolute;
|
||||
right: 80px !important;
|
||||
right: 105px !important;
|
||||
top: 3.7px !important;
|
||||
}
|
||||
.bp3-popover-wrapper {
|
||||
right: 29px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.searchIcon {
|
||||
position: absolute;
|
||||
|
@ -111,3 +129,20 @@
|
|||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.popover {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
top: -23px;
|
||||
right: 50px !important;
|
||||
}
|
||||
|
||||
.layoutCtn {
|
||||
display: flex;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
.messageContainer {
|
||||
width: 100%;
|
||||
height: 0px !important;
|
||||
}
|
||||
|
|
|
@ -17,11 +17,16 @@
|
|||
/* eslint-disable */
|
||||
// This is an auto-generated file
|
||||
export declare const andOr: string
|
||||
export declare const bp3PopoverWrapper: string
|
||||
export declare const highltedText: string
|
||||
export declare const layoutCtn: string
|
||||
export declare const messageContainer: string
|
||||
export declare const popover: string
|
||||
export declare const searchCtn: string
|
||||
export declare const searchIcon: string
|
||||
export declare const textCtn: string
|
||||
export declare const toggleBtn: string
|
||||
export declare const toggleHiddenBtn: string
|
||||
export declare const toggleLogo: string
|
||||
export declare const toggleRegexIconContainer: string
|
||||
export declare const toggleTitle: string
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
import React, { useState, Dispatch, FC, SetStateAction, useEffect } from 'react'
|
||||
|
||||
import cx from 'classnames'
|
||||
import { Switch } from '@blueprintjs/core'
|
||||
import { Container, Text } from '@harnessio/uicore'
|
||||
import { Classes, PopoverInteractionKind, PopoverPosition, Switch } from '@blueprintjs/core'
|
||||
import { Container, Popover, StringSubstitute, Text } from '@harnessio/uicore'
|
||||
import { Color, FontVariation } from '@harnessio/design-system'
|
||||
import { Link, useParams } from 'react-router-dom'
|
||||
import { SearchInputWithSpinner } from 'components/SearchInputWithSpinner/SearchInputWithSpinner'
|
||||
|
@ -27,6 +27,9 @@ import type { Identifier } from 'utils/types'
|
|||
import { useStrings } from 'framework/strings'
|
||||
import { SEARCH_MODE } from 'components/CodeSearch/CodeSearch'
|
||||
import svg from '../CodeSearch/search-background.svg?url'
|
||||
import Regex from '../../icons/regex.svg?url'
|
||||
import RegexEnabled from '../../icons/regexEnabled.svg?url'
|
||||
|
||||
import css from './CodeSearchBar.module.scss'
|
||||
|
||||
interface CodeSearchBarProps {
|
||||
|
@ -36,11 +39,22 @@ interface CodeSearchBarProps {
|
|||
onKeyDown?: (e: React.KeyboardEvent<HTMLElement>) => void
|
||||
setSearchMode: Dispatch<SetStateAction<SEARCH_MODE>>
|
||||
searchMode: SEARCH_MODE
|
||||
regexEnabled: boolean
|
||||
setRegexEnabled: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const KEYWORD_REGEX = /((?:(?:-{0,1})(?:repo|lang|file|case|count)):\S*|(?: or|and ))/gi
|
||||
|
||||
const CodeSearchBar: FC<CodeSearchBarProps> = ({ value, onChange, onSearch, onKeyDown, searchMode, setSearchMode }) => {
|
||||
const CodeSearchBar: FC<CodeSearchBarProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
onSearch,
|
||||
onKeyDown,
|
||||
searchMode,
|
||||
setSearchMode,
|
||||
setRegexEnabled,
|
||||
regexEnabled
|
||||
}) => {
|
||||
const { getString } = useStrings()
|
||||
const { hooks, routingId, defaultSettingsURL, isCurrentSessionPublic } = useAppContext()
|
||||
const { SEMANTIC_SEARCH_ENABLED: isSemanticSearchFFEnabled } = hooks?.useFeatureFlags()
|
||||
|
@ -102,61 +116,99 @@ const CodeSearchBar: FC<CodeSearchBarProps> = ({ value, onChange, onSearch, onKe
|
|||
onKeyDown={onKeyDown}
|
||||
placeholder={isSemanticMode ? getString('codeSearchModal') : getString('keywordSearchPlaceholder')}
|
||||
/>
|
||||
<Container className={css.layoutCtn}>
|
||||
{enableSemanticSearch ? (
|
||||
<>
|
||||
{isSemanticMode ? (
|
||||
<img className={cx(css.toggleLogo)} src={svg} width={122} height={25} />
|
||||
) : (
|
||||
<Text
|
||||
className={cx(css.toggleTitle)}
|
||||
font={{ variation: FontVariation.SMALL_SEMI }}
|
||||
color={Color.GREY_300}
|
||||
style={{ whiteSpace: 'nowrap' }}>
|
||||
{getString('enableAISearch')}
|
||||
</Text>
|
||||
)}
|
||||
<Switch
|
||||
onChange={() => {
|
||||
searchMode === SEARCH_MODE.KEYWORD
|
||||
? setSearchMode(SEARCH_MODE.SEMANTIC)
|
||||
: setSearchMode(SEARCH_MODE.KEYWORD)
|
||||
}}
|
||||
className={cx(css.toggleBtn)}
|
||||
checked={SEARCH_MODE.SEMANTIC === searchMode}></Switch>
|
||||
|
||||
{enableSemanticSearch ? (
|
||||
<>
|
||||
{isSemanticMode ? (
|
||||
<img className={cx(css.toggleLogo)} src={svg} width={122} height={25} />
|
||||
) : (
|
||||
<Text
|
||||
className={cx(css.toggleTitle)}
|
||||
font={{ variation: FontVariation.SMALL_SEMI }}
|
||||
color={Color.GREY_300}
|
||||
style={{ whiteSpace: 'nowrap' }}>
|
||||
{getString('enableAISearch')}
|
||||
</Text>
|
||||
)}
|
||||
<Switch
|
||||
onChange={() => {
|
||||
searchMode === SEARCH_MODE.KEYWORD
|
||||
? setSearchMode(SEARCH_MODE.SEMANTIC)
|
||||
: setSearchMode(SEARCH_MODE.KEYWORD)
|
||||
}}
|
||||
className={cx(css.toggleBtn)}
|
||||
checked={SEARCH_MODE.SEMANTIC === searchMode}></Switch>
|
||||
|
||||
<button
|
||||
className={cx(css.toggleHiddenBtn, css.toggleBtn)}
|
||||
onClick={() =>
|
||||
searchMode === SEARCH_MODE.KEYWORD
|
||||
? setSearchMode(SEARCH_MODE.SEMANTIC)
|
||||
: setSearchMode(SEARCH_MODE.KEYWORD)
|
||||
}></button>
|
||||
</>
|
||||
) : (
|
||||
aidaSettingResponse?.data?.value != 'true' &&
|
||||
isSemanticSearchFFEnabled &&
|
||||
!isAidaSettingLoading && (
|
||||
<Container
|
||||
background={Color.AI_PURPLE_50}
|
||||
padding="small"
|
||||
margin={{ top: 'xsmall', right: 'small', left: 'xsmall' }}>
|
||||
<Text
|
||||
font={{ variation: FontVariation.BODY2 }}
|
||||
margin={{ bottom: 'small' }}
|
||||
icon="info-messaging"
|
||||
iconProps={{ size: 15 }}>
|
||||
{getString('turnOnSemanticSearch')}
|
||||
</Text>
|
||||
<Text font={{ variation: FontVariation.BODY2_SEMI }} margin={{ bottom: 'small' }} color={Color.GREY_450}>
|
||||
{getString('enableAIDAMessage')}
|
||||
</Text>
|
||||
<Link to={defaultSettingsURL} color={Color.AI_PURPLE_800}>
|
||||
{getString('reviewProjectSettings')}
|
||||
</Link>
|
||||
</Container>
|
||||
)
|
||||
)}
|
||||
<button
|
||||
className={cx(css.toggleHiddenBtn, css.toggleBtn)}
|
||||
onClick={() =>
|
||||
searchMode === SEARCH_MODE.KEYWORD
|
||||
? setSearchMode(SEARCH_MODE.SEMANTIC)
|
||||
: setSearchMode(SEARCH_MODE.KEYWORD)
|
||||
}></button>
|
||||
</>
|
||||
) : (
|
||||
aidaSettingResponse?.data?.value != 'true' &&
|
||||
isSemanticSearchFFEnabled &&
|
||||
!isAidaSettingLoading && (
|
||||
<Container
|
||||
background={Color.AI_PURPLE_50}
|
||||
padding="small"
|
||||
className={css.messageContainer}
|
||||
margin={{ top: 'xsmall', right: 'small', left: 'xsmall' }}>
|
||||
<Text
|
||||
font={{ variation: FontVariation.BODY2 }}
|
||||
margin={{ bottom: 'small' }}
|
||||
icon="info-messaging"
|
||||
iconProps={{ size: 15 }}>
|
||||
{getString('turnOnSemanticSearch')}
|
||||
</Text>
|
||||
<Text font={{ variation: FontVariation.BODY2_SEMI }} margin={{ bottom: 'small' }} color={Color.GREY_450}>
|
||||
{getString('enableAIDAMessage')}
|
||||
</Text>
|
||||
<Link to={defaultSettingsURL} color={Color.AI_PURPLE_800}>
|
||||
{getString('reviewProjectSettings')}
|
||||
</Link>
|
||||
</Container>
|
||||
)
|
||||
)}
|
||||
{isSemanticSearchFFEnabled && aidaSettingResponse?.data?.value === 'true' && (
|
||||
<Container className={css.messageContainer}></Container>
|
||||
)}
|
||||
{!isSemanticMode && (
|
||||
<>
|
||||
<Popover
|
||||
content={
|
||||
<Container padding="medium">
|
||||
<Text font={{ variation: FontVariation.SMALL }} color={Color.WHITE}>
|
||||
<StringSubstitute
|
||||
str={getString('regex.tooltip')}
|
||||
vars={{
|
||||
regex: <strong>{getString('regex.string')}</strong>,
|
||||
enable: regexEnabled ? getString('regex.enabled') : getString('regex.disabled'),
|
||||
disable: regexEnabled ? getString('regex.disable') : getString('regex.enable')
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
</Container>
|
||||
}
|
||||
popoverClassName={cx(css.popover, Classes.DARK)}
|
||||
interactionKind={PopoverInteractionKind.HOVER_TARGET_ONLY}
|
||||
position={PopoverPosition.BOTTOM_RIGHT}
|
||||
isDark={true}>
|
||||
<img
|
||||
className={css.toggleRegexIconContainer}
|
||||
src={regexEnabled ? RegexEnabled : Regex}
|
||||
height={22}
|
||||
width={22}
|
||||
onClick={() => {
|
||||
setRegexEnabled(!regexEnabled)
|
||||
}}
|
||||
/>
|
||||
</Popover>
|
||||
</>
|
||||
)}
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -64,4 +64,20 @@
|
|||
right: 53px;
|
||||
top: 9px;
|
||||
}
|
||||
.toggleRegexIconContainer {
|
||||
position: absolute;
|
||||
right: 30px !important;
|
||||
top: 4.5px !important;
|
||||
cursor: pointer !important;
|
||||
z-index: 1;
|
||||
}
|
||||
.toggleRegexIconContainer:hover {
|
||||
fill: var(--primary-7) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.popover {
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
right: 5px !important;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
// This is an auto-generated file
|
||||
export declare const andOr: string
|
||||
export declare const highltedText: string
|
||||
export declare const popover: string
|
||||
export declare const searchCtn: string
|
||||
export declare const textCtn: string
|
||||
export declare const toggleRegexIconContainer: string
|
||||
export declare const toggleSearch: string
|
||||
export declare const toggleTitle: string
|
||||
|
|
|
@ -15,9 +15,14 @@
|
|||
*/
|
||||
|
||||
import React, { FC } from 'react'
|
||||
|
||||
import cx from 'classnames'
|
||||
import { Container, Popover, StringSubstitute, Text } from '@harnessio/uicore'
|
||||
import { Classes, PopoverInteractionKind, PopoverPosition } from '@blueprintjs/core'
|
||||
import { Color, FontVariation } from '@harnessio/design-system'
|
||||
import { useStrings } from 'framework/strings'
|
||||
import { SearchInputWithSpinner } from 'components/SearchInputWithSpinner/SearchInputWithSpinner'
|
||||
|
||||
import Regex from '../../icons/regex.svg?url'
|
||||
import RegexEnabled from '../../icons/regexEnabled.svg?url'
|
||||
import css from './KeywordSearchbar.module.scss'
|
||||
|
||||
interface KeywordSearchbarProps {
|
||||
|
@ -25,11 +30,22 @@ interface KeywordSearchbarProps {
|
|||
onChange: (value: string) => void
|
||||
onSearch?: (searchTerm: string) => void
|
||||
onKeyDown?: (e: React.KeyboardEvent<HTMLElement>) => void
|
||||
regexEnabled: boolean
|
||||
setRegexEnabled: (value: boolean) => void
|
||||
}
|
||||
|
||||
const KEYWORD_REGEX = /((?:(?:-{0,1})(?:repo|lang|file|case|count)):\S*|(?: or|and ))/gi
|
||||
|
||||
const KeywordSearchbar: FC<KeywordSearchbarProps> = ({ value, onChange, onSearch, onKeyDown }) => {
|
||||
const KeywordSearchbar: FC<KeywordSearchbarProps> = ({
|
||||
value,
|
||||
onChange,
|
||||
onSearch,
|
||||
onKeyDown,
|
||||
regexEnabled,
|
||||
setRegexEnabled
|
||||
}) => {
|
||||
const { getString } = useStrings()
|
||||
|
||||
return (
|
||||
<div className={css.searchCtn}>
|
||||
<div className={css.textCtn}>
|
||||
|
@ -73,6 +89,37 @@ const KeywordSearchbar: FC<KeywordSearchbarProps> = ({ value, onChange, onSearch
|
|||
onSearch={onSearch}
|
||||
onKeyDown={onKeyDown}
|
||||
/>
|
||||
|
||||
<Container className={css.toggleRegexIconContainer}>
|
||||
<Popover
|
||||
content={
|
||||
<Container padding="medium">
|
||||
<Text font={{ variation: FontVariation.SMALL }} color={Color.WHITE}>
|
||||
<StringSubstitute
|
||||
str={getString('regex.tooltip')}
|
||||
vars={{
|
||||
regex: <strong>{getString('regex.string')}</strong>,
|
||||
enable: regexEnabled ? getString('regex.enabled') : getString('regex.disabled'),
|
||||
disable: regexEnabled ? getString('regex.disable') : getString('regex.enable')
|
||||
}}
|
||||
/>
|
||||
</Text>
|
||||
</Container>
|
||||
}
|
||||
popoverClassName={cx(css.popover, Classes.DARK)}
|
||||
interactionKind={PopoverInteractionKind.HOVER_TARGET_ONLY}
|
||||
position={PopoverPosition.BOTTOM_RIGHT}
|
||||
isDark={true}>
|
||||
<img
|
||||
src={regexEnabled ? RegexEnabled : Regex}
|
||||
height={22}
|
||||
width={22}
|
||||
onClick={() => {
|
||||
setRegexEnabled?.(!regexEnabled)
|
||||
}}
|
||||
/>
|
||||
</Popover>
|
||||
</Container>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -908,6 +908,12 @@ export interface StringsMap {
|
|||
recursiveSearchLabel: string
|
||||
recursiveSearchTooltip: string
|
||||
refresh: string
|
||||
'regex.disable': string
|
||||
'regex.disabled': string
|
||||
'regex.enable': string
|
||||
'regex.enabled': string
|
||||
'regex.string': string
|
||||
'regex.tooltip': string
|
||||
reject: string
|
||||
rejected: string
|
||||
remove: string
|
||||
|
@ -970,7 +976,6 @@ export interface StringsMap {
|
|||
'searchScope.base': string
|
||||
'searchScope.orgAndProj': string
|
||||
'searchScope.orgOnly': string
|
||||
'searchScope.placeholder': string
|
||||
'searchScope.title': string
|
||||
secret: string
|
||||
'secrets.create': string
|
||||
|
|
|
@ -1285,3 +1285,10 @@ searchScope:
|
|||
orgOnly: Organizations only
|
||||
orgAndProj: Organizations and Projects
|
||||
title: Search scope
|
||||
regex:
|
||||
tooltip: '{regex} search {enable}. Click to {disable}'
|
||||
enable: enable
|
||||
disable: disable
|
||||
enabled: enabled
|
||||
disabled: disabled
|
||||
string: RegEx
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="#6B6D85" d="m12.56 15.38.23-3.487-2.977 1.955-1.23-2.126 3.206-1.532-3.207-1.532 1.231-2.126 2.977 1.955L12.56 5h2.471l-.239 3.487 2.977-1.955L19 8.658l-3.197 1.532L19 11.722l-1.231 2.126-2.976-1.955.238 3.487zM6.503 19q-.62 0-1.065-.43A1.42 1.42 0 0 1 5 17.526q0-.603.438-1.033.445-.43 1.065-.43.601 0 1.053.43.45.43.45 1.033 0 .405-.212.743-.207.332-.545.534a1.46 1.46 0 0 1-.746.197"/></svg>
|
After Width: | Height: | Size: 481 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="#0278D5" d="m12.56 15.38.23-3.487-2.977 1.955-1.23-2.126 3.206-1.532-3.207-1.532 1.231-2.126 2.977 1.955L12.56 5h2.471l-.239 3.487 2.977-1.955L19 8.658l-3.197 1.532L19 11.722l-1.231 2.126-2.976-1.955.238 3.487zM6.503 19q-.62 0-1.065-.43A1.42 1.42 0 0 1 5 17.526q0-.603.438-1.033.445-.43 1.065-.43.601 0 1.053.43.45.43.45 1.033 0 .405-.212.743-.207.332-.545.534a1.46 1.46 0 0 1-.746.197"/><rect width="24" height="24" fill="#0278D5" rx="4"/><path fill="#fff" d="m12.56 15.38.23-3.487-2.977 1.955-1.23-2.126 3.206-1.532-3.207-1.532 1.231-2.126 2.977 1.955L12.56 5h2.471l-.239 3.487 2.977-1.955L19 8.658l-3.197 1.532L19 11.722l-1.231 2.126-2.976-1.955.238 3.487zM6.503 19q-.62 0-1.065-.43A1.42 1.42 0 0 1 5 17.526q0-.603.438-1.033.445-.43 1.065-.43.601 0 1.053.43.45.43.45 1.033 0 .405-.212.743-.207.332-.545.534a1.46 1.46 0 0 1-.746.197"/></svg>
|
After Width: | Height: | Size: 930 B |
|
@ -73,7 +73,7 @@ const Search = () => {
|
|||
const { showError } = useToaster()
|
||||
const repoPath = repoName ? `${space}/${repoName}` : undefined
|
||||
|
||||
const { q, mode } = useQueryParams<{ q: string; mode: SEARCH_MODE }>()
|
||||
const { q, mode, regex } = useQueryParams<{ q: string; mode: SEARCH_MODE; regex: string }>()
|
||||
const [searchTerm, setSearchTerm] = useState(q || '')
|
||||
const [searchMode, setSearchMode] = useState(mode)
|
||||
const [selectedRepositories, setSelectedRepositories] = useState<SelectOption[]>([])
|
||||
|
@ -83,6 +83,8 @@ const Search = () => {
|
|||
|
||||
const [recursiveSearchEnabled, setRecursiveSearchEnabled] = useState(!projectId ? true : false)
|
||||
const [curScopeLabel, setCurScopeLabel] = useState<SelectOption>()
|
||||
const [regexEnabled, setRegexEnabled] = useState<boolean>(regex === 'true' ? true : false)
|
||||
|
||||
//semantic
|
||||
// const [loadingSearch, setLoadingSearch] = useState(false)
|
||||
const [semanticSearchResult, setSemanticSearchResult] = useState<SemanticSearchResultType[]>([])
|
||||
|
@ -131,7 +133,8 @@ const Search = () => {
|
|||
space_paths: !repoPath && !repoPaths.length ? [space] : [],
|
||||
query,
|
||||
max_result_count: maxResultCount,
|
||||
recursive: recursiveSearchEnabled
|
||||
recursive: recursiveSearchEnabled,
|
||||
enable_regex: regexEnabled
|
||||
})
|
||||
|
||||
setKeyowordSearchResults(res)
|
||||
|
@ -141,8 +144,8 @@ const Search = () => {
|
|||
} catch (error) {
|
||||
showError(getErrorMessage(error))
|
||||
}
|
||||
}, 300),
|
||||
[selectedLanguages, selectedRepositories, repoPath, mode, recursiveSearchEnabled]
|
||||
}, 300), // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[selectedLanguages, selectedRepositories, repoPath, mode, recursiveSearchEnabled, regexEnabled]
|
||||
)
|
||||
|
||||
const performSemanticSearch = useCallback(() => {
|
||||
|
@ -185,6 +188,8 @@ const Search = () => {
|
|||
searchMode={searchMode}
|
||||
setSearchMode={setSearchMode}
|
||||
value={searchTerm}
|
||||
regexEnabled={regexEnabled}
|
||||
setRegexEnabled={setRegexEnabled}
|
||||
onChange={text => {
|
||||
setSearchTerm(text)
|
||||
}}
|
||||
|
@ -203,6 +208,8 @@ const Search = () => {
|
|||
) : (
|
||||
<KeywordSearchbar
|
||||
value={searchTerm}
|
||||
regexEnabled={regexEnabled}
|
||||
setRegexEnabled={setRegexEnabled}
|
||||
onChange={text => {
|
||||
setSearchTerm(text)
|
||||
}}
|
||||
|
|
|
@ -94,7 +94,7 @@ const KeywordSearchFilters: React.FC<KeywordSearchFiltersProps> = ({
|
|||
const [scopeLabel, setScopeLabel] = useState<SelectOption>(curScopeLabel ? curScopeLabel : scopeOption[0])
|
||||
return (
|
||||
<div className={css.filtersCtn}>
|
||||
{projectId ? null : (
|
||||
{projectId || isRepoLevelSearch ? null : (
|
||||
<>
|
||||
<Container>
|
||||
<Text font={{ variation: FontVariation.SMALL_SEMI }} color={Color.GREY_600} margin={{ bottom: 'xsmall' }}>
|
||||
|
|
Loading…
Reference in New Issue