@@ -31,7 +31,7 @@ import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; | |||
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; | |||
import { scrollToElement } from 'sonar-ui-common/helpers/scrolling'; | |||
import { getSuggestions } from '../../../api/components'; | |||
import { getCodeUrl, getComponentOverviewUrl } from '../../../helpers/urls'; | |||
import { getComponentOverviewUrl } from '../../../helpers/urls'; | |||
import { ComponentQualifier } from '../../../types/component'; | |||
import RecentHistory from '../RecentHistory'; | |||
import './Search.css'; | |||
@@ -163,23 +163,6 @@ export class Search extends React.PureComponent<Props, State> { | |||
return next; | |||
}, []); | |||
findFile = (key: string) => { | |||
const findInResults = (results: ComponentResult[] | undefined) => | |||
results && results.find(r => r.key === key); | |||
const file = findInResults(this.state.results['FIL']); | |||
if (file) { | |||
return file; | |||
} | |||
const test = findInResults(this.state.results['UTS']); | |||
if (test) { | |||
return test; | |||
} | |||
return undefined; | |||
}; | |||
stopLoading = () => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
@@ -285,20 +268,16 @@ export class Search extends React.PureComponent<Props, State> { | |||
if (selected.startsWith('qualifier###')) { | |||
this.searchMore(selected.substr(12)); | |||
} else { | |||
const file = this.findFile(selected); | |||
if (file) { | |||
this.props.router.push(getCodeUrl(file.project!, undefined, file.key)); | |||
} else { | |||
let qualifier = ComponentQualifier.Project; | |||
if ((results[ComponentQualifier.Portfolio] ?? []).find(r => r.key === selected)) { | |||
qualifier = ComponentQualifier.Portfolio; | |||
} else if ((results[ComponentQualifier.SubPortfolio] ?? []).find(r => r.key === selected)) { | |||
qualifier = ComponentQualifier.SubPortfolio; | |||
} | |||
let qualifier = ComponentQualifier.Project; | |||
this.props.router.push(getComponentOverviewUrl(selected, qualifier)); | |||
if ((results[ComponentQualifier.Portfolio] ?? []).find(r => r.key === selected)) { | |||
qualifier = ComponentQualifier.Portfolio; | |||
} else if ((results[ComponentQualifier.SubPortfolio] ?? []).find(r => r.key === selected)) { | |||
qualifier = ComponentQualifier.SubPortfolio; | |||
} | |||
this.props.router.push(getComponentOverviewUrl(selected, qualifier)); | |||
this.closeSearch(); | |||
} | |||
}; |
@@ -23,7 +23,8 @@ import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; | |||
import ClockIcon from 'sonar-ui-common/components/icons/ClockIcon'; | |||
import FavoriteIcon from 'sonar-ui-common/components/icons/FavoriteIcon'; | |||
import QualifierIcon from 'sonar-ui-common/components/icons/QualifierIcon'; | |||
import { getCodeUrl, getComponentOverviewUrl } from '../../../helpers/urls'; | |||
import { ComponentQualifier } from '../../../../js/types/component'; | |||
import { getComponentOverviewUrl } from '../../../helpers/urls'; | |||
import { ComponentResult } from './utils'; | |||
interface Props { | |||
@@ -82,23 +83,11 @@ export default class SearchResult extends React.PureComponent<Props, State> { | |||
this.props.onSelect(this.props.component.key); | |||
}; | |||
renderOrganization = (component: ComponentResult) => { | |||
if (!this.props.appState.organizationsEnabled) { | |||
return null; | |||
} | |||
if (!['VW', 'SVW', 'APP', 'TRK'].includes(component.qualifier) || !component.organization) { | |||
return null; | |||
} | |||
const organization = this.props.organizations[component.organization]; | |||
return organization ? ( | |||
<div className="navbar-search-item-right text-muted-2">{organization.name}</div> | |||
) : null; | |||
}; | |||
renderProject = (component: ComponentResult) => { | |||
if (!['BRC', 'FIL', 'UTS'].includes(component.qualifier) || component.project == null) { | |||
if ( | |||
ComponentQualifier.SubProject !== (component.qualifier as ComponentQualifier) || | |||
component.project == null | |||
) { | |||
return null; | |||
} | |||
@@ -111,10 +100,7 @@ export default class SearchResult extends React.PureComponent<Props, State> { | |||
render() { | |||
const { component } = this.props; | |||
const isFile = component.qualifier === 'FIL' || component.qualifier === 'UTS'; | |||
const to = isFile | |||
? getCodeUrl(component.project!, undefined, component.key) | |||
: getComponentOverviewUrl(component.key, component.qualifier); | |||
const to = getComponentOverviewUrl(component.key, component.qualifier); | |||
return ( | |||
<li | |||
@@ -144,7 +130,6 @@ export default class SearchResult extends React.PureComponent<Props, State> { | |||
<span className="navbar-search-item-match">{component.name}</span> | |||
)} | |||
{this.renderOrganization(component)} | |||
{this.renderProject(component)} | |||
</span> | |||
</Link> |
@@ -78,20 +78,6 @@ it('renders projects', () => { | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('renders organizations', () => { | |||
const component = { | |||
isRecentlyBrowsed: true, | |||
key: 'foo', | |||
name: 'foo', | |||
qualifier: 'TRK', | |||
organization: 'bar' | |||
}; | |||
const wrapper = shallowRender({ appState: { organizationsEnabled: true }, component }); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.setProps({ appState: { organizationsEnabled: false } }); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); | |||
it('shows tooltip after delay', () => { | |||
const wrapper = shallowRender(); | |||
expect(wrapper.find('Tooltip').prop('visible')).toBe(false); |
@@ -101,111 +101,6 @@ exports[`renders match 1`] = ` | |||
</li> | |||
`; | |||
exports[`renders organizations 1`] = ` | |||
<li | |||
key="foo" | |||
> | |||
<Tooltip | |||
mouseEnterDelay={1} | |||
overlay="foo" | |||
placement="left" | |||
visible={false} | |||
> | |||
<Link | |||
data-key="foo" | |||
onClick={[MockFunction]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/dashboard", | |||
"query": Object { | |||
"id": "foo", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="navbar-search-item-link" | |||
onMouseEnter={[Function]} | |||
> | |||
<span | |||
className="navbar-search-item-icons little-spacer-right" | |||
> | |||
<ClockIcon | |||
size={12} | |||
/> | |||
<QualifierIcon | |||
className="little-spacer-right" | |||
qualifier="TRK" | |||
/> | |||
</span> | |||
<span | |||
className="navbar-search-item-match" | |||
> | |||
foo | |||
</span> | |||
<div | |||
className="navbar-search-item-right text-muted-2" | |||
> | |||
bar | |||
</div> | |||
</span> | |||
</Link> | |||
</Tooltip> | |||
</li> | |||
`; | |||
exports[`renders organizations 2`] = ` | |||
<li | |||
key="foo" | |||
> | |||
<Tooltip | |||
mouseEnterDelay={1} | |||
overlay="foo" | |||
placement="left" | |||
visible={false} | |||
> | |||
<Link | |||
data-key="foo" | |||
onClick={[MockFunction]} | |||
onlyActiveOnIndex={false} | |||
style={Object {}} | |||
to={ | |||
Object { | |||
"pathname": "/dashboard", | |||
"query": Object { | |||
"id": "foo", | |||
}, | |||
} | |||
} | |||
> | |||
<span | |||
className="navbar-search-item-link" | |||
onMouseEnter={[Function]} | |||
> | |||
<span | |||
className="navbar-search-item-icons little-spacer-right" | |||
> | |||
<ClockIcon | |||
size={12} | |||
/> | |||
<QualifierIcon | |||
className="little-spacer-right" | |||
qualifier="TRK" | |||
/> | |||
</span> | |||
<span | |||
className="navbar-search-item-match" | |||
> | |||
foo | |||
</span> | |||
</span> | |||
</Link> | |||
</Tooltip> | |||
</li> | |||
`; | |||
exports[`renders projects 1`] = ` | |||
<li | |||
key="qwe" |
@@ -55,6 +55,21 @@ exports[`renders different components and dividers between them 1`] = ` | |||
<ul | |||
className="menu" | |||
> | |||
<li | |||
className="menu-header" | |||
key="header-FIL" | |||
> | |||
qualifiers.FIL | |||
</li> | |||
<span | |||
key="zux" | |||
> | |||
zux | |||
</span> | |||
<li | |||
className="divider" | |||
key="divider-TRK" | |||
/> | |||
<li | |||
className="menu-header" | |||
key="header-TRK" | |||
@@ -91,21 +106,6 @@ exports[`renders different components and dividers between them 1`] = ` | |||
> | |||
qux | |||
</span> | |||
<li | |||
className="divider" | |||
key="divider-FIL" | |||
/> | |||
<li | |||
className="menu-header" | |||
key="header-FIL" | |||
> | |||
qualifiers.FIL | |||
</li> | |||
<span | |||
key="zux" | |||
> | |||
zux | |||
</span> | |||
</ul> | |||
`; | |||
@@ -18,11 +18,19 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { sortBy } from 'lodash'; | |||
import { ComponentQualifier } from '../../../../js/types/component'; | |||
const ORDER = ['DEV', 'VW', 'SVW', 'APP', 'TRK', 'BRC', 'FIL', 'UTS']; | |||
const ORDER = [ | |||
ComponentQualifier.Developper, | |||
ComponentQualifier.Portfolio, | |||
ComponentQualifier.SubPortfolio, | |||
ComponentQualifier.Application, | |||
ComponentQualifier.Project, | |||
ComponentQualifier.SubProject | |||
]; | |||
export function sortQualifiers(qualifiers: string[]) { | |||
return sortBy(qualifiers, qualifier => ORDER.indexOf(qualifier)); | |||
return sortBy(qualifiers, qualifier => ORDER.indexOf(qualifier as ComponentQualifier)); | |||
} | |||
export interface ComponentResult { |
@@ -1159,7 +1159,7 @@ property.category.housekeeping.branchesAndPullRequests=Branches and Pull Request | |||
#------------------------------------------------------------------------------ | |||
search.shortcut_hint=Hint: Press {shortcut} from anywhere to open this search bar. | |||
search.show_more.hint=Press {key} to display | |||
search.placeholder=Search for projects and files... | |||
search.placeholder=Search for projects... | |||
search.search_for_projects=Search for projects... | |||
search.search_for_members=Search for members... | |||
search.search_for_users=Search for users... |