diff options
17 files changed, 183 insertions, 67 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/SnippetViewer.tsx b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/SnippetViewer.tsx index 4322c189d3b..4e0cbe6cb89 100644 --- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/SnippetViewer.tsx +++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/SnippetViewer.tsx @@ -136,6 +136,7 @@ export default class SnippetViewer extends React.PureComponent<Props> { (duplicationsCount && duplicationsByLine && duplicationsByLine[line.line]) || []; const isSinkLine = issuesForLine.some(i => i.key === this.props.issue.key); + const firstLineNumber = snippet && snippet.length ? snippet[0].line : 0; const noop = () => {}; return ( @@ -149,6 +150,7 @@ export default class SnippetViewer extends React.PureComponent<Props> { displaySCM={displaySCM} duplications={lineDuplications} duplicationsCount={duplicationsCount} + firstLineNumber={firstLineNumber} highlighted={false} highlightedLocationMessage={optimizeLocationMessage( this.props.highlightedLocationMessage, diff --git a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/SnippetViewer-test.tsx.snap b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/SnippetViewer-test.tsx.snap index 1279baf3394..54632e972dc 100644 --- a/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/SnippetViewer-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/SnippetViewer-test.tsx.snap @@ -36,6 +36,7 @@ exports[`should render correctly 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={5} highlighted={false} issueLocations={Array []} issues={Array []} @@ -84,6 +85,7 @@ exports[`should render correctly 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={5} highlighted={false} issueLocations={Array []} issues={Array []} @@ -145,6 +147,7 @@ exports[`should render correctly 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={5} highlighted={false} issueLocations={Array []} issues={Array []} @@ -243,6 +246,7 @@ exports[`should render correctly when at the bottom of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={10} highlighted={false} issueLocations={Array []} issues={Array []} @@ -291,6 +295,7 @@ exports[`should render correctly when at the bottom of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={10} highlighted={false} issueLocations={Array []} issues={Array []} @@ -352,6 +357,7 @@ exports[`should render correctly when at the bottom of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={10} highlighted={false} issueLocations={Array []} issues={Array []} @@ -413,6 +419,7 @@ exports[`should render correctly when at the bottom of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={10} highlighted={false} issueLocations={Array []} issues={Array []} @@ -500,6 +507,7 @@ exports[`should render correctly when at the top of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={1} highlighted={false} issueLocations={Array []} issues={Array []} @@ -548,6 +556,7 @@ exports[`should render correctly when at the top of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={1} highlighted={false} issueLocations={Array []} issues={Array []} @@ -609,6 +618,7 @@ exports[`should render correctly when at the top of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={1} highlighted={false} issueLocations={Array []} issues={Array []} @@ -670,6 +680,7 @@ exports[`should render correctly when at the top of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={1} highlighted={false} issueLocations={Array []} issues={Array []} @@ -731,6 +742,7 @@ exports[`should render correctly when at the top of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={1} highlighted={false} issueLocations={Array []} issues={Array []} @@ -792,6 +804,7 @@ exports[`should render correctly when at the top of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={1} highlighted={false} issueLocations={Array []} issues={Array []} @@ -853,6 +866,7 @@ exports[`should render correctly when at the top of the file 1`] = ` displayLocationMarkers={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={1} highlighted={false} issueLocations={Array []} issues={Array []} @@ -952,6 +966,7 @@ exports[`should render correctly with no SCM 1`] = ` displaySCM={false} duplications={Array []} duplicationsCount={0} + firstLineNumber={5} highlighted={false} issueLocations={Array []} issues={Array []} @@ -1001,6 +1016,7 @@ exports[`should render correctly with no SCM 1`] = ` displaySCM={false} duplications={Array []} duplicationsCount={0} + firstLineNumber={5} highlighted={false} issueLocations={Array []} issues={Array []} @@ -1063,6 +1079,7 @@ exports[`should render correctly with no SCM 1`] = ` displaySCM={false} duplications={Array []} duplicationsCount={0} + firstLineNumber={5} highlighted={false} issueLocations={Array []} issues={Array []} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx index 25b05fc41c6..8aa0c34a5d4 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerCode.tsx @@ -129,6 +129,7 @@ export default class SourceViewerCode extends React.PureComponent<Props> { const duplicationsCount = this.props.duplications ? this.props.duplications.length : 0; const issuesForLine = this.getIssuesForLine(line); + const firstLineNumber = sources && sources.length ? sources[0].line : 0; let scrollToUncoveredLine = false; if ( @@ -155,6 +156,7 @@ export default class SourceViewerCode extends React.PureComponent<Props> { displayLocationMarkers={this.props.displayLocationMarkers} duplications={this.getDuplicationsForLine(line)} duplicationsCount={duplicationsCount} + firstLineNumber={firstLineNumber} highlighted={line.line === this.props.highlightedLine} highlightedLocationMessage={optimizeLocationMessage( highlightedLocationMessage, diff --git a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerCode-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerCode-test.tsx.snap index cec54e6a9a6..1784b9b6fa0 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerCode-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/SourceViewer/__tests__/__snapshots__/SourceViewerCode-test.tsx.snap @@ -22,6 +22,7 @@ exports[`should render correctly: default 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -68,6 +69,7 @@ exports[`should render correctly: default 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -127,6 +129,7 @@ exports[`should render correctly: default 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -199,6 +202,7 @@ exports[`should render correctly: has file level issues 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -240,6 +244,7 @@ exports[`should render correctly: has file level issues 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -286,6 +291,7 @@ exports[`should render correctly: has file level issues 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -345,6 +351,7 @@ exports[`should render correctly: has file level issues 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -427,6 +434,7 @@ exports[`should render correctly: has more sources 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -473,6 +481,7 @@ exports[`should render correctly: has more sources 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} @@ -532,6 +541,7 @@ exports[`should render correctly: has more sources 1`] = ` displayIssues={true} duplications={Array []} duplicationsCount={0} + firstLineNumber={16} highlighted={false} issueLocations={Array []} issues={Array []} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.css b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.css index 311e044f4e6..d0e77ccd1f6 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.css +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.css @@ -241,3 +241,13 @@ .source-line-duplicated { background-color: #797979 !important; } + +.source-viewer-bubble-popup a { + font-family: var(--baseFontFamily); + font-size: var(--baseFontSize); + text-align: left; + user-select: text; + border-bottom: none; + transition: none; + color: unset; +} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx index 40ae17c22c7..d0b7f207c03 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/Line.tsx @@ -41,6 +41,7 @@ interface Props { displaySCM?: boolean; duplications: number[]; duplicationsCount: number; + firstLineNumber: number; highlighted: boolean; highlightedLocationMessage: { index: number; text: string | undefined } | undefined; highlightedSymbols: string[] | undefined; @@ -99,6 +100,7 @@ export default class Line extends React.PureComponent<Props> { displaySCM = true, duplications, duplicationsCount, + firstLineNumber, highlighted, highlightedSymbols, issueLocations, @@ -127,7 +129,7 @@ export default class Line extends React.PureComponent<Props> { return ( <tr className={className} data-line-number={line.line}> - <LineNumber line={line} /> + <LineNumber firstLineNumber={firstLineNumber} line={line} /> {displaySCM && <LineSCM line={line} previousLine={previousLine} />} {displayIssues && !displayAllIssues ? ( diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.tsx index 406a5efdde7..21df17a4fa2 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineNumber.tsx @@ -18,29 +18,37 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import Dropdown from 'sonar-ui-common/components/controls/Dropdown'; -import { PopupPlacement } from 'sonar-ui-common/components/ui/popups'; +import Toggler from 'sonar-ui-common/components/controls/Toggler'; import { translateWithParameters } from 'sonar-ui-common/helpers/l10n'; import LineOptionsPopup from './LineOptionsPopup'; export interface LineNumberProps { + firstLineNumber: number; line: T.SourceLine; } -export function LineNumber({ line }: LineNumberProps) { +export function LineNumber({ firstLineNumber, line }: LineNumberProps) { + const [isOpen, setOpen] = React.useState<boolean>(false); const { line: lineNumber } = line; const hasLineNumber = !!lineNumber; + return hasLineNumber ? ( <td className="source-meta source-line-number" data-line-number={lineNumber}> - <Dropdown - overlay={<LineOptionsPopup line={line} />} - overlayPlacement={PopupPlacement.RightTop}> + <Toggler + closeOnClickOutside={true} + onRequestClose={() => setOpen(false)} + open={isOpen} + overlay={<LineOptionsPopup firstLineNumber={firstLineNumber} line={line} />}> <span + aria-expanded={isOpen} + aria-haspopup={true} aria-label={translateWithParameters('source_viewer.line_X', lineNumber)} - role="button"> + onClick={() => setOpen(true)} + role="button" + tabIndex={0}> {lineNumber} </span> - </Dropdown> + </Toggler> </td> ) : ( <td className="source-meta source-line-number" /> diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/LineOptionsPopup.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/LineOptionsPopup.tsx index f35a3d6ad1f..24ee901a7ea 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/LineOptionsPopup.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/LineOptionsPopup.tsx @@ -18,29 +18,39 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { Link } from 'react-router'; +import { ActionsDropdownItem } from 'sonar-ui-common/components/controls/ActionsDropdown'; +import { DropdownOverlay } from 'sonar-ui-common/components/controls/Dropdown'; +import { PopupPlacement } from 'sonar-ui-common/components/ui/popups'; import { translate } from 'sonar-ui-common/helpers/l10n'; +import { getPathUrlAsString } from 'sonar-ui-common/helpers/urls'; import { getCodeUrl } from '../../../helpers/urls'; import { SourceViewerContext } from '../SourceViewerContext'; -interface LineOptionsPopupProps { +export interface LineOptionsPopupProps { + firstLineNumber: number; line: T.SourceLine; } -export function LineOptionsPopup({ line }: LineOptionsPopupProps) { +export function LineOptionsPopup({ firstLineNumber, line }: LineOptionsPopupProps) { return ( <SourceViewerContext.Consumer> - {({ branchLike, file }) => ( - <div className="source-viewer-bubble-popup nowrap"> - <Link - className="js-get-permalink" - rel="noopener noreferrer" - target="_blank" - to={getCodeUrl(file.project, branchLike, file.key, line.line)}> - {translate('component_viewer.get_permalink')} - </Link> - </div> - )} + {({ branchLike, file }) => { + const codeLocation = getCodeUrl(file.project, branchLike, file.key, line.line); + const codeUrl = getPathUrlAsString(codeLocation, false); + const isAtTop = line.line - 4 < firstLineNumber; + return ( + <DropdownOverlay + className="big-spacer-left" + noPadding={true} + placement={isAtTop ? PopupPlacement.BottomLeft : PopupPlacement.TopLeft}> + <ul className="padded source-viewer-bubble-popup nowrap"> + <ActionsDropdownItem copyValue={codeUrl}> + {translate('component_viewer.copy_permalink')} + </ActionsDropdownItem> + </ul> + </DropdownOverlay> + ); + }} </SourceViewerContext.Consumer> ); } diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/Line-test.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/Line-test.tsx index 710a78ecd1e..4ef1b49633a 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/Line-test.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/Line-test.tsx @@ -98,6 +98,7 @@ function shallowRender(props: Partial<Line['props']> = {}) { displayLocationMarkers={false} duplications={[]} duplicationsCount={0} + firstLineNumber={1} highlighted={false} highlightedLocationMessage={undefined} highlightedSymbols={undefined} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineNumber-test.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineNumber-test.tsx index 6f70d56c2d9..f536dd12bcb 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineNumber-test.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineNumber-test.tsx @@ -24,8 +24,9 @@ import { LineNumber, LineNumberProps } from '../LineNumber'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot('default'); expect(shallowRender({ line: { line: 0 } })).toMatchSnapshot('no line number'); + expect(shallowRender({ line: { line: 12 } })).toMatchSnapshot('first line'); }); function shallowRender(props: Partial<LineNumberProps> = {}) { - return shallow(<LineNumber line={{ line: 3 }} {...props} />); + return shallow(<LineNumber firstLineNumber={10} line={{ line: 20 }} {...props} />); } diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineOptionsPopup-test.tsx b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineOptionsPopup-test.tsx index b8b5c1c41b2..cedd3ed89c4 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineOptionsPopup-test.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineOptionsPopup-test.tsx @@ -20,7 +20,8 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { mockBranch } from '../../../../helpers/mocks/branch-like'; -import { LineOptionsPopup } from '../LineOptionsPopup'; +import { mockSourceLine } from '../../../../helpers/testMocks'; +import { LineOptionsPopup, LineOptionsPopupProps } from '../LineOptionsPopup'; jest.mock('../../SourceViewerContext', () => ({ SourceViewerContext: { @@ -33,7 +34,10 @@ jest.mock('../../SourceViewerContext', () => ({ })); it('should render correctly', () => { - const line = { line: 3 }; - const wrapper = shallow(<LineOptionsPopup line={line} />).dive(); - expect(wrapper).toMatchSnapshot(); + expect(shallowRender({ line: { line: 10 } }).dive()).toMatchSnapshot(); + expect(shallowRender({ line: { line: 2 } }).dive()).toMatchSnapshot('first line'); }); + +function shallowRender(props: Partial<LineOptionsPopupProps> = {}) { + return shallow(<LineOptionsPopup firstLineNumber={1} line={mockSourceLine()} {...props} />); +} diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/Line-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/Line-test.tsx.snap index 2cc3c08322d..853ff92974d 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/Line-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/Line-test.tsx.snap @@ -6,6 +6,7 @@ exports[`should render correctly 1`] = ` data-line-number={16} > <Memo(LineNumber) + firstLineNumber={1} line={ Object { "code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;", @@ -144,6 +145,7 @@ exports[`should render correctly for last, new, and highlighted lines 1`] = ` data-line-number={16} > <Memo(LineNumber) + firstLineNumber={1} line={ Object { "code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;", @@ -282,6 +284,7 @@ exports[`should render correctly with coverage 1`] = ` data-line-number={16} > <Memo(LineNumber) + firstLineNumber={1} line={ Object { "code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;", @@ -436,6 +439,7 @@ exports[`should render correctly with duplication information 1`] = ` data-line-number={16} > <Memo(LineNumber) + firstLineNumber={1} line={ Object { "code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;", @@ -635,6 +639,7 @@ exports[`should render correctly with issues info 1`] = ` data-line-number={16} > <Memo(LineNumber) + firstLineNumber={1} line={ Object { "code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;", @@ -849,6 +854,7 @@ exports[`should render correctly: no SCM 1`] = ` data-line-number={16} > <Memo(LineNumber) + firstLineNumber={1} line={ Object { "code": "<span class=\\"k\\">import</span> java.util.<span class=\\"sym-9 sym\\">ArrayList</span>;", diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineNumber-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineNumber-test.tsx.snap index 0d2a6cc0f78..ea264c2f415 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineNumber-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineNumber-test.tsx.snap @@ -3,27 +3,68 @@ exports[`should render correctly: default 1`] = ` <td className="source-meta source-line-number" - data-line-number={3} + data-line-number={20} > - <Dropdown + <Toggler + closeOnClickOutside={true} + onRequestClose={[Function]} + open={false} overlay={ <Memo(LineOptionsPopup) + firstLineNumber={10} line={ Object { - "line": 3, + "line": 20, } } /> } - overlayPlacement="right-top" > <span - aria-label="source_viewer.line_X.3" + aria-expanded={false} + aria-haspopup={true} + aria-label="source_viewer.line_X.20" + onClick={[Function]} role="button" + tabIndex={0} > - 3 + 20 </span> - </Dropdown> + </Toggler> +</td> +`; + +exports[`should render correctly: first line 1`] = ` +<td + className="source-meta source-line-number" + data-line-number={12} +> + <Toggler + closeOnClickOutside={true} + onRequestClose={[Function]} + open={false} + overlay={ + <Memo(LineOptionsPopup) + firstLineNumber={10} + line={ + Object { + "line": 12, + } + } + /> + } + > + <span + aria-expanded={false} + aria-haspopup={true} + aria-label="source_viewer.line_X.12" + onClick={[Function]} + role="button" + tabIndex={0} + > + 12 + </span> + </Toggler> </td> `; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineOptionsPopup-test.tsx.snap b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineOptionsPopup-test.tsx.snap index d0c730eba89..76fe0f1819f 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineOptionsPopup-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/__snapshots__/LineOptionsPopup-test.tsx.snap @@ -1,28 +1,37 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`should render correctly 1`] = ` -<div - className="source-viewer-bubble-popup nowrap" +<DropdownOverlay + className="big-spacer-left" + noPadding={true} + placement="top-left" > - <Link - className="js-get-permalink" - onlyActiveOnIndex={false} - rel="noopener noreferrer" - style={Object {}} - target="_blank" - to={ - Object { - "pathname": "/code", - "query": Object { - "branch": "feature", - "id": "prj", - "line": 3, - "selected": "foo", - }, - } - } + <ul + className="padded source-viewer-bubble-popup nowrap" > - component_viewer.get_permalink - </Link> -</div> + <ActionsDropdownItem + copyValue="http://localhost/code?id=prj&branch=feature&selected=foo&line=10" + > + component_viewer.copy_permalink + </ActionsDropdownItem> + </ul> +</DropdownOverlay> +`; + +exports[`should render correctly: first line 1`] = ` +<DropdownOverlay + className="big-spacer-left" + noPadding={true} + placement="bottom-left" +> + <ul + className="padded source-viewer-bubble-popup nowrap" + > + <ActionsDropdownItem + copyValue="http://localhost/code?id=prj&branch=feature&selected=foo&line=2" + > + component_viewer.copy_permalink + </ActionsDropdownItem> + </ul> +</DropdownOverlay> `; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/styles.css b/server/sonar-web/src/main/js/components/SourceViewer/styles.css index 63393b55f51..ed716732a98 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/styles.css +++ b/server/sonar-web/src/main/js/components/SourceViewer/styles.css @@ -115,13 +115,6 @@ border-top: 1px solid var(--barBorderColor); } -.source-viewer-bubble-popup { - font-family: var(--baseFontFamily); - font-size: var(--baseFontSize); - text-align: left; - user-select: text; -} - .issue-location.highlighted { border-color: var(--issueLocationHighlighted); background-color: var(--issueLocationHighlighted); diff --git a/server/sonar-web/src/main/js/helpers/urls.ts b/server/sonar-web/src/main/js/helpers/urls.ts index 629480e472b..3d255640269 100644 --- a/server/sonar-web/src/main/js/helpers/urls.ts +++ b/server/sonar-web/src/main/js/helpers/urls.ts @@ -249,10 +249,10 @@ export function getCodeUrl( branchLike?: BranchLike, selected?: string, line?: number -) { +): Location { return { pathname: '/code', - query: { id: project, ...getBranchLikeQuery(branchLike), selected, line } + query: { id: project, ...getBranchLikeQuery(branchLike), selected, line: line?.toFixed() } }; } diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 8e4490ebcbb..d548061fca2 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2635,7 +2635,7 @@ component_viewer.show_raw_source=Show Raw Source component_viewer.more_actions=More Actions component_viewer.new_window=Open in New Window component_viewer.open_in_workspace=Pin This File -component_viewer.get_permalink=Get Permalink +component_viewer.copy_permalink=Copy Permalink component_viewer.covered_lines=Covered Lines component_viewer.show_details=Show Measures component_viewer.file_measures=File measures |