@@ -19,29 +19,35 @@ | |||
*/ | |||
import * as React from 'react'; | |||
import { Button } from '../../../components/controls/buttons'; | |||
import Tooltip from '../../../components/controls/Tooltip'; | |||
import { translate } from '../../../helpers/l10n'; | |||
export interface PortfolioNewCodeToggleProps { | |||
enabled: boolean; | |||
showNewCode: boolean; | |||
onNewCodeToggle: (newSelected: boolean) => void; | |||
} | |||
export default function PortfolioNewCodeToggle(props: PortfolioNewCodeToggleProps) { | |||
const { showNewCode } = props; | |||
const { showNewCode, enabled } = props; | |||
return ( | |||
<div className="big-spacer-right"> | |||
<div className="button-group"> | |||
<Tooltip | |||
overlay={translate('code_viewer.portfolio_code_toggle_disabled.help')} | |||
visible={enabled ? false : undefined}> | |||
<div className="big-spacer-right button-group"> | |||
<Button | |||
disabled={!enabled} | |||
className={showNewCode ? 'button-active' : undefined} | |||
onClick={() => props.onNewCodeToggle(true)}> | |||
{translate('projects.view.new_code')} | |||
</Button> | |||
<Button | |||
disabled={!enabled} | |||
className={showNewCode ? undefined : 'button-active'} | |||
onClick={() => props.onNewCodeToggle(false)}> | |||
{translate('projects.view.overall_code')} | |||
</Button> | |||
</div> | |||
</div> | |||
</Tooltip> | |||
); | |||
} |
@@ -17,7 +17,7 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { omit } from 'lodash'; | |||
import { isEmpty, omit } from 'lodash'; | |||
import * as React from 'react'; | |||
import { getTree } from '../../../api/components'; | |||
import SearchBox from '../../../components/controls/SearchBox'; | |||
@@ -133,13 +133,14 @@ export class Search extends React.PureComponent<Props, State> { | |||
render() { | |||
const { component, newCodeSelected } = this.props; | |||
const { loading } = this.state; | |||
const { loading, query } = this.state; | |||
const isPortfolio = ['VW', 'SVW', 'APP'].includes(component.qualifier); | |||
return ( | |||
<div className="code-search" id="code-search"> | |||
{isPortfolio && ( | |||
<PortfolioNewCodeToggle | |||
enabled={isEmpty(query)} | |||
onNewCodeToggle={this.props.onNewCodeToggle} | |||
showNewCode={newCodeSelected} | |||
/> |
@@ -20,12 +20,20 @@ | |||
import { shallow } from 'enzyme'; | |||
import * as React from 'react'; | |||
import { Button } from '../../../../components/controls/buttons'; | |||
import Tooltip from '../../../../components/controls/Tooltip'; | |||
import PortfolioNewCodeToggle, { PortfolioNewCodeToggleProps } from '../PortfolioNewCodeToggle'; | |||
it('renders correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
}); | |||
it('should show tooltips when disabled', () => { | |||
const wrapper = shallowRender({ enabled: false }); | |||
expect(wrapper.find(Tooltip).props().visible).toBeUndefined(); | |||
wrapper.setProps({ enabled: true }); | |||
expect(wrapper.find(Tooltip).props().visible).toBe(false); | |||
}); | |||
it('should toggle correctly', () => { | |||
const onNewCodeToggle = jest.fn(); | |||
const wrapper = shallowRender({ onNewCodeToggle }); | |||
@@ -46,6 +54,11 @@ it('should toggle correctly', () => { | |||
function shallowRender(props?: Partial<PortfolioNewCodeToggleProps>) { | |||
return shallow( | |||
<PortfolioNewCodeToggle showNewCode={true} onNewCodeToggle={jest.fn()} {...props} /> | |||
<PortfolioNewCodeToggle | |||
showNewCode={true} | |||
enabled={true} | |||
onNewCodeToggle={jest.fn()} | |||
{...props} | |||
/> | |||
); | |||
} |
@@ -44,7 +44,13 @@ it('should render correcly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
expect( | |||
shallowRender({ component: mockComponent({ qualifier: ComponentQualifier.Portfolio }) }) | |||
).toMatchSnapshot('node code toggle for portfolio'); | |||
).toMatchSnapshot('new code toggle for portfolio'); | |||
expect( | |||
shallowRender({ | |||
component: mockComponent({ qualifier: ComponentQualifier.Portfolio }), | |||
location: mockLocation({ query: { id: 'foo', search: 'bar' } }) | |||
}) | |||
).toMatchSnapshot('new code toggle for portfolio disabled'); | |||
}); | |||
it('should search correct query on mount', async () => { |
@@ -1,23 +1,26 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div | |||
className="big-spacer-right" | |||
<Tooltip | |||
overlay="code_viewer.portfolio_code_toggle_disabled.help" | |||
visible={false} | |||
> | |||
<div | |||
className="button-group" | |||
className="big-spacer-right button-group" | |||
> | |||
<Button | |||
className="button-active" | |||
disabled={false} | |||
onClick={[Function]} | |||
> | |||
projects.view.new_code | |||
</Button> | |||
<Button | |||
disabled={false} | |||
onClick={[Function]} | |||
> | |||
projects.view.overall_code | |||
</Button> | |||
</div> | |||
</div> | |||
</Tooltip> | |||
`; |
@@ -19,12 +19,13 @@ exports[`should render correcly 1`] = ` | |||
</div> | |||
`; | |||
exports[`should render correcly: node code toggle for portfolio 1`] = ` | |||
exports[`should render correcly: new code toggle for portfolio 1`] = ` | |||
<div | |||
className="code-search" | |||
id="code-search" | |||
> | |||
<PortfolioNewCodeToggle | |||
enabled={true} | |||
onNewCodeToggle={[MockFunction]} | |||
showNewCode={false} | |||
/> | |||
@@ -41,3 +42,27 @@ exports[`should render correcly: node code toggle for portfolio 1`] = ` | |||
/> | |||
</div> | |||
`; | |||
exports[`should render correcly: new code toggle for portfolio disabled 1`] = ` | |||
<div | |||
className="code-search" | |||
id="code-search" | |||
> | |||
<PortfolioNewCodeToggle | |||
enabled={false} | |||
onNewCodeToggle={[MockFunction]} | |||
showNewCode={false} | |||
/> | |||
<SearchBox | |||
minLength={3} | |||
onChange={[Function]} | |||
onKeyDown={[Function]} | |||
placeholder="code.search_placeholder.portfolio" | |||
value="bar" | |||
/> | |||
<DeferredSpinner | |||
className="spacer-left" | |||
loading={true} | |||
/> | |||
</div> | |||
`; |
@@ -1418,7 +1418,7 @@ code_viewer.no_source_code_displayed_due_to_empty_analysis.VW=No projects, appli | |||
code_viewer.no_source_code_displayed_due_to_empty_analysis.SVW=No projects, applications, or portfolios in this portfolio. | |||
code_viewer.no_source_code_displayed_due_to_security=Due to security settings, no source code can be displayed. | |||
code_viewer.no_source_code_displayed_due_to_source_removed=The file was removed, no source code can be displayed. | |||
code_viewer.portfolio_code_toggle_disabled.help=New Code and Overall Code measures are not available when searching for projects or applications. | |||
#------------------------------------------------------------------------------ | |||
# |