import ComponentName from './ComponentName';
import ComponentMeasure from './ComponentMeasure';
import ComponentDetach from './ComponentDetach';
+import ComponentPin from './ComponentPin';
-const Component = ({ component, previous, coverageMetric, onBrowse }) => (
- <tr>
- <td className="thin nowrap">
- <span className="spacer-right">
- <ComponentDetach component={component}/>
- </span>
- </td>
- <td className="code-name-cell">
- <ComponentName
- component={component}
- previous={previous}
- onBrowse={onBrowse}/>
- </td>
- <td className="thin nowrap text-right">
- <div className="code-components-cell">
- <ComponentMeasure
- component={component}
- metricKey="ncloc"
- metricType="SHORT_INT"/>
- </div>
- </td>
- <td className="thin nowrap text-right">
- <div className="code-components-cell">
- <ComponentMeasure
- component={component}
- metricKey="sqale_index"
- metricType="SHORT_WORK_DUR"/>
- </div>
- </td>
- <td className="thin nowrap text-right">
- <div className="code-components-cell">
- <ComponentMeasure
- component={component}
- metricKey="violations"
- metricType="SHORT_INT"/>
- </div>
- </td>
- <td className="thin nowrap text-right">
- <div className="code-components-cell">
- <ComponentMeasure
- component={component}
- metricKey={coverageMetric}
- metricType="PERCENT"/>
- </div>
- </td>
- <td className="thin nowrap text-right">
- <div className="code-components-cell">
- <ComponentMeasure
+const Component = ({ component, previous, coverageMetric, onBrowse }) => {
+ let componentAction = null;
+
+ switch (component.qualifier) {
+ case 'FIL':
+ case 'UTS':
+ componentAction = <ComponentPin component={component}/>;
+ break;
+ default:
+ componentAction = <ComponentDetach component={component}/>;
+ }
+
+ return (
+ <tr>
+ <td className="thin nowrap">
+ <span className="spacer-right">
+ {componentAction}
+ </span>
+ </td>
+ <td className="code-name-cell">
+ <ComponentName
component={component}
- metricKey="duplicated_lines_density"
- metricType="PERCENT"/>
- </div>
- </td>
- </tr>
-);
+ previous={previous}
+ onBrowse={onBrowse}/>
+ </td>
+ <td className="thin nowrap text-right">
+ <div className="code-components-cell">
+ <ComponentMeasure
+ component={component}
+ metricKey="ncloc"
+ metricType="SHORT_INT"/>
+ </div>
+ </td>
+ <td className="thin nowrap text-right">
+ <div className="code-components-cell">
+ <ComponentMeasure
+ component={component}
+ metricKey="sqale_index"
+ metricType="SHORT_WORK_DUR"/>
+ </div>
+ </td>
+ <td className="thin nowrap text-right">
+ <div className="code-components-cell">
+ <ComponentMeasure
+ component={component}
+ metricKey="violations"
+ metricType="SHORT_INT"/>
+ </div>
+ </td>
+ <td className="thin nowrap text-right">
+ <div className="code-components-cell">
+ <ComponentMeasure
+ component={component}
+ metricKey={coverageMetric}
+ metricType="PERCENT"/>
+ </div>
+ </td>
+ <td className="thin nowrap text-right">
+ <div className="code-components-cell">
+ <ComponentMeasure
+ component={component}
+ metricKey="duplicated_lines_density"
+ metricType="PERCENT"/>
+ </div>
+ </td>
+ </tr>
+ );
+};
export default Component;
const ComponentDetach = ({ component }) => (
<a
className="icon-detach"
- target="_blank"
- title={translate('code.open_in_new_tab')}
+ title={translate('code.open_component_page')}
href={getComponentUrl(component.key)}/>
);
--- /dev/null
+/*
+ * SonarQube :: Web
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import React from 'react';
+
+import Workspace from '../../../components/workspace/main';
+import PinIcon from '../../../components/shared/pin-icon';
+import { translate } from '../../../helpers/l10n';
+
+
+const ComponentPin = ({ component }) => {
+ const handleClick = (e) => {
+ e.preventDefault();
+ Workspace.openComponent({ uuid: component.uuid });
+ };
+
+ return (
+ <a
+ className="link-no-underline"
+ onClick={handleClick}
+ title={translate('component_viewer.open_in_workspace')}
+ href="#">
+ <PinIcon/>
+ </a>
+ );
+};
+
+
+export default ComponentPin;
--- /dev/null
+/*
+ * SonarQube :: Web
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import React from 'react';
+
+const PinIcon = () => (
+ <svg width="9" height="14" viewBox="0 0 288 448">
+ <path
+ fill="#236a97"
+ d="M120 216v-112q0-3.5-2.25-5.75t-5.75-2.25-5.75 2.25-2.25 5.75v112q0 3.5 2.25 5.75t5.75 2.25 5.75-2.25 2.25-5.75zM288 304q0 6.5-4.75 11.25t-11.25 4.75h-107.25l-12.75 120.75q-0.5 3-2.625 5.125t-5.125 2.125h-0.25q-6.75 0-8-6.75l-19-121.25h-101q-6.5 0-11.25-4.75t-4.75-11.25q0-30.75 19.625-55.375t44.375-24.625v-128q-13 0-22.5-9.5t-9.5-22.5 9.5-22.5 22.5-9.5h160q13 0 22.5 9.5t9.5 22.5-9.5 22.5-22.5 9.5v128q24.75 0 44.375 24.625t19.625 55.375z"/>
+ </svg>
+);
+
+export default PinIcon;
+
import Breadcrumb from '../../../src/main/js/apps/code/components/Breadcrumb';
import Breadcrumbs from '../../../src/main/js/apps/code/components/Breadcrumbs';
-import Component from '../../../src/main/js/apps/code/components/Component';
import ComponentDetach from '../../../src/main/js/apps/code/components/ComponentDetach';
import ComponentMeasure from '../../../src/main/js/apps/code/components/ComponentMeasure';
import ComponentName from '../../../src/main/js/apps/code/components/ComponentName';
-import Components from '../../../src/main/js/apps/code/components/Components';
import ComponentsEmpty from '../../../src/main/js/apps/code/components/ComponentsEmpty';
import Truncated from '../../../src/main/js/apps/code/components/Truncated';
});
});
- describe('<Component/>', () => {
- let output;
-
- before(() => {
- output = shallow(
- <Component
- component={exampleComponent}
- coverageMetric="coverage"
- onBrowse={exampleOnBrowse}/>);
- });
-
- it('should render <ComponentName/>', () => {
- const findings = output.find(ComponentName);
- expect(findings)
- .to.have.length(1);
- expect(findings.first().props())
- .to.deep.equal({ component: exampleComponent, previous: undefined, onBrowse: exampleOnBrowse });
- });
-
- it('should render <ComponentMeasure/>s', () => {
- const findings = output.find(ComponentMeasure);
- expect(findings)
- .to.have.length(5);
- expect(findings.at(0).props())
- .to.deep.equal({ component: exampleComponent, metricKey: 'ncloc', metricType: 'SHORT_INT' });
- expect(findings.at(1).props())
- .to.deep.equal({ component: exampleComponent, metricKey: 'sqale_index', metricType: 'SHORT_WORK_DUR' });
- expect(findings.at(2).props())
- .to.deep.equal({ component: exampleComponent, metricKey: 'violations', metricType: 'SHORT_INT' });
- expect(findings.at(3).props())
- .to.deep.equal({ component: exampleComponent, metricKey: 'coverage', metricType: 'PERCENT' });
- expect(findings.at(4).props())
- .to.deep.equal({ component: exampleComponent, metricKey: 'duplicated_lines_density', metricType: 'PERCENT' });
- });
-
- it('should render <ComponentDetach/>', () => {
- const findings = output.find(ComponentDetach);
- expect(findings)
- .to.have.length(1);
- expect(findings.first().props())
- .to.deep.equal({ component: exampleComponent });
- });
- });
-
describe('<ComponentDetach/>', () => {
it('should render link', () => {
const output = shallow(
expect(output.type())
.to.equal('a');
- expect(output.prop('target'))
- .to.equal('_blank');
expect(output.prop('href'))
.to.equal(expectedUrl);
});
});
});
- describe('<Components/>', () => {
- let output;
-
- before(() => {
- output = shallow(
- <Components
- baseComponent={exampleComponent}
- components={[exampleComponent2, exampleComponent3]}
- onBrowse={exampleOnBrowse}/>);
- });
-
- it('should render base component', () => {
- const findings = output.findWhere(node => {
- return node.type() === Component && node.prop('component') === exampleComponent;
- });
-
- expect(findings)
- .to.have.length(1);
- expect(findings.first().prop('onBrowse'))
- .to.not.be.ok;
- });
-
- it('should render children component', () => {
- const findings = output.findWhere(node => {
- return node.type() === Component && node.prop('component') !== exampleComponent;
- });
-
- expect(findings)
- .to.have.length(2);
- expect(findings.at(0).prop('onBrowse'))
- .to.equal(exampleOnBrowse)
- });
- });
-
describe('<ComponentsEmpty/>', () => {
it('should render', () => {
const output = shallow(<ComponentsEmpty/>);
# CODE
#
#------------------------------------------------------------------------------
-code.open_in_new_tab=Open in New Tab
+code.open_component_page=Open Component's Page