Pārlūkot izejas kodu

SONAR-16316 New place for regulatory report

tags/9.5.0.56709
Revanshu Paliwal pirms 2 gadiem
vecāks
revīzija
c1a02f4549
13 mainītis faili ar 543 papildinājumiem un 97 dzēšanām
  1. 45
    0
      server/sonar-web/src/main/js/api/mocks/BranchesServiceMock.ts
  2. 1
    15
      server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx
  3. 1
    0
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformation.tsx
  4. 34
    2
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformationRenderer.tsx
  5. 14
    0
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformationRenderer-test.tsx
  6. 4
    4
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap
  7. 221
    0
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformationRenderer-test.tsx.snap
  8. 153
    0
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/projectRegulatoryReport/RegulatoryReport.tsx
  9. 45
    0
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/projectRegulatoryReport/RegulatoryReportModal.tsx
  10. 19
    2
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/projectRegulatoryReport/__tests__/RegulatoryReport-it.tsx
  11. 0
    6
      server/sonar-web/src/main/js/app/utils/startReactApp.tsx
  12. 0
    66
      server/sonar-web/src/main/js/apps/projectRegulatoryReport/RegulatoryReport.tsx
  13. 6
    2
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

+ 45
- 0
server/sonar-web/src/main/js/api/mocks/BranchesServiceMock.ts Parādīt failu

@@ -0,0 +1,45 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info 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 { cloneDeep } from 'lodash';
import { mockBranch } from '../../helpers/mocks/branch-like';
import { BranchLike } from '../../types/branch-like';
import { getBranches } from '../branches';

export default class BranchesServiceMock {
branchLikes: BranchLike[];
defaultBranchLikes: BranchLike[] = [
mockBranch({ isMain: true, name: 'master' }),
mockBranch({ excludedFromPurge: false, name: 'delete-branch' }),
mockBranch({ name: 'normal-branch' })
];

constructor() {
this.branchLikes = cloneDeep(this.defaultBranchLikes);
(getBranches as jest.Mock).mockImplementation(this.getBranchesHandler);
}

getBranchesHandler = () => {
return Promise.resolve(this.branchLikes);
};

resetBranches = () => {
this.branchLikes = cloneDeep(this.defaultBranchLikes);
};
}

+ 1
- 15
server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx Parādīt failu

@@ -329,8 +329,7 @@ export class Menu extends React.PureComponent<Props> {
this.renderBackgroundTasksLink(query),
this.renderUpdateKeyLink(query),
this.renderWebhooksLink(query, isProject),
this.renderDeletionLink(query),
this.renderRegulatoryReport(query)
this.renderDeletionLink(query)
];
};

@@ -542,19 +541,6 @@ export class Menu extends React.PureComponent<Props> {
);
};

renderRegulatoryReport = (query: Query) => {
if (!this.props.appState.regulatoryReportFeatureEnabled) {
return null;
}
return (
<li key="project_regulatory_report">
<Link activeClassName="active" to={{ pathname: '/project/regulatory-report', query }}>
{translate('regulatory_report.page')}
</Link>
</li>
);
};

renderExtension = ({ key, name }: Extension, isAdmin: boolean, baseQuery: Query) => {
const pathname = isAdmin ? `/project/admin/extension/${key}` : `/project/extension/${key}`;
const query = { ...baseQuery, qualifier: this.props.component.qualifier };

+ 1
- 0
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformation.tsx Parādīt failu

@@ -97,6 +97,7 @@ export class ProjectInformation extends React.PureComponent<Props, State> {
canConfigureNotifications={canConfigureNotifications}
canUseBadges={canUseBadges}
component={component}
branchLike={branchLike}
measures={measures}
onComponentChange={this.props.onComponentChange}
onPageChange={this.setPage}

+ 34
- 2
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/ProjectInformationRenderer.tsx Parādīt failu

@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { ButtonLink } from '../../../../../components/controls/buttons';
import ModalButton from '../../../../../components/controls/ModalButton';
import PrivacyBadgeContainer from '../../../../../components/common/PrivacyBadgeContainer';
import { translate } from '../../../../../helpers/l10n';
import { ComponentQualifier } from '../../../../../types/component';
@@ -30,18 +32,31 @@ import MetaQualityProfiles from './meta/MetaQualityProfiles';
import MetaSize from './meta/MetaSize';
import MetaTags from './meta/MetaTags';
import { ProjectInformationPages } from './ProjectInformationPages';
import RegulatoryReportModal from './projectRegulatoryReport/RegulatoryReportModal';
import withAppStateContext from '../../../app-state/withAppStateContext';
import { AppState } from '../../../../../types/appstate';
import { BranchLike } from '../../../../../types/branch-like';

export interface ProjectInformationRendererProps {
appState: AppState;
canConfigureNotifications: boolean;
canUseBadges: boolean;
component: Component;
branchLike?: BranchLike;
measures?: Measure[];
onComponentChange: (changes: {}) => void;
onPageChange: (page: ProjectInformationPages) => void;
}

export function ProjectInformationRenderer(props: ProjectInformationRendererProps) {
const { canConfigureNotifications, canUseBadges, component, measures = [] } = props;
const {
canConfigureNotifications,
canUseBadges,
component,
measures = [],
appState,
branchLike
} = props;

const isApp = component.qualifier === ComponentQualifier.Application;

@@ -113,9 +128,26 @@ export function ProjectInformationRenderer(props: ProjectInformationRendererProp
to={ProjectInformationPages.notifications}
/>
)}
{component.qualifier === ComponentQualifier.Project &&
appState.regulatoryReportFeatureEnabled && (
<div className="big-padded bordered-bottom">
<ModalButton
modal={({ onClose }) => (
<RegulatoryReportModal
component={component}
branchLike={branchLike}
onClose={onClose}
/>
)}>
{({ onClick }) => (
<ButtonLink onClick={onClick}>{translate('regulatory_report.page')}</ButtonLink>
)}
</ModalButton>
</div>
)}
</div>
</>
);
}

export default React.memo(ProjectInformationRenderer);
export default withAppStateContext(React.memo(ProjectInformationRenderer));

+ 14
- 0
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/ProjectInformationRenderer-test.tsx Parādīt failu

@@ -19,6 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockAppState } from '../../../../../../helpers/testMocks';
import { mockComponent } from '../../../../../../helpers/mocks/component';
import {
ProjectInformationRenderer,
@@ -56,9 +57,22 @@ it('should handle missing quality profiles and quality gates', () => {
).toMatchSnapshot();
});

it('should render app correctly when regulatoryReportFeatureEnabled is false', () => {
expect(
shallowRender({
appState: mockAppState({
regulatoryReportFeatureEnabled: false
})
})
).toMatchSnapshot();
});

function shallowRender(props: Partial<ProjectInformationRendererProps> = {}) {
return shallow(
<ProjectInformationRenderer
appState={mockAppState({
regulatoryReportFeatureEnabled: true
})}
canConfigureNotifications={true}
canUseBadges={true}
component={mockComponent({ qualifier: 'TRK', visibility: 'public' })}

+ 4
- 4
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformation-test.tsx.snap Parādīt failu

@@ -2,7 +2,7 @@

exports[`should render correctly: default 1`] = `
<Fragment>
<Memo(ProjectInformationRenderer)
<withAppStateContext(Component)
canConfigureNotifications={false}
canUseBadges={true}
component={
@@ -64,7 +64,7 @@ exports[`should render correctly: default 1`] = `

exports[`should render correctly: logged in user 1`] = `
<Fragment>
<Memo(ProjectInformationRenderer)
<withAppStateContext(Component)
canConfigureNotifications={true}
canUseBadges={true}
component={
@@ -155,7 +155,7 @@ exports[`should render correctly: logged in user 1`] = `

exports[`should render correctly: measures loaded 1`] = `
<Fragment>
<Memo(ProjectInformationRenderer)
<withAppStateContext(Component)
canConfigureNotifications={false}
canUseBadges={true}
component={
@@ -231,7 +231,7 @@ exports[`should render correctly: measures loaded 1`] = `

exports[`should render correctly: private 1`] = `
<Fragment>
<Memo(ProjectInformationRenderer)
<withAppStateContext(Component)
canConfigureNotifications={false}
canUseBadges={true}
component={

+ 221
- 0
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/__tests__/__snapshots__/ProjectInformationRenderer-test.tsx.snap Parādīt failu

@@ -88,6 +88,15 @@ exports[`should handle missing quality profiles and quality gates 1`] = `
onPageChange={[MockFunction]}
to={2}
/>
<div
className="big-padded bordered-bottom"
>
<ModalButton
modal={[Function]}
>
<Component />
</ModalButton>
</div>
</div>
</Fragment>
`;
@@ -246,6 +255,15 @@ exports[`should render a private project correctly 1`] = `
onPageChange={[MockFunction]}
to={2}
/>
<div
className="big-padded bordered-bottom"
>
<ModalButton
modal={[Function]}
>
<Component />
</ModalButton>
</div>
</div>
</Fragment>
`;
@@ -351,6 +369,164 @@ exports[`should render an app correctly: default 1`] = `
</Fragment>
`;

exports[`should render app correctly when regulatoryReportFeatureEnabled is false 1`] = `
<Fragment>
<div>
<h2
className="big-padded bordered-bottom"
>
project.info.title
</h2>
</div>
<div
className="overflow-y-auto"
>
<div
className="big-padded bordered-bottom"
>
<div
className="display-flex-center"
>
<h3
className="spacer-right"
>
project.info.description
</h3>
<PrivacyBadgeContainer
qualifier="TRK"
visibility="public"
/>
</div>
<MetaTags
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
"visibility": "public",
}
}
onComponentChange={[MockFunction]}
/>
</div>
<div
className="big-padded bordered-bottom it__project-loc-value"
>
<MetaSize
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
"visibility": "public",
}
}
measures={Array []}
/>
</div>
<div
className="big-padded bordered-bottom"
>
<MetaQualityGate
qualityGate={
Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
}
}
/>
<withLanguagesContext(MetaQualityProfiles)
headerClassName="big-spacer-top"
profiles={
Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
]
}
/>
</div>
<MetaLinks
component={
Object {
"breadcrumbs": Array [],
"key": "my-project",
"name": "MyProject",
"qualifier": "TRK",
"qualityGate": Object {
"isDefault": true,
"key": "30",
"name": "Sonar way",
},
"qualityProfiles": Array [
Object {
"deleted": false,
"key": "my-qp",
"language": "ts",
"name": "Sonar way",
},
],
"tags": Array [],
"visibility": "public",
}
}
/>
<div
className="big-padded bordered-bottom"
>
<MetaKey
componentKey="my-project"
qualifier="TRK"
/>
</div>
<Memo(DrawerLink)
label="overview.badges.get_badge.TRK"
onPageChange={[MockFunction]}
to={1}
/>
<Memo(DrawerLink)
label="project.info.to_notifications"
onPageChange={[MockFunction]}
to={2}
/>
</div>
</Fragment>
`;

exports[`should render correctly: default 1`] = `
<Fragment>
<div>
@@ -505,6 +681,15 @@ exports[`should render correctly: default 1`] = `
onPageChange={[MockFunction]}
to={2}
/>
<div
className="big-padded bordered-bottom"
>
<ModalButton
modal={[Function]}
>
<Component />
</ModalButton>
</div>
</div>
</Fragment>
`;
@@ -658,6 +843,15 @@ exports[`should render correctly: no badges 1`] = `
onPageChange={[MockFunction]}
to={2}
/>
<div
className="big-padded bordered-bottom"
>
<ModalButton
modal={[Function]}
>
<Component />
</ModalButton>
</div>
</div>
</Fragment>
`;
@@ -806,6 +1000,15 @@ exports[`should render correctly: no badges, no notifications 1`] = `
qualifier="TRK"
/>
</div>
<div
className="big-padded bordered-bottom"
>
<ModalButton
modal={[Function]}
>
<Component />
</ModalButton>
</div>
</div>
</Fragment>
`;
@@ -959,6 +1162,15 @@ exports[`should render correctly: with notifications 1`] = `
onPageChange={[MockFunction]}
to={1}
/>
<div
className="big-padded bordered-bottom"
>
<ModalButton
modal={[Function]}
>
<Component />
</ModalButton>
</div>
</div>
</Fragment>
`;
@@ -1118,6 +1330,15 @@ exports[`should render with description 1`] = `
onPageChange={[MockFunction]}
to={2}
/>
<div
className="big-padded bordered-bottom"
>
<ModalButton
modal={[Function]}
>
<Component />
</ModalButton>
</div>
</div>
</Fragment>
`;

+ 153
- 0
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/projectRegulatoryReport/RegulatoryReport.tsx Parādīt failu

@@ -0,0 +1,153 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info 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 classNames from 'classnames';
import * as React from 'react';
import { BranchLike } from '../../../../../../types/branch-like';
import { getBranches } from '../../../../../../api/branches';
import { getRegulatoryReportUrl } from '../../../../../../api/regulatory-report';
import { ButtonLink } from '../../../../../../components/controls/buttons';
import Select, { BasicSelectOption } from '../../../../../../components/controls/Select';
import {
getBranchLikeDisplayName,
isBranch,
isMainBranch
} from '../../../../../../helpers/branch-like';
import { translate } from '../../../../../../helpers/l10n';
import { Component } from '../../../../../../types/types';
import { orderBy } from 'lodash';

interface Props {
component: Pick<Component, 'key' | 'name'>;
branchLike?: BranchLike;
onClose: () => void;
}

interface State {
downloadStarted: boolean;
selectedBranch: string;
branchLikesOptions: BasicSelectOption[];
}

export default class RegulatoryReport extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
downloadStarted: false,
selectedBranch: '',
branchLikesOptions: []
};
}

componentDidMount() {
const { component, branchLike } = this.props;
getBranches(component.key)
.then(data => {
const mainBranch = data.find(isMainBranch);
const otherBranchSorted = orderBy(
data.filter(isBranch).filter(b => !isMainBranch(b)),
b => b.name
);
const sortedBranch = mainBranch ? [mainBranch, ...otherBranchSorted] : otherBranchSorted;
const options = sortedBranch
.filter(br => br.excludedFromPurge)
.map(br => {
return {
value: getBranchLikeDisplayName(br),
label: getBranchLikeDisplayName(br)
};
});

let selectedBranch = '';
if (branchLike && isBranch(branchLike) && branchLike.excludedFromPurge) {
selectedBranch = getBranchLikeDisplayName(branchLike);
} else if (mainBranch) {
selectedBranch = getBranchLikeDisplayName(mainBranch);
}
this.setState({ selectedBranch, branchLikesOptions: options });
})
.catch(() => {
this.setState({ branchLikesOptions: [] });
});
}

onBranchSelect = (newOption: BasicSelectOption) => {
this.setState({ selectedBranch: newOption.value, downloadStarted: false });
};

render() {
const { component, onClose } = this.props;
const { downloadStarted, selectedBranch, branchLikesOptions } = this.state;

return (
<>
<div className="modal-head">
<h2>{translate('regulatory_report.page')}</h2>
</div>
<div className="modal-body">
<p>{translate('regulatory_report.description1')}</p>
<div className="markdown">
<ul>
<li>{translate('regulatory_report.bullet_point1')}</li>
<li>{translate('regulatory_report.bullet_point2')}</li>
<li>{translate('regulatory_report.bullet_point3')}</li>
</ul>
</div>
<p>{translate('regulatory_report.description2')}</p>
<div className="modal-field big-spacer-top">
<label htmlFor="regulatory-report-branch-select">
{translate('regulatory_page.select_branch')}
</label>
<Select
className="width-100"
inputId="regulatory-report-branch-select"
id="regulatory-report-branch-select-input"
onChange={this.onBranchSelect}
options={branchLikesOptions}
value={branchLikesOptions.find(o => o.value === selectedBranch)}
/>
</div>
<div className="modal-field big-spacer-top">
{downloadStarted && (
<div>
<p>{translate('regulatory_page.download_start.sentence')}</p>
</div>
)}
</div>
</div>
<div className="modal-foot">
<a
className={classNames('button button-primary big-spacer-right', {
disabled: downloadStarted
})}
download={[component.name, selectedBranch, 'PDF Report.zip']
.filter(s => !!s)
.join(' - ')}
onClick={() => this.setState({ downloadStarted: true })}
href={getRegulatoryReportUrl(component.key, selectedBranch)}
target="_blank"
rel="noopener noreferrer">
{translate('download_verb')}
</a>
<ButtonLink onClick={onClose}>{translate('cancel')}</ButtonLink>
</div>
</>
);
}
}

+ 45
- 0
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/projectRegulatoryReport/RegulatoryReportModal.tsx Parādīt failu

@@ -0,0 +1,45 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info 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 * as React from 'react';
import { translate } from '../../../../../../helpers/l10n';
import { Component } from '../../../../../../types/types';
import Modal from '../../../../../../components/controls/Modal';
import RegulatoryReport from './RegulatoryReport';
import ClickEventBoundary from '../../../../../../components/controls/ClickEventBoundary';
import { BranchLike } from '../../../../../../types/branch-like';

interface Props {
component: Component;
branchLike?: BranchLike;
onClose: () => void;
}

export default function RegulatoryReportModal(props: Props) {
const { component, branchLike } = props;
return (
<Modal contentLabel={translate('regulatory_report.page')} onRequestClose={props.onClose}>
<ClickEventBoundary>
<form>
<RegulatoryReport component={component} branchLike={branchLike} onClose={props.onClose} />
</form>
</ClickEventBoundary>
</Modal>
);
}

server/sonar-web/src/main/js/apps/projectRegulatoryReport/__tests__/RegulatoryReport-it.tsx → server/sonar-web/src/main/js/app/components/nav/component/projectInformation/projectRegulatoryReport/__tests__/RegulatoryReport-it.tsx Parādīt failu

@@ -20,9 +20,20 @@
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import * as React from 'react';
import { renderComponent } from '../../../helpers/testReactTestingUtils';
import BranchesServiceMock from '../../../../../../../api/mocks/BranchesServiceMock';
import { renderComponent } from '../../../../../../../helpers/testReactTestingUtils';
import RegulatoryReport from '../RegulatoryReport';

jest.mock('../../../../../../../api/branches');

let handler: BranchesServiceMock;

beforeAll(() => {
handler = new BranchesServiceMock();
});

afterEach(() => handler.resetBranches());

it('should open the regulatory report page', async () => {
const user = userEvent.setup();
renderRegulatoryReportApp();
@@ -30,6 +41,12 @@ it('should open the regulatory report page', async () => {
expect(screen.getByText('regulatory_report.description1')).toBeInTheDocument();
expect(screen.getByText('regulatory_report.description2')).toBeInTheDocument();

const branchSelect = screen.getByRole('textbox');
expect(branchSelect).toBeInTheDocument();

await user.click(branchSelect);
await user.keyboard('[ArrowDown][Enter]');

const downloadButton = screen.getByText('download_verb');
expect(downloadButton).toBeInTheDocument();

@@ -39,5 +56,5 @@ it('should open the regulatory report page', async () => {
});

function renderRegulatoryReportApp() {
renderComponent(<RegulatoryReport branchLike={undefined} component={{ key: '', name: '' }} />);
renderComponent(<RegulatoryReport component={{ key: '', name: '' }} onClose={() => {}} />);
}

+ 0
- 6
server/sonar-web/src/main/js/app/utils/startReactApp.tsx Parādīt failu

@@ -239,12 +239,6 @@ function renderComponentRoutes() {
path="project/deletion"
component={lazyLoadComponent(() => import('../../apps/projectDeletion/App'))}
/>
<Route
path="project/regulatory-report"
component={lazyLoadComponent(() =>
import('../../apps/projectRegulatoryReport/RegulatoryReport')
)}
/>
<Route
path="project/links"
component={lazyLoadComponent(() => import('../../apps/projectLinks/App'))}

+ 0
- 66
server/sonar-web/src/main/js/apps/projectRegulatoryReport/RegulatoryReport.tsx Parādīt failu

@@ -1,66 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2022 SonarSource SA
* mailto:info 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 classNames from 'classnames';
import * as React from 'react';
import { getRegulatoryReportUrl } from '../../api/regulatory-report';
import { isBranch } from '../../helpers/branch-like';
import { translate } from '../../helpers/l10n';
import { BranchLike } from '../../types/branch-like';
import { Component } from '../../types/types';

interface Props {
component: Pick<Component, 'key' | 'name'>;
branchLike?: BranchLike;
}

function RegulatoryReport(props: Props) {
const { component, branchLike } = props;
const branchName = branchLike && isBranch(branchLike) ? branchLike.name : undefined;
const [downloadStarted, setDownloadStarted] = React.useState(false);
return (
<div className="page page-limited">
<header className="page-header">
<h1 className="page-title">{translate('regulatory_report.page')}</h1>
</header>
<div className="page-description">
<p>{translate('regulatory_report.description1')}</p>
<p>{translate('regulatory_report.description2')}</p>
<div className="big-spacer-top">
<a
className={classNames('button button-primary', { disabled: downloadStarted })}
download={[component.name, branchName, 'PDF Report'].filter(s => !!s).join(' - ')}
onClick={() => setDownloadStarted(true)}
href={getRegulatoryReportUrl(component.key, branchName)}
target="_blank"
rel="noopener noreferrer">
{translate('download_verb')}
</a>
{downloadStarted && (
<div className="spacer-top">
<p>{translate('regulatory_page.download_start.sentence')}</p>
</div>
)}
</div>
</div>
</div>
);
}

export default RegulatoryReport;

+ 6
- 2
sonar-core/src/main/resources/org/sonar/l10n/core.properties Parādīt failu

@@ -647,9 +647,13 @@ baseline.branch_analyses.ranges.allTime=All time
baseline.no_analyses=No analyses

regulatory_report.page=Regulatory Report
regulatory_report.description1=The regulatory report is a zip file containing a snapshot of the branch you selected. It contains an overview of the project, the configuration items relevant to its quality (quality profile, quality gate and analysis exclusions), as well as lists of findings for both new code and overall code.
regulatory_report.description2=The file is created on demand when you download it. This may take some time.
regulatory_report.description1=The regulatory report is a zip file containing a snapshot of the selected branch. It contains:
regulatory_report.bullet_point1=An overview of the selected branch of the project.
regulatory_report.bullet_point2=The configuration items relevant to the project's quality (quality profile, quality gate, and analysis exclusions).
regulatory_report.bullet_point3=Lists of findings for both new and overall code on the selected branch.
regulatory_report.description2=The generation and download of the report may take a few minutes.
regulatory_page.download_start.sentence=Your download should start shortly. This may take some time.
regulatory_page.select_branch=Select Branch

#------------------------------------------------------------------------------
#

Notiek ielāde…
Atcelt
Saglabāt