From 68c3027b07fe706a58ac69dcb356dc86d9b3c1a0 Mon Sep 17 00:00:00 2001 From: Wouter Admiraal Date: Tue, 25 Jan 2022 12:01:52 +0100 Subject: [PATCH] SONAR-15782 Move application report code to core extensions --- .../components/extensions/exposeLibraries.ts | 4 +- .../js/app/components/nav/component/Menu.tsx | 18 --- .../src/main/js/app/utils/startReactApp.tsx | 12 +- .../ApplicationSettingsApp.tsx | 136 ------------------ .../ReportFrequencyForm.tsx | 96 ------------- .../__tests__/ApplicationSettingsApp-test.tsx | 70 --------- .../__tests__/ReportFrequencyForm-test.tsx | 70 --------- .../ApplicationSettingsApp-test.tsx.snap | 59 -------- .../ReportFrequencyForm-test.tsx.snap | 108 -------------- .../js/apps/application-settings/routes.ts | 28 ---- .../sonar-web/src/main/js/types/settings.ts | 3 +- .../resources/org/sonar/l10n/core.properties | 3 - 12 files changed, 14 insertions(+), 593 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/application-settings/ApplicationSettingsApp.tsx delete mode 100644 server/sonar-web/src/main/js/apps/application-settings/ReportFrequencyForm.tsx delete mode 100644 server/sonar-web/src/main/js/apps/application-settings/__tests__/ApplicationSettingsApp-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/application-settings/__tests__/ReportFrequencyForm-test.tsx delete mode 100644 server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ApplicationSettingsApp-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ReportFrequencyForm-test.tsx.snap delete mode 100644 server/sonar-web/src/main/js/apps/application-settings/routes.ts diff --git a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts index d85617d3fa7..03bccc291d7 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts +++ b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts @@ -99,6 +99,7 @@ import { postJSONBody, request } from '../../../helpers/request'; +import { sanitizeStringRestricted } from '../../../helpers/sanitize'; import { getStandards, renderCWECategory, @@ -162,7 +163,8 @@ const exposeLibraries = () => { getComponentIssuesUrl, getComponentSecurityHotspotsUrl, getMeasureHistoryUrl, - getRulesUrl + getRulesUrl, + sanitizeStringRestricted }; } }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx b/server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx index dead2fed58b..609f6461392 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx @@ -318,7 +318,6 @@ export class Menu extends React.PureComponent { this.renderSettingsLink(query, isApplication, isPortfolio), this.renderBranchesLink(query, isProject), this.renderBaselineLink(query, isApplication, isPortfolio), - this.renderReportSettingsLink(query, isApplication), ...this.renderAdminExtensions(query, isApplication), this.renderImportExportLink(query, isProject), this.renderProfilesLink(query), @@ -410,23 +409,6 @@ export class Menu extends React.PureComponent { ); }; - renderReportSettingsLink = (query: Query, isApplication: boolean) => { - const extensions = this.getConfiguration().extensions || []; - const hasGovernance = extensions.find(e => e.key === 'governance/console'); - - if (!isApplication || !hasGovernance) { - return null; - } - - return ( -
  • - - {translate('application_settings.report')} - -
  • - ); - }; - renderImportExportLink = (query: Query, isProject: boolean) => { if (!isProject) { return null; diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx index 40c777ca892..2b03991f6e3 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx @@ -27,7 +27,6 @@ import { IntlProvider } from 'react-intl'; import { Provider } from 'react-redux'; import { IndexRoute, Redirect, Route, RouteConfig, RouteProps, Router } from 'react-router'; import accountRoutes from '../../apps/account/routes'; -import applicationSettingsRoutes from '../../apps/application-settings/routes'; import auditLogsRoutes from '../../apps/audit-logs/routes'; import backgroundTasksRoutes from '../../apps/background-tasks/routes'; import codeRoutes from '../../apps/code/routes'; @@ -123,6 +122,16 @@ function renderRedirects() { }} /> + { + replace({ + pathname: '/project/admin/extension/governance/application_report', + query: { id: nextState.location.query.id } + }); + }} + /> + { @@ -226,7 +235,6 @@ function renderComponentRoutes() { - { - mounted = false; - - state: State = { - loading: true - }; - - componentDidMount() { - this.mounted = true; - this.fetchInitialData(); - } - - async componentDidUpdate(prevProps: Props) { - if (prevProps.component.key !== this.props.component.key) { - this.setState({ loading: true }); - await this.fetchSetting(); - this.setState({ loading: false }); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchInitialData = async () => { - this.setState({ loading: true }); - await Promise.all([this.fetchDefinition(), this.fetchSetting()]); - this.setState({ loading: false }); - }; - - fetchDefinition = async () => { - const { component } = this.props; - try { - const definitions = await getDefinitions(component.key); - const definition = definitions.find(d => d.key === SettingsKey.ProjectReportFrequency); - - if (this.mounted) { - this.setState({ definition }); - } - } catch (_) { - /* do nothing */ - } - }; - - fetchSetting = async () => { - const { component } = this.props; - try { - const setting = ( - await getValues({ component: component.key, keys: SettingsKey.ProjectReportFrequency }) - ).pop(); - - if (this.mounted) { - this.setState({ - frequency: setting ? setting.value : undefined - }); - } - } catch (_) { - /* do nothing */ - } - }; - - handleSubmit = async (frequency: string) => { - const { component } = this.props; - - try { - await setSimpleSettingValue({ - component: component.key, - key: SettingsKey.ProjectReportFrequency, - value: frequency - }); - - this.setState({ frequency }); - } catch (_) { - /* Do nothing */ - } - }; - - render() { - const { definition, frequency, loading } = this.state; - - return ( -
    -

    {translate('application_settings.page')}

    -
    - -
    - {definition && frequency && ( - - )} -
    -
    -
    -
    - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-settings/ReportFrequencyForm.tsx b/server/sonar-web/src/main/js/apps/application-settings/ReportFrequencyForm.tsx deleted file mode 100644 index 545d432c459..00000000000 --- a/server/sonar-web/src/main/js/apps/application-settings/ReportFrequencyForm.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 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 { Button, ResetButtonLink } from '../../components/controls/buttons'; -import SelectLegacy from '../../components/controls/SelectLegacy'; -import { translate } from '../../helpers/l10n'; -import { sanitizeStringRestricted } from '../../helpers/sanitize'; -import { SettingCategoryDefinition } from '../../types/settings'; - -export interface ReportFrequencyFormProps { - definition: SettingCategoryDefinition; - frequency: string; - onSave: (value: string) => Promise; -} - -export default function ReportFrequencyForm(props: ReportFrequencyFormProps) { - const { definition, frequency } = props; - const { defaultValue } = definition; - - const [currentSelection, setCurrentSelection] = React.useState(frequency); - - const options = props.definition.options.map(option => ({ - label: option, - value: option - })); - - const handleReset = () => { - if (defaultValue) { - setCurrentSelection(defaultValue); - props.onSave(defaultValue); - } - }; - - return ( -
    -

    {translate('application_settings.report.frequency')}

    - {definition.description && ( -
    - )} - - setCurrentSelection(value)} - options={options} - value={currentSelection} - /> - -
    - {frequency !== currentSelection && ( - - )} - - {defaultValue !== undefined && frequency !== defaultValue && ( - - )} - - {frequency !== currentSelection && ( - setCurrentSelection(frequency)}> - {translate('cancel')} - - )} -
    -
    - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-settings/__tests__/ApplicationSettingsApp-test.tsx b/server/sonar-web/src/main/js/apps/application-settings/__tests__/ApplicationSettingsApp-test.tsx deleted file mode 100644 index 77f8c981da3..00000000000 --- a/server/sonar-web/src/main/js/apps/application-settings/__tests__/ApplicationSettingsApp-test.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { setSimpleSettingValue } from '../../../api/settings'; -import { mockComponent } from '../../../helpers/mocks/component'; -import { waitAndUpdate } from '../../../helpers/testUtils'; -import { SettingsKey } from '../../../types/settings'; -import ApplicationSettingsApp from '../ApplicationSettingsApp'; - -jest.mock('../../../api/settings', () => { - const { mockDefinition } = jest.requireActual('../../../helpers/mocks/settings'); - - const definition = mockDefinition({ - key: 'sonar.governance.report.project.branch.frequency', // SettingsKey.ProjectReportFrequency - defaultValue: 'Monthly', - description: 'description', - options: ['Daily', 'Weekly', 'Monthly'] - }); - - return { - getDefinitions: jest.fn().mockResolvedValue([definition]), - getValues: jest.fn().mockResolvedValue([{ value: 'Monthly' }]), - setSimpleSettingValue: jest.fn().mockResolvedValue(undefined) - }; -}); - -it('should render correctly', async () => { - const wrapper = shallowRender(); - expect(wrapper).toMatchSnapshot('loading'); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('default'); -}); - -it('should handle submission', async () => { - const component = mockComponent({ key: 'app-key' }); - const wrapper = shallowRender({ component }); - await waitAndUpdate(wrapper); - - wrapper.instance().handleSubmit('Daily'); - - expect(setSimpleSettingValue).toBeCalledWith({ - component: component.key, - key: SettingsKey.ProjectReportFrequency, - value: 'Daily' - }); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-settings/__tests__/ReportFrequencyForm-test.tsx b/server/sonar-web/src/main/js/apps/application-settings/__tests__/ReportFrequencyForm-test.tsx deleted file mode 100644 index dc6db927c59..00000000000 --- a/server/sonar-web/src/main/js/apps/application-settings/__tests__/ReportFrequencyForm-test.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { Button, ResetButtonLink } from '../../../components/controls/buttons'; -import SelectLegacy from '../../../components/controls/SelectLegacy'; -import { mockDefinition } from '../../../helpers/mocks/settings'; -import ReportFrequencyForm, { ReportFrequencyFormProps } from '../ReportFrequencyForm'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ frequency: 'Weekly' })).toMatchSnapshot('changed'); - expect(shallowRender({ definition: mockDefinition() })).toMatchSnapshot('no description'); -}); - -it('should handle changes', () => { - const onSave = jest.fn(); - const wrapper = shallowRender({ onSave }); - - wrapper.find(SelectLegacy).simulate('change', { value: 'Daily' }); - - expect(wrapper.find('.button-success').exists()).toBe(true); - expect(wrapper.find(ResetButtonLink).exists()).toBe(true); - - wrapper.find(Button).simulate('click'); - - expect(onSave).toBeCalledWith('Daily'); -}); - -it('should handle reset', () => { - const onSave = jest.fn(); - const wrapper = shallowRender({ frequency: 'Weekly', onSave }); - - expect(wrapper.find('.button-success').exists()).toBe(false); - wrapper.find(Button).simulate('click'); - - expect(onSave).toBeCalledWith('Monthly'); -}); - -function shallowRender(props: Partial = {}) { - return shallow( - - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ApplicationSettingsApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ApplicationSettingsApp-test.tsx.snap deleted file mode 100644 index 60191d42174..00000000000 --- a/server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ApplicationSettingsApp-test.tsx.snap +++ /dev/null @@ -1,59 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` -
    -

    - application_settings.page -

    -
    - -
    - -
    -
    -
    -
    -`; - -exports[`should render correctly: loading 1`] = ` -
    -

    - application_settings.page -

    -
    - -
    - -
    -
    -`; diff --git a/server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ReportFrequencyForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ReportFrequencyForm-test.tsx.snap deleted file mode 100644 index 7ea031a392b..00000000000 --- a/server/sonar-web/src/main/js/apps/application-settings/__tests__/__snapshots__/ReportFrequencyForm-test.tsx.snap +++ /dev/null @@ -1,108 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: changed 1`] = ` -
    -

    - application_settings.report.frequency -

    -
    - -
    - -
    -
    -`; - -exports[`should render correctly: default 1`] = ` -
    -

    - application_settings.report.frequency -

    -
    - -
    -
    -`; - -exports[`should render correctly: no description 1`] = ` -
    -

    - application_settings.report.frequency -

    - -
    -
    -`; diff --git a/server/sonar-web/src/main/js/apps/application-settings/routes.ts b/server/sonar-web/src/main/js/apps/application-settings/routes.ts deleted file mode 100644 index e1f12d9d8ad..00000000000 --- a/server/sonar-web/src/main/js/apps/application-settings/routes.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 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 { lazyLoadComponent } from '../../components/lazyLoadComponent'; - -const routes = [ - { - indexRoute: { component: lazyLoadComponent(() => import('./ApplicationSettingsApp')) } - } -]; - -export default routes; diff --git a/server/sonar-web/src/main/js/types/settings.ts b/server/sonar-web/src/main/js/types/settings.ts index 82098ddfc3d..2d50a443fe2 100644 --- a/server/sonar-web/src/main/js/types/settings.ts +++ b/server/sonar-web/src/main/js/types/settings.ts @@ -21,8 +21,7 @@ export const enum SettingsKey { DaysBeforeDeletingInactiveBranchesAndPRs = 'sonar.dbcleaner.daysBeforeDeletingInactiveBranchesAndPRs', DefaultProjectVisibility = 'projects.default.visibility', ServerBaseUrl = 'sonar.core.serverBaseURL', - PluginRiskConsent = 'sonar.plugins.risk.consent', - ProjectReportFrequency = 'sonar.governance.report.project.branch.frequency' + PluginRiskConsent = 'sonar.plugins.risk.consent' } export type Setting = SettingValue & { definition: SettingDefinition; hasValue: boolean }; 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 71be2967cd2..3528fb722c5 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -556,9 +556,6 @@ visibility.private.description.long=Only members of the organization will be abl # #------------------------------------------------------------------------------ -application_settings.page=Application Settings -application_settings.report=Application Report Settings -application_settings.report.frequency=Application Reports Frequency coding_rules.page=Rules global_permissions.page=Global Permissions global_permissions.page.description=Grant and revoke permissions to make changes at the global level. These permissions include editing Quality Profiles, executing analysis, and performing global system administration. -- 2.39.5