diff options
author | Wouter Admiraal <wouter.admiraal@sonarsource.com> | 2022-01-25 11:25:46 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-01-27 20:03:05 +0000 |
commit | 1d409d5db753fe003513f4e1a8d99a0fe6c1becc (patch) | |
tree | 55d7b7f5637d017d70175072ec209c68353d8d34 | |
parent | af68aa7b419e675aaa903b8a77070b727aa71383 (diff) | |
download | sonarqube-1d409d5db753fe003513f4e1a8d99a0fe6c1becc.tar.gz sonarqube-1d409d5db753fe003513f4e1a8d99a0fe6c1becc.zip |
SONAR-15782 Move application console code to core extensions
42 files changed, 20 insertions, 3223 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index d49d2fd4d00..b50b600b491 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -122,6 +122,7 @@ eslint_report_cache_template: &ESLINT_REPORT_CACHE_TEMPLATE - private/core-extension-securityreport/eslint-report/ - private/core-extension-license/eslint-report/ - private/core-extension-governance/eslint-report/ + - private/core-extension-developer-server/eslint-report/ fingerprint_script: echo $CIRRUS_BUILD_ID jest_report_cache_template: &JEST_REPORT_CACHE_TEMPLATE @@ -131,6 +132,7 @@ jest_report_cache_template: &JEST_REPORT_CACHE_TEMPLATE - private/core-extension-securityreport/coverage/ - private/core-extension-license/coverage/ - private/core-extension-governance/coverage/ + - private/core-extension-developer-server/coverage/ fingerprint_script: echo $CIRRUS_BUILD_ID junit_report_cache_template: &JUNIT_REPORT_CACHE_TEMPLATE diff --git a/server/sonar-web/src/main/js/api/application.ts b/server/sonar-web/src/main/js/api/application.ts index 42518728ba0..209c67af262 100644 --- a/server/sonar-web/src/main/js/api/application.ts +++ b/server/sonar-web/src/main/js/api/application.ts @@ -19,7 +19,7 @@ */ import throwGlobalError from '../app/utils/throwGlobalError'; import { getJSON, post, postJSON } from '../helpers/request'; -import { Application, ApplicationPeriod, ApplicationProject } from '../types/application'; +import { Application, ApplicationPeriod } from '../types/application'; import { Visibility } from '../types/component'; export function getApplicationLeak( @@ -39,51 +39,6 @@ export function getApplicationDetails(application: string, branch?: string): Pro ); } -export function addApplicationBranch(data: { - application: string; - branch: string; - project: string[]; - projectBranch: string[]; -}) { - return post('/api/applications/create_branch', data).catch(throwGlobalError); -} - -export function updateApplicationBranch(data: { - application: string; - branch: string; - name: string; - project: string[]; - projectBranch: string[]; -}) { - return post('/api/applications/update_branch', data).catch(throwGlobalError); -} - -export function deleteApplicationBranch(application: string, branch: string) { - return post('/api/applications/delete_branch', { application, branch }).catch(throwGlobalError); -} - -export function getApplicationProjects(data: { - application: string; - p?: number; - ps?: number; - q?: string; - selected: string; -}): Promise<{ paging: T.Paging; projects: ApplicationProject[] }> { - return getJSON('/api/applications/search_projects', data).catch(throwGlobalError); -} - -export function addProjectToApplication(application: string, project: string) { - return post('/api/applications/add_project', { application, project }).catch(throwGlobalError); -} - -export function removeProjectFromApplication(application: string, project: string) { - return post('/api/applications/remove_project', { application, project }).catch(throwGlobalError); -} - -export function refreshApplication(key: string) { - return post('/api/applications/refresh', { key }).catch(throwGlobalError); -} - export function createApplication( name: string, description: string, @@ -105,9 +60,3 @@ export function createApplication( export function deleteApplication(application: string) { return post('/api/applications/delete', { application }).catch(throwGlobalError); } - -export function editApplication(application: string, name: string, description: string) { - return post('/api/applications/update', { name, description, application }).catch( - throwGlobalError - ); -} 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 4cb44009b46..dead2fed58b 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 @@ -36,7 +36,6 @@ import { ComponentQualifier, isPortfolioLike } from '../../../../types/component import './Menu.css'; const SETTINGS_URLS = [ - '/application/console', '/project/admin', '/project/baseline', '/project/branches', @@ -319,7 +318,6 @@ export class Menu extends React.PureComponent<Props> { this.renderSettingsLink(query, isApplication, isPortfolio), this.renderBranchesLink(query, isProject), this.renderBaselineLink(query, isApplication, isPortfolio), - this.renderConsoleAppLink(query, isApplication), this.renderReportSettingsLink(query, isApplication), ...this.renderAdminExtensions(query, isApplication), this.renderImportExportLink(query, isProject), @@ -412,19 +410,6 @@ export class Menu extends React.PureComponent<Props> { ); }; - renderConsoleAppLink = (query: Query, isApplication: boolean) => { - if (!isApplication) { - return null; - } - return ( - <li key="app-console"> - <Link activeClassName="active" to={{ pathname: '/application/console', query }}> - {translate('application_console.page')} - </Link> - </li> - ); - }; - renderReportSettingsLink = (query: Query, isApplication: boolean) => { const extensions = this.getConfiguration().extensions || []; const hasGovernance = extensions.find(e => e.key === 'governance/console'); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Menu-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Menu-test.tsx.snap index e97e4aa5b53..87467c85c81 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Menu-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/Menu-test.tsx.snap @@ -92,23 +92,6 @@ exports[`should disable links if application has inaccessible projects 1`] = ` style={Object {}} to={ Object { - "pathname": "/application/console", - "query": Object { - "id": "foo", - }, - } - } - > - application_console.page - </Link> - </li> - <li> - <Link - activeClassName="active" - onlyActiveOnIndex={false} - style={Object {}} - to={ - Object { "pathname": "/project/deletion", "query": Object { "id": "foo", @@ -1112,23 +1095,6 @@ exports[`should work for qualifier: APP, false 1`] = ` style={Object {}} to={ Object { - "pathname": "/application/console", - "query": Object { - "id": "foo", - }, - } - } - > - application_console.page - </Link> - </li> - <li> - <Link - activeClassName="active" - onlyActiveOnIndex={false} - style={Object {}} - to={ - Object { "pathname": "/project/deletion", "query": Object { "id": "foo", diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap index 231a3776bc6..1548a5317c3 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/CurrentBranchLike-test.tsx.snap @@ -81,7 +81,7 @@ exports[`applications should render correctly when there is only one branch and style={Object {}} to={ Object { - "pathname": "/application/console", + "pathname": "/project/admin/extension/developer-server/application-console", "query": Object { "id": "my-project", }, 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 c9b4d492a54..40c777ca892 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 applicationConsoleRoutes from '../../apps/application-console/routes'; import applicationSettingsRoutes from '../../apps/application-settings/routes'; import auditLogsRoutes from '../../apps/audit-logs/routes'; import backgroundTasksRoutes from '../../apps/background-tasks/routes'; @@ -115,6 +114,16 @@ function renderRedirects() { /> <Route + path="/application/console" + onEnter={(nextState, replace) => { + replace({ + pathname: '/project/admin/extension/developer-server/application-console', + query: { id: nextState.location.query.id } + }); + }} + /> + + <Route path="/issues/search" onEnter={(_, replace) => { replace(`/issues${window.location.hash}`); @@ -217,7 +226,6 @@ function renderComponentRoutes() { <RouteWithChildRoutes path="project/import_export" childRoutes={projectDumpRoutes} /> <RouteWithChildRoutes path="project/settings" childRoutes={settingsRoutes} /> <RouteWithChildRoutes path="project_roles" childRoutes={projectPermissionsRoutes} /> - <RouteWithChildRoutes path="application/console" childRoutes={applicationConsoleRoutes} /> <RouteWithChildRoutes path="application/settings" childRoutes={applicationSettingsRoutes} /> <RouteWithChildRoutes path="project/webhooks" childRoutes={webhooksRoutes} /> <Route diff --git a/server/sonar-web/src/main/js/apps/application-console/ApplicationBranches.tsx b/server/sonar-web/src/main/js/apps/application-console/ApplicationBranches.tsx deleted file mode 100644 index 70360060872..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/ApplicationBranches.tsx +++ /dev/null @@ -1,128 +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 } from '../../components/controls/buttons'; -import { Alert } from '../../components/ui/Alert'; -import { translate } from '../../helpers/l10n'; -import { Application } from '../../types/application'; -import ApplicationProjectBranch from './ApplicationProjectBranch'; -import CreateBranchForm from './CreateBranchForm'; -import { ApplicationBranch } from './utils'; - -interface Props { - application: Application; - canBrowseAllChildProjects: boolean; - onUpdateBranches: (branches: ApplicationBranch[]) => void; -} - -interface State { - creating: boolean; -} - -export default class ApplicationBranches extends React.PureComponent<Props, State> { - state: State = { creating: false }; - - handleCreate = (branch: ApplicationBranch) => { - this.props.onUpdateBranches([...this.props.application.branches, branch]); - }; - - handleCreateFormClose = () => { - this.setState({ creating: false }); - }; - - handleCreateClick = () => { - this.setState({ creating: true }); - }; - - canCreateBranches = () => { - return ( - this.props.application.projects && - this.props.application.projects.some(p => Boolean(p.enabled)) - ); - }; - - renderBranches(createEnable: boolean, readonly: boolean) { - const { application } = this.props; - if (!createEnable) { - return ( - <div className="app-branches-list"> - <p className="text-center big-spacer-top"> - {translate('application_console.branches.no_branches')} - </p> - </div> - ); - } - return ( - <div className="app-branches-list"> - <table className="data zebra"> - <tbody> - {application.branches.map(branch => ( - <ApplicationProjectBranch - application={application} - branch={branch} - key={branch.name} - onUpdateBranches={this.props.onUpdateBranches} - readonly={readonly} - /> - ))} - </tbody> - </table> - </div> - ); - } - - render() { - const { application, canBrowseAllChildProjects } = this.props; - const createEnable = this.canCreateBranches(); - const readonly = !canBrowseAllChildProjects; - return ( - <div className="app-branches-console"> - {readonly && ( - <Alert className="huge-spacer-top" variant="warning"> - {translate('application_console.branches.cannot_access_all_child_projects')} - </Alert> - )} - - <div className="boxed-group-actions"> - <Button disabled={!createEnable || readonly} onClick={this.handleCreateClick}> - {translate('application_console.branches.create')} - </Button> - </div> - <h2 - className="text-limited big-spacer-top" - title={translate('application_console.branches')}> - {translate('application_console.branches')} - </h2> - <p>{translate('application_console.branches.help')}</p> - - {this.renderBranches(createEnable, readonly)} - - {this.state.creating && ( - <CreateBranchForm - application={application} - enabledProjectsKey={application.projects.map(p => p.key)} - onClose={this.handleCreateFormClose} - onCreate={this.handleCreate} - /> - )} - </div> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/ApplicationConsoleApp.tsx b/server/sonar-web/src/main/js/apps/application-console/ApplicationConsoleApp.tsx deleted file mode 100644 index 21b7bac88ee..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/ApplicationConsoleApp.tsx +++ /dev/null @@ -1,137 +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 { Location } from 'history'; -import * as React from 'react'; -import { InjectedRouter } from 'react-router'; -import { editApplication, getApplicationDetails, refreshApplication } from '../../api/application'; -import addGlobalSuccessMessage from '../../app/utils/addGlobalSuccessMessage'; -import { translate } from '../../helpers/l10n'; -import { Application, ApplicationProject } from '../../types/application'; -import ApplicationConsoleAppRenderer from './ApplicationConsoleAppRenderer'; -import { ApplicationBranch } from './utils'; - -interface Props { - component: Pick<T.Component, 'key' | 'canBrowseAllChildProjects'>; - location: Location; - router: Pick<InjectedRouter, 'replace'>; -} - -interface State { - application?: Application; - loading: boolean; -} - -export default class ApplicationConsoleApp extends React.PureComponent<Props, State> { - mounted = false; - - state: State = { - loading: false - }; - - componentDidMount() { - this.mounted = true; - this.fetchDetails(); - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.component.key !== this.props.component.key) { - this.fetchDetails(); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - updateApplicationState = (buildNewFields: (prevApp: Application) => Partial<Application>) => { - this.setState(state => { - if (state.application) { - return { application: { ...state.application, ...buildNewFields(state.application) } }; - } - - return null; - }); - }; - - fetchDetails = async () => { - try { - const application = await getApplicationDetails(this.props.component.key); - if (this.mounted) { - this.setState({ application, loading: false }); - } - } catch { - if (this.mounted) { - this.setState({ loading: false }); - } - } - }; - - handleRefreshClick = async () => { - if (this.state.application) { - await refreshApplication(this.state.application.key); - addGlobalSuccessMessage(translate('application_console.refresh_started')); - } - }; - - handleEdit = async (name: string, description: string) => { - if (this.state.application) { - await editApplication(this.state.application.key, name, description); - } - if (this.mounted) { - this.updateApplicationState(() => ({ name, description })); - } - }; - - handleAddProject = (project: ApplicationProject) => { - this.updateApplicationState(prevApp => ({ projects: [...prevApp.projects, project] })); - }; - - handleRemoveProject = (projectKey: string) => { - this.updateApplicationState(prevApp => ({ - projects: prevApp.projects.filter(p => p.key !== projectKey) - })); - }; - - handleUpdateBranches = (branches: ApplicationBranch[]) => { - this.updateApplicationState(() => ({ branches })); - }; - - render() { - const { component } = this.props; - const { application, loading } = this.state; - if (!application) { - // when application is not found - return null; - } - - return ( - <ApplicationConsoleAppRenderer - loading={loading} - application={application} - canBrowseAllChildProjects={Boolean(component.canBrowseAllChildProjects)} - onAddProject={this.handleAddProject} - onEdit={this.handleEdit} - onRefresh={this.handleRefreshClick} - onRemoveProject={this.handleRemoveProject} - onUpdateBranches={this.handleUpdateBranches} - /> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/ApplicationConsoleAppRenderer.tsx b/server/sonar-web/src/main/js/apps/application-console/ApplicationConsoleAppRenderer.tsx deleted file mode 100644 index 207ee55edc6..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/ApplicationConsoleAppRenderer.tsx +++ /dev/null @@ -1,104 +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 } from '../../components/controls/buttons'; -import { translate } from '../../helpers/l10n'; -import { Application, ApplicationProject } from '../../types/application'; -import { Branch } from '../../types/branch-like'; -import ApplicationBranches from './ApplicationBranches'; -import ApplicationProjects from './ApplicationProjects'; -import EditForm from './EditForm'; - -export interface ApplicationConsoleAppRendererProps { - loading: boolean; - application: Application; - canBrowseAllChildProjects: boolean; - onAddProject: (project: ApplicationProject) => void; - onRefresh: () => void; - onEdit: (name: string, description: string) => Promise<void>; - onRemoveProject: (projectKey: string) => void; - onUpdateBranches: (branches: Branch[]) => void; -} - -export default function ApplicationConsoleAppRenderer(props: ApplicationConsoleAppRendererProps) { - const [editing, setEditing] = React.useState(false); - - const { application, canBrowseAllChildProjects, loading } = props; - - if (loading) { - return <i className="spinner spacer" />; - } - - return ( - <div className="page page-limited"> - <div className="boxed-group" id="view-details"> - <div className="boxed-group-actions"> - <Button - className="little-spacer-right" - id="view-details-edit" - onClick={() => setEditing(true)}> - {translate('edit')} - </Button> - <Button className="little-spacer-right" onClick={props.onRefresh}> - {translate('application_console.recompute')} - </Button> - </div> - - <header className="boxed-group-header" id="view-details-header"> - <h2 className="text-limited" title={application.name}> - {application.name} - </h2> - </header> - - <div className="boxed-group-inner" id="view-details-content"> - <div className="big-spacer-bottom"> - {application.description && ( - <div className="little-spacer-bottom">{application.description}</div> - )} - <div className="subtitle"> - {translate('key')}: {application.key} - </div> - </div> - - <ApplicationProjects - onAddProject={props.onAddProject} - onRemoveProject={props.onRemoveProject} - application={application} - /> - - <ApplicationBranches - application={application} - canBrowseAllChildProjects={canBrowseAllChildProjects} - onUpdateBranches={props.onUpdateBranches} - /> - </div> - - {editing && ( - <EditForm - header={translate('application_console.edit')} - onClose={() => setEditing(false)} - onEdit={props.onEdit} - application={application} - /> - )} - </div> - </div> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/ApplicationProjectBranch.tsx b/server/sonar-web/src/main/js/apps/application-console/ApplicationProjectBranch.tsx deleted file mode 100644 index 15b74069735..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/ApplicationProjectBranch.tsx +++ /dev/null @@ -1,59 +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 BranchIcon from '../../components/icons/BranchIcon'; -import { translate } from '../../helpers/l10n'; -import { Application } from '../../types/application'; -import BranchRowActions from './BranchRowActions'; -import { ApplicationBranch } from './utils'; - -export interface ApplicationProjectBranchProps { - application: Application; - branch: ApplicationBranch; - onUpdateBranches: (branches: Array<ApplicationBranch>) => void; - readonly: boolean; -} - -export default function ApplicationProjectBranch(props: ApplicationProjectBranchProps) { - const { application, branch, readonly } = props; - - return ( - <tr> - <td> - <BranchIcon className="little-spacer-right" /> - {branch.name} - {branch.isMain && ( - <span className="badge spacer-left"> - {translate('application_console.branches.main_branch')} - </span> - )} - </td> - <td className="thin nowrap"> - {!branch.isMain && !readonly && ( - <BranchRowActions - application={application} - branch={branch} - onUpdateBranches={props.onUpdateBranches} - /> - )} - </td> - </tr> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/ApplicationProjects.tsx b/server/sonar-web/src/main/js/apps/application-console/ApplicationProjects.tsx deleted file mode 100644 index c7ca29443b0..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/ApplicationProjects.tsx +++ /dev/null @@ -1,233 +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 classNames from 'classnames'; -import { find, without } from 'lodash'; -import * as React from 'react'; -import { - addProjectToApplication, - getApplicationProjects, - removeProjectFromApplication -} from '../../api/application'; -import SelectList, { - SelectListFilter, - SelectListSearchParams -} from '../../components/controls/SelectList'; -import Tooltip from '../../components/controls/Tooltip'; -import QualifierIcon from '../../components/icons/QualifierIcon'; -import WarningIcon from '../../components/icons/WarningIcon'; -import { translate } from '../../helpers/l10n'; -import { Application, ApplicationProject } from '../../types/application'; - -interface Props { - onAddProject?: (project: ApplicationProject) => void; - onRemoveProject?: (projectKey: string) => void; - application: Application; -} - -interface State { - disabledProjects: string[]; - lastSearchParams: SelectListSearchParams & { applicationKey: string }; - needToReload: boolean; - projects: Array<ApplicationProject>; - projectsTotalCount?: number; - selectedProjects: string[]; -} - -export default class ApplicationProjects extends React.PureComponent<Props, State> { - mounted = false; - - constructor(props: Props) { - super(props); - - this.state = { - disabledProjects: [], - lastSearchParams: { - applicationKey: props.application.key, - query: '', - filter: SelectListFilter.Selected - }, - needToReload: false, - projects: [], - selectedProjects: [] - }; - } - - componentDidMount() { - this.mounted = true; - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.application.key !== this.props.application.key) { - this.setState( - prevState => { - return { - lastSearchParams: { - ...prevState.lastSearchParams, - applicationKey: this.props.application.key - } - }; - }, - () => this.fetchProjects(this.state.lastSearchParams) - ); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - loadApplicationProjects = (searchParams: SelectListSearchParams) => - getApplicationProjects({ - application: this.state.lastSearchParams.applicationKey, - p: searchParams.page, - ps: searchParams.pageSize, - q: searchParams.query !== '' ? searchParams.query : undefined, - selected: searchParams.filter - }); - - fetchProjects = (searchParams: SelectListSearchParams) => - this.loadApplicationProjects(searchParams).then(data => { - if (this.mounted) { - this.setState(prevState => { - const more = searchParams.page != null && searchParams.page > 1; - - const { projects, selectedProjects, disabledProjects } = this.dealWithProjects( - data, - more, - prevState - ); - - return { - disabledProjects, - lastSearchParams: { ...prevState.lastSearchParams, ...searchParams }, - needToReload: false, - projects, - projectsTotalCount: data.paging.total, - selectedProjects - }; - }); - } - }); - - dealWithProjects = ( - data: { projects: Array<ApplicationProject>; paging: T.Paging }, - more: boolean, - prevState: Readonly<State> - ) => { - const projects = more ? [...prevState.projects, ...data.projects] : data.projects; - - const newSelectedProjects = data.projects - .filter(project => project.selected) - .map(project => project.key); - const selectedProjects = more - ? [...prevState.selectedProjects, ...newSelectedProjects] - : newSelectedProjects; - - const disabledProjects = more ? [...prevState.disabledProjects] : []; - - return { - disabledProjects, - projects, - selectedProjects - }; - }; - - handleSelect = (projectKey: string) => { - return addProjectToApplication(this.props.application.key, projectKey).then(() => { - if (this.mounted) { - this.setState(state => { - const project = state.projects.find(p => p.key === projectKey); - if (project && this.props.onAddProject) { - this.props.onAddProject(project); - } - return { - needToReload: true, - selectedProjects: [...state.selectedProjects, projectKey] - }; - }); - } - }); - }; - - handleUnselect = (projectKey: string) => { - return removeProjectFromApplication(this.props.application.key, projectKey).then(() => { - if (this.mounted) { - this.setState(state => { - if (this.props.onRemoveProject) { - this.props.onRemoveProject(projectKey); - } - return { - needToReload: true, - selectedProjects: without(state.selectedProjects, projectKey) - }; - }); - } - }); - }; - - renderElement = (projectKey: string) => { - const project = find(this.state.projects, { key: projectKey }); - if (project === undefined) { - return ''; - } - - return ( - <div - className={classNames('views-project-item display-flex-center little-padded', { - 'bg-warning': !project.accessible - })}> - {!project.accessible ? ( - <Tooltip overlay={translate('application_console.project_inaccessible')}> - <WarningIcon className="spacer-right" /> - </Tooltip> - ) : ( - <QualifierIcon className="spacer-right" qualifier="TRK" /> - )} - <div> - <div title={project.name}>{project.name}</div> - <div className="note">{project.key}</div> - </div> - </div> - ); - }; - - render() { - const { projects, selectedProjects } = this.state; - - return ( - <SelectList - disabledElements={this.state.disabledProjects} - elements={projects.map(project => project.key)} - elementsTotalCount={this.state.projectsTotalCount} - needToReload={ - this.state.needToReload && - this.state.lastSearchParams && - this.state.lastSearchParams.filter !== SelectListFilter.All - } - onSearch={this.fetchProjects} - onSelect={this.handleSelect} - onUnselect={this.handleUnselect} - renderElement={this.renderElement} - selectedElements={selectedProjects} - withPaging={true} - /> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/BranchRowActions.tsx b/server/sonar-web/src/main/js/apps/application-console/BranchRowActions.tsx deleted file mode 100644 index c62245f90e2..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/BranchRowActions.tsx +++ /dev/null @@ -1,107 +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 { without } from 'lodash'; -import * as React from 'react'; -import { deleteApplicationBranch } from '../../api/application'; -import ActionsDropdown, { ActionsDropdownItem } from '../../components/controls/ActionsDropdown'; -import ConfirmButton from '../../components/controls/ConfirmButton'; -import { translate, translateWithParameters } from '../../helpers/l10n'; -import { Application } from '../../types/application'; -import CreateBranchForm from './CreateBranchForm'; -import { ApplicationBranch } from './utils'; - -interface Props { - application: Application; - branch: ApplicationBranch; - onUpdateBranches: (branches: Array<ApplicationBranch>) => void; -} - -interface State { - isUpdating: boolean; -} - -export default class BranchRowActions extends React.PureComponent<Props, State> { - state: State = { isUpdating: false }; - - handleDelete = () => { - const { application, branch } = this.props; - return deleteApplicationBranch(application.key, branch.name).then(() => { - this.props.onUpdateBranches(without(application.branches, branch)); - }); - }; - - handleUpdate = (newBranchName: string) => { - this.props.onUpdateBranches( - this.props.application.branches.map(branch => { - if (branch.name === this.props.branch.name) { - branch.name = newBranchName; - } - return branch; - }) - ); - }; - - handleCloseForm = () => { - this.setState({ isUpdating: false }); - }; - - handleUpdateClick = () => { - this.setState({ isUpdating: true }); - }; - - render() { - return ( - <> - <ConfirmButton - confirmButtonText={translate('delete')} - isDestructive={true} - modalBody={translateWithParameters( - 'application_console.branches.delete.warning_x', - this.props.branch.name - )} - modalHeader={translate('application_console.branches.delete')} - onConfirm={this.handleDelete}> - {({ onClick }) => ( - <ActionsDropdown> - <ActionsDropdownItem onClick={this.handleUpdateClick}> - {translate('edit')} - </ActionsDropdownItem> - <ActionsDropdownItem destructive={true} onClick={onClick}> - {translate('delete')} - </ActionsDropdownItem> - </ActionsDropdown> - )} - </ConfirmButton> - - {this.state.isUpdating && ( - <CreateBranchForm - application={this.props.application} - branch={this.props.branch} - enabledProjectsKey={this.props.application.projects - .filter(p => p.enabled) - .map(p => p.key)} - onClose={this.handleCloseForm} - onUpdate={this.handleUpdate} - /> - )} - </> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/BranchSelectItem.tsx b/server/sonar-web/src/main/js/apps/application-console/BranchSelectItem.tsx deleted file mode 100644 index 439bc4d742c..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/BranchSelectItem.tsx +++ /dev/null @@ -1,75 +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 Tooltip from '../../components/controls/Tooltip'; -import BranchIcon from '../../components/icons/BranchIcon'; - -export interface Option { - label: string; - type: string; - value: string; -} - -interface Props { - option: Option; - children?: React.ReactNode; - className?: string; - isFocused?: boolean; - onFocus: (option: Option, event: React.SyntheticEvent<HTMLElement>) => void; - onSelect: (option: Option, event: React.SyntheticEvent<HTMLElement>) => void; -} - -export default class BranchSelectItem extends React.PureComponent<Props> { - handleMouseDown = (event: React.MouseEvent<HTMLElement>) => { - event.preventDefault(); - event.stopPropagation(); - this.props.onSelect(this.props.option, event); - }; - - handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => { - this.props.onFocus(this.props.option, event); - }; - - handleMouseMove = (event: React.MouseEvent<HTMLElement>) => { - if (this.props.isFocused) { - return; - } - this.props.onFocus(this.props.option, event); - }; - - render() { - const { option } = this.props; - return ( - <Tooltip overlay={option.label} placement="left"> - <div - className={this.props.className} - onMouseDown={this.handleMouseDown} - onMouseEnter={this.handleMouseEnter} - onMouseMove={this.handleMouseMove} - role="listitem"> - <div> - <BranchIcon className="little-spacer-right" /> - {option.label} - </div> - </div> - </Tooltip> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/CreateBranchForm.tsx b/server/sonar-web/src/main/js/apps/application-console/CreateBranchForm.tsx deleted file mode 100644 index 8b25d018c77..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/CreateBranchForm.tsx +++ /dev/null @@ -1,303 +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 { some, without } from 'lodash'; -import * as React from 'react'; -import { - addApplicationBranch, - getApplicationDetails, - updateApplicationBranch -} from '../../api/application'; -import { ResetButtonLink, SubmitButton } from '../../components/controls/buttons'; -import SimpleModal from '../../components/controls/SimpleModal'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; -import MandatoryFieldMarker from '../../components/ui/MandatoryFieldMarker'; -import MandatoryFieldsExplanation from '../../components/ui/MandatoryFieldsExplanation'; -import { translate } from '../../helpers/l10n'; -import { Application, ApplicationProject } from '../../types/application'; -import ProjectBranchRow from './ProjectBranchRow'; -import { ApplicationBranch, SelectBranchOption } from './utils'; - -interface Props { - application: Application; - branch?: ApplicationBranch; - enabledProjectsKey: string[]; - onClose: () => void; - onCreate?: (branch: ApplicationBranch) => void; - onUpdate?: (name: string) => void; -} - -interface BranchesList { - [name: string]: SelectBranchOption | null; -} - -interface State { - loading: boolean; - name: string; - projects: ApplicationProject[]; - selected: string[]; - selectedBranches: BranchesList; -} - -const MAX_PROJECTS_HEIGHT = 220; -const PROJECT_HEIGHT = 22; -export default class CreateBranchForm extends React.PureComponent<Props, State> { - mounted = false; - node?: HTMLElement | null = null; - currentSelect?: HTMLElement | null = null; - - state: State = { - loading: false, - name: '', - projects: [], - selected: [], - selectedBranches: {} - }; - - componentDidMount() { - this.mounted = true; - const { application } = this.props; - const branch = this.props.branch ? this.props.branch.name : undefined; - this.setState({ loading: true }); - getApplicationDetails(application.key, branch).then( - ({ projects }) => { - if (this.mounted) { - const enabledProjects = projects.filter(p => - this.props.enabledProjectsKey.includes(p.key) - ); - const selected = enabledProjects.filter(p => p.selected).map(p => p.key); - const selectedBranches: BranchesList = {}; - enabledProjects.forEach(p => { - if (!p.enabled) { - selectedBranches[p.key] = null; - } else { - selectedBranches[p.key] = { - value: p.branch || '', - label: p.branch || '', - isMain: p.isMain || false - }; - } - }); - this.setState({ - name: branch || '', - selected, - loading: false, - projects: enabledProjects, - selectedBranches - }); - } - }, - () => { - this.props.onClose(); - } - ); - } - - componentWillUnmount() { - this.mounted = false; - } - - stopLoading = () => { - if (this.mounted) { - this.setState({ loading: false }); - } - }; - - canSubmit = () => { - const hasUnselectedBranches = some(this.state.selectedBranches, (branch, projectKey) => { - return !branch && this.state.selected.includes(projectKey); - }); - return ( - !this.state.loading && - this.state.name.length > 0 && - !hasUnselectedBranches && - this.state.selected.length > 0 - ); - }; - - handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { - this.setState({ name: event.currentTarget.value }); - }; - - handleFormSubmit = async () => { - const projectKeys = this.state.selected; - - const projectBranches = projectKeys.map(p => { - const branch = this.state.selectedBranches[p]; - return !branch || branch.isMain ? '' : branch.value; - }); - - if (this.props.branch) { - await updateApplicationBranch({ - application: this.props.application.key, - branch: this.props.branch.name, - name: this.state.name, - project: projectKeys, - projectBranch: projectBranches - }); - if (this.props.onUpdate) { - this.props.onUpdate(this.state.name); - } - } else { - await addApplicationBranch({ - application: this.props.application.key, - branch: this.state.name, - project: projectKeys, - projectBranch: projectBranches - }); - if (this.props.onCreate) { - this.props.onCreate({ name: this.state.name, isMain: false }); - } - } - this.props.onClose(); - }; - - handleProjectCheck = (checked: boolean, key: string) => { - this.setState(state => ({ - selected: checked ? [...state.selected, key] : without(state.selected, key) - })); - }; - - handleBranchChange = (projectKey: string, branch: SelectBranchOption) => { - this.setState(state => ({ - selectedBranches: { ...state.selectedBranches, [projectKey]: branch } - })); - }; - - handleSelectorClose = () => { - if (this.node) { - this.node.classList.add('selector-hidden'); - } - }; - - handleSelectorDirection = (selectNode: HTMLElement, elementCount: number) => { - if (this.node) { - const modalTop = this.node.getBoundingClientRect().top; - const modalHeight = this.node.offsetHeight; - const maxSelectHeight = Math.min(MAX_PROJECTS_HEIGHT, (elementCount + 1) * PROJECT_HEIGHT); - const selectBottom = selectNode.getBoundingClientRect().top + maxSelectHeight; - if (selectBottom > modalTop + modalHeight) { - this.node.classList.add('inverted-direction'); - } else { - this.node.classList.remove('inverted-direction'); - } - this.node.classList.remove('selector-hidden'); - } - }; - - renderProjectsList = () => { - return ( - <> - <strong className="spacer-left spacer-top"> - {translate('application_console.branches.configuration')} - </strong> - <p className="spacer-top big-spacer-bottom spacer-left spacer-right"> - {translate('application_console.branches.create.help')} - </p> - <table className="data zebra"> - <thead> - <tr> - <th className="thin" /> - <th className="thin">{translate('project')}</th> - <th>{translate('branch')}</th> - </tr> - </thead> - <tbody> - {this.state.projects.map(project => ( - <ProjectBranchRow - checked={this.state.selected.includes(project.key)} - key={project.key} - onChange={this.handleBranchChange} - onCheck={this.handleProjectCheck} - onClose={this.handleSelectorClose} - onOpen={this.handleSelectorDirection} - project={project} - /> - ))} - </tbody> - </table> - </> - ); - }; - - render() { - const isUpdating = this.props.branch !== undefined; - const header = translate('application_console.branches', isUpdating ? 'update' : 'create'); - return ( - <SimpleModal - header={header} - onClose={this.props.onClose} - onSubmit={this.handleFormSubmit} - size="medium"> - {({ onCloseClick, onFormSubmit, submitting }) => ( - <form className="views-form" onSubmit={onFormSubmit}> - <div className="modal-head"> - <h2>{header}</h2> - </div> - - <div - className="modal-body modal-container selector-hidden" - ref={node => (this.node = node)}> - {this.state.loading ? ( - <div className="text-center big-spacer-top big-spacer-bottom"> - <i className="spinner spacer-right" /> - </div> - ) : ( - <> - <MandatoryFieldsExplanation className="modal-field" /> - <div className="modal-field"> - <label htmlFor="view-edit-name"> - {translate('name')} - <MandatoryFieldMarker /> - </label> - <input - autoFocus={true} - className="input-super-large" - maxLength={250} - name="name" - onChange={this.handleInputChange} - size={50} - type="text" - value={this.state.name} - /> - </div> - {this.renderProjectsList()} - </> - )} - </div> - - <div className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> - <SubmitButton disabled={submitting || !this.canSubmit()}> - {translate( - 'application_console.branches', - isUpdating ? 'update' : 'create', - 'verb' - )} - </SubmitButton> - <ResetButtonLink onClick={onCloseClick}> - {translate('application_console.branches.cancel')} - </ResetButtonLink> - </div> - </form> - )} - </SimpleModal> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/EditForm.tsx b/server/sonar-web/src/main/js/apps/application-console/EditForm.tsx deleted file mode 100644 index 6e1cd3f2033..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/EditForm.tsx +++ /dev/null @@ -1,111 +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 { ResetButtonLink, SubmitButton } from '../../components/controls/buttons'; -import SimpleModal from '../../components/controls/SimpleModal'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; -import { translate } from '../../helpers/l10n'; -import { Application } from '../../types/application'; - -interface Props { - header: string; - onClose: () => void; - onEdit: (name: string, description: string) => Promise<void>; - application: Application; -} - -interface State { - description: string; - name: string; -} - -export default class EditForm extends React.PureComponent<Props, State> { - constructor(props: Props) { - super(props); - this.state = { - description: props.application.description || '', - name: props.application.name - }; - } - - handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => { - this.setState({ name: event.currentTarget.value }); - }; - - handleDescriptionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => { - this.setState({ description: event.currentTarget.value }); - }; - - handleFormSubmit = async () => { - await this.props.onEdit(this.state.name, this.state.description); - this.props.onClose(); - }; - - render() { - return ( - <SimpleModal - header={this.props.header} - onClose={this.props.onClose} - onSubmit={this.handleFormSubmit} - size="small"> - {({ onCloseClick, onFormSubmit, submitting }) => ( - <form onSubmit={onFormSubmit}> - <div className="modal-head"> - <h2>{this.props.header}</h2> - </div> - - <div className="modal-body"> - <div className="modal-field"> - <label htmlFor="view-edit-name">{translate('name')}</label> - <input - autoFocus={true} - id="view-edit-name" - maxLength={100} - name="name" - onChange={this.handleNameChange} - size={50} - type="text" - value={this.state.name} - /> - </div> - <div className="modal-field"> - <label htmlFor="view-edit-description">{translate('description')}</label> - <textarea - id="view-edit-description" - name="description" - onChange={this.handleDescriptionChange} - value={this.state.description} - /> - </div> - </div> - - <div className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> - <SubmitButton disabled={submitting || !this.state.name.length}> - {translate('save')} - </SubmitButton> - <ResetButtonLink onClick={onCloseClick}>{translate('cancel')}</ResetButtonLink> - </div> - </form> - )} - </SimpleModal> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/ProjectBranchRow.tsx b/server/sonar-web/src/main/js/apps/application-console/ProjectBranchRow.tsx deleted file mode 100644 index 936859b7cad..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/ProjectBranchRow.tsx +++ /dev/null @@ -1,138 +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 { orderBy } from 'lodash'; -import * as React from 'react'; -import { getBranches } from '../../api/branches'; -import Checkbox from '../../components/controls/Checkbox'; -import SelectLegacy from '../../components/controls/SelectLegacy'; -import Tooltip from '../../components/controls/Tooltip'; -import QualifierIcon from '../../components/icons/QualifierIcon'; -import DeferredSpinner from '../../components/ui/DeferredSpinner'; -import { ApplicationProject } from '../../types/application'; -import BranchSelectItem from './BranchSelectItem'; -import { ApplicationBranch, SelectBranchOption } from './utils'; - -interface Props { - checked: boolean; - onChange: (projectKey: string, branch: SelectBranchOption) => void; - onCheck: (checked: boolean, id?: string) => void; - onClose: () => void; - onOpen: (selectNode: HTMLElement, elementCount: number) => void; - project: ApplicationProject; -} - -interface State { - branches?: SelectBranchOption[]; - loading: boolean; - selectedBranch?: SelectBranchOption; -} - -export default class ProjectBranchRow extends React.PureComponent<Props, State> { - node?: HTMLElement | null = null; - mounted = false; - state: State = { loading: false }; - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - parseBranches = (branches: Array<ApplicationBranch>) => { - return orderBy(branches, [b => b.isMain, b => b.name]).map(branch => { - return { value: branch.name, label: branch.name, isMain: branch.isMain }; - }); - }; - - setCurrentTarget = (event: React.FocusEvent<HTMLInputElement>) => { - this.node = event.target; - }; - - handleChange = (value: SelectBranchOption) => { - this.props.onChange(this.props.project.key, value); - this.setState({ selectedBranch: value }); - }; - - handleOpen = () => { - if (this.state.branches && this.node) { - this.props.onOpen(this.node, this.state.branches.length); - return; - } - - const { project } = this.props; - this.setState({ loading: true }); - getBranches(project.key).then( - branchesResult => { - const branches = this.parseBranches(branchesResult); - if (this.node) { - this.props.onOpen(this.node, branches.length); - } - if (this.mounted) { - this.setState({ branches, loading: false }); - } - }, - () => { - /* Fail silently*/ - } - ); - }; - - render() { - const { checked, onCheck, onClose, project } = this.props; - const options = this.state.branches || [ - { value: project.branch, label: project.branch, isMain: project.isMain } - ]; - const value = project.enabled - ? this.state.selectedBranch || project.branch - : this.state.selectedBranch; - return ( - <tr key={project.key}> - <td className="text-center"> - <Checkbox checked={checked} id={project.key} onCheck={onCheck} /> - </td> - <td className="nowrap hide-overflow branch-name-row"> - <Tooltip overlay={project.name}> - <span> - <QualifierIcon qualifier="TRK" /> {project.name} - </span> - </Tooltip> - </td> - <td> - <SelectLegacy - className="width100" - clearable={false} - disabled={!checked} - onChange={this.handleChange} - onClose={onClose} - onFocus={this.setCurrentTarget} - onOpen={this.handleOpen} - optionComponent={BranchSelectItem} - options={options} - searchable={false} - value={value} - /> - <DeferredSpinner className="project-branch-row-spinner" loading={this.state.loading} /> - </td> - </tr> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationBranches-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationBranches-test.tsx deleted file mode 100644 index e332a2bb0f1..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationBranches-test.tsx +++ /dev/null @@ -1,65 +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 { mockApplication, mockApplicationProject } from '../../../helpers/mocks/application'; -import { mockBranch, mockMainBranch } from '../../../helpers/mocks/branch-like'; -import ApplicationBranches from '../ApplicationBranches'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect( - shallowRender({ - application: mockApplication({ projects: [mockApplicationProject({ enabled: true })] }) - }) - ).toMatchSnapshot('can create branches'); - expect(shallowRender({ canBrowseAllChildProjects: false })).toMatchSnapshot('readonly'); - const wrapper = shallowRender(); - wrapper.setState({ creating: true }); - expect(wrapper).toMatchSnapshot('creating branch'); -}); - -it('correctly triggers the onUpdateBranches prop', () => { - const onUpdateBranches = jest.fn(); - const branch = mockBranch(); - const branches = [mockMainBranch()]; - const wrapper = shallowRender({ application: mockApplication({ branches }), onUpdateBranches }); - const instance = wrapper.instance(); - - instance.handleCreateClick(); - expect(wrapper.state().creating).toBe(true); - - instance.handleCreateFormClose(); - expect(wrapper.state().creating).toBe(false); - - instance.handleCreate(branch); - expect(onUpdateBranches).toBeCalledWith([...branches, branch]); -}); - -function shallowRender(props: Partial<ApplicationBranches['props']> = {}) { - return shallow<ApplicationBranches>( - <ApplicationBranches - application={mockApplication()} - canBrowseAllChildProjects={true} - onUpdateBranches={jest.fn()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationConsoleApp-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationConsoleApp-test.tsx deleted file mode 100644 index f5957d8578d..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationConsoleApp-test.tsx +++ /dev/null @@ -1,136 +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 { - editApplication, - getApplicationDetails, - refreshApplication -} from '../../../api/application'; -import addGlobalSuccessMessage from '../../../app/utils/addGlobalSuccessMessage'; -import { mockApplication, mockApplicationProject } from '../../../helpers/mocks/application'; -import { mockLocation, mockRouter } from '../../../helpers/testMocks'; -import { waitAndUpdate } from '../../../helpers/testUtils'; -import { Application } from '../../../types/application'; -import ApplicationConsoleApp from '../ApplicationConsoleApp'; - -jest.mock('../../../api/application', () => ({ - getApplicationDetails: jest.fn().mockResolvedValue({}), - refreshApplication: jest.fn().mockResolvedValue({}), - editApplication: jest.fn().mockResolvedValue({}) -})); - -jest.mock('../../../app/utils/addGlobalSuccessMessage', () => jest.fn()); - -it('Should render correctly', async () => { - expect(shallowRender()).toMatchSnapshot('Empty app'); - const app = mockApplication(); - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot('With app'); - wrapper.setProps({ component: { key: '1', canBrowseAllChildProjects: true } }); - expect(wrapper).toMatchSnapshot('can browse all child projects'); -}); - -it('Should edit application correctly', async () => { - const app = mockApplication(); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockRejectedValueOnce(app); - let wrapper = shallowRender({}); - wrapper.instance().handleEdit('NEW_NAME', 'NEW_DESC'); - expect(wrapper.state().application).toBeUndefined(); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - wrapper = shallowRender({}); - await waitAndUpdate(wrapper); - await wrapper.instance().handleEdit('NEW_NAME', 'NEW_DESC'); - expect(editApplication).toBeCalledWith(app.key, 'NEW_NAME', 'NEW_DESC'); - expect(wrapper.state().application?.name).toBe('NEW_NAME'); - expect(wrapper.state().application?.description).toBe('NEW_DESC'); -}); - -it('Should add project to application', async () => { - const app = mockApplication(); - const project = mockApplicationProject({ key: 'FOO' }); - (getApplicationDetails as jest.Mock<Promise<Application>>).mockRejectedValueOnce(app); - let wrapper = shallowRender({}); - wrapper.instance().handleAddProject(project); - expect(wrapper.state().application?.projects).toBeUndefined(); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - wrapper = shallowRender({}); - await waitAndUpdate(wrapper); - wrapper.instance().handleAddProject(project); - expect(wrapper.state().application?.projects).toContain(project); -}); - -it('Should remove project from application', async () => { - const project = mockApplicationProject({ key: 'FOO' }); - const app = mockApplication({ projects: [project] }); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockRejectedValueOnce(app); - let wrapper = shallowRender({}); - wrapper.instance().handleRemoveProject('FOO'); - expect(wrapper.state().application?.projects).toBeUndefined(); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - wrapper = shallowRender({}); - await waitAndUpdate(wrapper); - wrapper.instance().handleRemoveProject('FOO'); - expect(wrapper.state().application?.projects.length).toBe(0); -}); - -it('Should update branch correctly', async () => { - const app = mockApplication(); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockRejectedValueOnce(app); - let wrapper = shallowRender({}); - wrapper.instance().handleUpdateBranches([]); - expect(wrapper.state().application).toBeUndefined(); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - wrapper = shallowRender({}); - await waitAndUpdate(wrapper); - wrapper.instance().handleUpdateBranches([]); - expect(wrapper.state().application?.branches.length).toBe(0); -}); - -it('should handle refreshing', async () => { - const app = mockApplication(); - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - const wrapper = shallowRender(); - await waitAndUpdate(wrapper); - wrapper.instance().handleRefreshClick(); - await waitAndUpdate(wrapper); - expect(refreshApplication).toBeCalledWith('foo'); - expect(addGlobalSuccessMessage).toBeCalled(); -}); - -function shallowRender(props: Partial<ApplicationConsoleApp['props']> = {}) { - return shallow<ApplicationConsoleApp>( - <ApplicationConsoleApp - component={{ key: '1' }} - location={mockLocation()} - router={mockRouter()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationConsoleAppRenderer-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationConsoleAppRenderer-test.tsx deleted file mode 100644 index 4ba7a59e833..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationConsoleAppRenderer-test.tsx +++ /dev/null @@ -1,61 +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 { mockApplication } from '../../../helpers/mocks/application'; -import { click } from '../../../helpers/testUtils'; -import ApplicationConsoleAppRenderer, { - ApplicationConsoleAppRendererProps -} from '../ApplicationConsoleAppRenderer'; -import EditForm from '../EditForm'; - -jest.mock('../../../app/utils/addGlobalSuccessMessage', () => jest.fn()); - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect( - shallowRender({ - application: mockApplication({ description: 'Foo bar', key: 'foo' }) - }) - ).toMatchSnapshot('can recompute'); - expect(shallowRender({ loading: true })).toMatchSnapshot('is loading'); -}); - -it('should handle editing', () => { - const wrapper = shallowRender(); - click(wrapper.find('#view-details-edit')); - expect(wrapper.find(EditForm)).toMatchSnapshot('edit form'); -}); - -function shallowRender(props: Partial<ApplicationConsoleAppRendererProps> = {}) { - return shallow( - <ApplicationConsoleAppRenderer - application={mockApplication({ key: 'foo' })} - canBrowseAllChildProjects={true} - loading={false} - onAddProject={jest.fn()} - onEdit={jest.fn()} - onRefresh={jest.fn()} - onRemoveProject={jest.fn()} - onUpdateBranches={jest.fn()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationProjectBranch-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationProjectBranch-test.tsx deleted file mode 100644 index c3fafcb7b39..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationProjectBranch-test.tsx +++ /dev/null @@ -1,44 +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 { mockApplication } from '../../../helpers/mocks/application'; -import { mockBranch, mockMainBranch } from '../../../helpers/mocks/branch-like'; -import ApplicationProjectBranch, { - ApplicationProjectBranchProps -} from '../ApplicationProjectBranch'; - -it('should render correctly', () => { - expect(shallowRender()).toMatchSnapshot('default'); - expect(shallowRender({ branch: mockMainBranch() })).toMatchSnapshot('main branch'); - expect(shallowRender({ readonly: true })).toMatchSnapshot('readonly'); -}); - -function shallowRender(props: Partial<ApplicationProjectBranchProps> = {}) { - return shallow<ApplicationProjectBranchProps>( - <ApplicationProjectBranch - application={mockApplication()} - branch={mockBranch()} - onUpdateBranches={jest.fn()} - readonly={false} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationProjects-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationProjects-test.tsx deleted file mode 100644 index 3ea49a97ba9..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/ApplicationProjects-test.tsx +++ /dev/null @@ -1,105 +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 { - addProjectToApplication, - getApplicationProjects, - removeProjectFromApplication -} from '../../../api/application'; -import SelectList, { SelectListFilter } from '../../../components/controls/SelectList'; -import { mockApplication } from '../../../helpers/mocks/application'; -import { waitAndUpdate } from '../../../helpers/testUtils'; -import ApplicationProjects from '../ApplicationProjects'; - -jest.mock('../../../api/application', () => ({ - getApplicationProjects: jest.fn().mockResolvedValue({ - paging: { pageIndex: 1, pageSize: 3, total: 55 }, - projects: [ - { key: 'test1', name: 'test1', accessible: true, selected: false }, - { - key: 'test2', - name: 'test2', - accessible: false, - selected: false, - disabled: true, - includedIn: 'foo' - }, - { key: 'test3', name: 'test3', accessible: true, selected: true } - ] - }), - addProjectToApplication: jest.fn().mockResolvedValue({}), - removeProjectFromApplication: jest.fn().mockResolvedValue({}) -})); - -beforeEach(jest.clearAllMocks); - -it('should render correctly in application mode', async () => { - const wrapper = shallowRender(); - wrapper - .find(SelectList) - .props() - .onSearch({ query: '', filter: SelectListFilter.Selected, page: 1, pageSize: 100 }); - await waitAndUpdate(wrapper); - - expect(wrapper).toMatchSnapshot(); - expect(wrapper.instance().renderElement('test1')).toMatchSnapshot('render project: basic'); - expect(wrapper.instance().renderElement('test2')).toMatchSnapshot('render project: inaccessible'); - expect(wrapper.instance().renderElement('cheeseburger')).toMatchInlineSnapshot(`""`); - - expect(getApplicationProjects).toHaveBeenCalledWith( - expect.objectContaining({ - application: 'foo', - p: 1, - ps: 100, - q: undefined, - selected: SelectListFilter.Selected - }) - ); - - wrapper.instance().handleSelect('test1'); - await waitAndUpdate(wrapper); - expect(addProjectToApplication).toHaveBeenCalledWith('foo', 'test1'); - - wrapper.instance().fetchProjects({ query: 'bar', filter: SelectListFilter.Selected }); - await waitAndUpdate(wrapper); - expect(getApplicationProjects).toHaveBeenCalledWith( - expect.objectContaining({ application: 'foo', q: 'bar', selected: SelectListFilter.Selected }) - ); - - wrapper.instance().handleUnselect('test1'); - await waitAndUpdate(wrapper); - expect(removeProjectFromApplication).toHaveBeenCalledWith('foo', 'test1'); -}); - -it('should refresh properly if props changes', () => { - const wrapper = shallowRender(); - const spy = jest.spyOn(wrapper.instance(), 'fetchProjects'); - - wrapper.setProps({ application: { key: 'bar' } as any }); - expect(wrapper.state().lastSearchParams.applicationKey).toBe('bar'); - expect(spy).toHaveBeenCalled(); -}); - -function shallowRender(props: Partial<ApplicationProjects['props']> = {}) { - return shallow<ApplicationProjects>( - <ApplicationProjects application={mockApplication()} {...props} /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/BranchRowActions-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/BranchRowActions-test.tsx deleted file mode 100644 index a6ce3013a19..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/BranchRowActions-test.tsx +++ /dev/null @@ -1,39 +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 { mockApplication } from '../../../helpers/mocks/application'; -import { mockBranch } from '../../../helpers/mocks/branch-like'; -import BranchRowActions from '../BranchRowActions'; - -it('Should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -function shallowRender(props: Partial<BranchRowActions['props']> = {}) { - return shallow<BranchRowActions>( - <BranchRowActions - application={mockApplication()} - branch={mockBranch()} - onUpdateBranches={jest.fn()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/BranchSelectItem-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/BranchSelectItem-test.tsx deleted file mode 100644 index 7bfb96e3cae..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/BranchSelectItem-test.tsx +++ /dev/null @@ -1,37 +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 BranchSelectItem from '../BranchSelectItem'; - -it('Should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -function shallowRender(props: Partial<BranchSelectItem['props']> = {}) { - return shallow<BranchSelectItem>( - <BranchSelectItem - option={{ label: 'test', type: 'type', value: 'value' }} - onFocus={jest.fn()} - onSelect={jest.fn()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/CreateBranchForm-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/CreateBranchForm-test.tsx deleted file mode 100644 index 91c441bb628..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/CreateBranchForm-test.tsx +++ /dev/null @@ -1,132 +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 { getApplicationDetails } from '../../../api/application'; -import { mockApplication, mockApplicationProject } from '../../../helpers/mocks/application'; -import { waitAndUpdate } from '../../../helpers/testUtils'; -import { Application } from '../../../types/application'; -import CreateBranchForm from '../CreateBranchForm'; - -jest.mock('../../../api/application', () => ({ - getApplicationDetails: jest.fn().mockResolvedValue({ projects: [] }), - addApplicationBranch: jest.fn(), - updateApplicationBranch: jest.fn() -})); - -it('Should handle submit correctly', async () => { - const app = mockApplication(); - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - const handleClose = jest.fn(); - const handleCeate = jest.fn(); - const handleUpdate = jest.fn(); - let wrapper = shallowRender({ application: app, onClose: handleClose, onCreate: handleCeate }); - wrapper.instance().handleFormSubmit(); - await waitAndUpdate(wrapper); - expect(handleClose).toHaveBeenCalled(); - expect(handleCeate).toHaveBeenCalled(); - - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - wrapper = shallowRender({ - application: app, - branch: { isMain: false, name: 'foo' }, - onUpdate: handleUpdate - }); - wrapper.instance().handleFormSubmit(); - await waitAndUpdate(wrapper); - expect(handleUpdate).toHaveBeenCalled(); -}); - -it('Should render correctly', async () => { - const app = mockApplication({ - projects: [ - mockApplicationProject({ key: '1', enabled: true }), - mockApplicationProject({ key: '2', enabled: true }), - mockApplicationProject({ key: '3', enabled: false }), - mockApplicationProject({ enabled: false }) - ] - }); - (getApplicationDetails as jest.Mock<Promise<Application>>).mockResolvedValueOnce(app); - const wrapper = shallowRender({ application: app, enabledProjectsKey: ['1', '3'] }); - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); -}); - -it('Should close when no response', async () => { - const app = mockApplication(); - (getApplicationDetails as jest.Mock<Promise<Application>>).mockRejectedValueOnce(app); - const handleClose = jest.fn(); - const wrapper = shallowRender({ application: app, onClose: handleClose }); - await waitAndUpdate(wrapper); - expect(handleClose).toHaveBeenCalled(); -}); - -it('Should update loading flag', () => { - const wrapper = shallowRender(); - wrapper.setState({ loading: true }); - wrapper.instance().stopLoading(); - expect(wrapper.state().loading).toBe(false); -}); - -it('Should update on input event', () => { - const wrapper = shallowRender(); - wrapper.setState({ name: '' }); - wrapper - .instance() - .handleInputChange(({ currentTarget: { value: 'bar' } } as any) as React.ChangeEvent< - HTMLInputElement - >); - expect(wrapper.state().name).toBe('bar'); -}); - -it('Should tell if it can submit correctly', () => { - const wrapper = shallowRender(); - wrapper.setState({ loading: true }); - expect(wrapper.instance().canSubmit()).toBe(false); - wrapper.setState({ loading: false, name: '' }); - expect(wrapper.instance().canSubmit()).toBe(false); - wrapper.setState({ - loading: false, - name: 'ok', - selectedBranches: { foo: null }, - selected: ['foo'] - }); - expect(wrapper.instance().canSubmit()).toBe(false); - wrapper.setState({ - loading: false, - name: 'ok', - selectedBranches: { foo: { label: 'foo', isMain: true, value: 'foo' } }, - selected: ['foo'] - }); - expect(wrapper.instance().canSubmit()).toBe(true); -}); - -function shallowRender(props: Partial<CreateBranchForm['props']> = {}) { - return shallow<CreateBranchForm>( - <CreateBranchForm - application={mockApplication()} - enabledProjectsKey={[]} - onClose={jest.fn()} - onCreate={jest.fn()} - onUpdate={jest.fn()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/EditForm-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/EditForm-test.tsx deleted file mode 100644 index d2b66b36351..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/EditForm-test.tsx +++ /dev/null @@ -1,61 +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 SimpleModal from '../../../components/controls/SimpleModal'; -import { mockApplication } from '../../../helpers/mocks/application'; -import { change, waitAndUpdate } from '../../../helpers/testUtils'; -import EditForm from '../EditForm'; - -it('should render correctly', () => { - expect( - shallowRender() - .find(SimpleModal) - .dive() - ).toMatchSnapshot(); -}); - -it('should correctly submit the new info', async () => { - const onClose = jest.fn(); - const onEdit = jest.fn(); - const wrapper = shallowRender({ onClose, onEdit }); - const modal = wrapper.find(SimpleModal).dive(); - - change(modal.find('#view-edit-name'), 'New name'); - change(modal.find('#view-edit-description'), 'New description'); - - wrapper.instance().handleFormSubmit(); - await waitAndUpdate(wrapper); - expect(onEdit).toBeCalledWith('New name', 'New description'); - expect(onClose).toBeCalled(); -}); - -function shallowRender(props: Partial<EditForm['props']> = {}) { - return shallow<EditForm>( - <EditForm - header="Edit" - onClose={jest.fn()} - onEdit={jest.fn()} - application={mockApplication()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/ProjectBranchRow-test.tsx b/server/sonar-web/src/main/js/apps/application-console/__tests__/ProjectBranchRow-test.tsx deleted file mode 100644 index b18f7674b59..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/ProjectBranchRow-test.tsx +++ /dev/null @@ -1,41 +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 { mockApplicationProject } from '../../../helpers/mocks/application'; -import ProjectBranchRow from '../ProjectBranchRow'; - -it('Should render correctly', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -function shallowRender(props: Partial<ProjectBranchRow['props']> = {}) { - return shallow<ProjectBranchRow>( - <ProjectBranchRow - checked={true} - onChange={jest.fn()} - onCheck={jest.fn()} - onOpen={jest.fn()} - onClose={jest.fn()} - project={mockApplicationProject()} - {...props} - /> - ); -} diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationBranches-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationBranches-test.tsx.snap deleted file mode 100644 index 39ee8f1edcc..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationBranches-test.tsx.snap +++ /dev/null @@ -1,217 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: can create branches 1`] = ` -<div - className="app-branches-console" -> - <div - className="boxed-group-actions" - > - <Button - disabled={false} - onClick={[Function]} - > - application_console.branches.create - </Button> - </div> - <h2 - className="text-limited big-spacer-top" - title="application_console.branches" - > - application_console.branches - </h2> - <p> - application_console.branches.help - </p> - <div - className="app-branches-list" - > - <table - className="data zebra" - > - <tbody> - <ApplicationProjectBranch - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "enabled": true, - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - branch={ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - } - } - key="branch-6.7" - onUpdateBranches={[MockFunction]} - readonly={false} - /> - </tbody> - </table> - </div> -</div> -`; - -exports[`should render correctly: creating branch 1`] = ` -<div - className="app-branches-console" -> - <div - className="boxed-group-actions" - > - <Button - disabled={true} - onClick={[Function]} - > - application_console.branches.create - </Button> - </div> - <h2 - className="text-limited big-spacer-top" - title="application_console.branches" - > - application_console.branches - </h2> - <p> - application_console.branches.help - </p> - <div - className="app-branches-list" - > - <p - className="text-center big-spacer-top" - > - application_console.branches.no_branches - </p> - </div> - <CreateBranchForm - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - enabledProjectsKey={ - Array [ - "bar", - ] - } - onClose={[Function]} - onCreate={[Function]} - /> -</div> -`; - -exports[`should render correctly: default 1`] = ` -<div - className="app-branches-console" -> - <div - className="boxed-group-actions" - > - <Button - disabled={true} - onClick={[Function]} - > - application_console.branches.create - </Button> - </div> - <h2 - className="text-limited big-spacer-top" - title="application_console.branches" - > - application_console.branches - </h2> - <p> - application_console.branches.help - </p> - <div - className="app-branches-list" - > - <p - className="text-center big-spacer-top" - > - application_console.branches.no_branches - </p> - </div> -</div> -`; - -exports[`should render correctly: readonly 1`] = ` -<div - className="app-branches-console" -> - <Alert - className="huge-spacer-top" - variant="warning" - > - application_console.branches.cannot_access_all_child_projects - </Alert> - <div - className="boxed-group-actions" - > - <Button - disabled={true} - onClick={[Function]} - > - application_console.branches.create - </Button> - </div> - <h2 - className="text-limited big-spacer-top" - title="application_console.branches" - > - application_console.branches - </h2> - <p> - application_console.branches.help - </p> - <div - className="app-branches-list" - > - <p - className="text-center big-spacer-top" - > - application_console.branches.no_branches - </p> - </div> -</div> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationConsoleApp-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationConsoleApp-test.tsx.snap deleted file mode 100644 index c92ad0958e4..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationConsoleApp-test.tsx.snap +++ /dev/null @@ -1,73 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly: Empty app 1`] = `""`; - -exports[`Should render correctly: With app 1`] = ` -<ApplicationConsoleAppRenderer - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - canBrowseAllChildProjects={false} - loading={false} - onAddProject={[Function]} - onEdit={[Function]} - onRefresh={[Function]} - onRemoveProject={[Function]} - onUpdateBranches={[Function]} -/> -`; - -exports[`Should render correctly: can browse all child projects 1`] = ` -<ApplicationConsoleAppRenderer - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - canBrowseAllChildProjects={true} - loading={false} - onAddProject={[Function]} - onEdit={[Function]} - onRefresh={[Function]} - onRemoveProject={[Function]} - onUpdateBranches={[Function]} -/> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationConsoleAppRenderer-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationConsoleAppRenderer-test.tsx.snap deleted file mode 100644 index 7af0e3d73f4..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationConsoleAppRenderer-test.tsx.snap +++ /dev/null @@ -1,265 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should handle editing: edit form 1`] = ` -<EditForm - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - header="application_console.edit" - onClose={[Function]} - onEdit={[MockFunction]} -/> -`; - -exports[`should render correctly: can recompute 1`] = ` -<div - className="page page-limited" -> - <div - className="boxed-group" - id="view-details" - > - <div - className="boxed-group-actions" - > - <Button - className="little-spacer-right" - id="view-details-edit" - onClick={[Function]} - > - edit - </Button> - <Button - className="little-spacer-right" - onClick={[MockFunction]} - > - application_console.recompute - </Button> - </div> - <header - className="boxed-group-header" - id="view-details-header" - > - <h2 - className="text-limited" - title="Foo" - > - Foo - </h2> - </header> - <div - className="boxed-group-inner" - id="view-details-content" - > - <div - className="big-spacer-bottom" - > - <div - className="little-spacer-bottom" - > - Foo bar - </div> - <div - className="subtitle" - > - key - : - foo - </div> - </div> - <ApplicationProjects - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "description": "Foo bar", - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - onAddProject={[MockFunction]} - onRemoveProject={[MockFunction]} - /> - <ApplicationBranches - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "description": "Foo bar", - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - canBrowseAllChildProjects={true} - onUpdateBranches={[MockFunction]} - /> - </div> - </div> -</div> -`; - -exports[`should render correctly: default 1`] = ` -<div - className="page page-limited" -> - <div - className="boxed-group" - id="view-details" - > - <div - className="boxed-group-actions" - > - <Button - className="little-spacer-right" - id="view-details-edit" - onClick={[Function]} - > - edit - </Button> - <Button - className="little-spacer-right" - onClick={[MockFunction]} - > - application_console.recompute - </Button> - </div> - <header - className="boxed-group-header" - id="view-details-header" - > - <h2 - className="text-limited" - title="Foo" - > - Foo - </h2> - </header> - <div - className="boxed-group-inner" - id="view-details-content" - > - <div - className="big-spacer-bottom" - > - <div - className="subtitle" - > - key - : - foo - </div> - </div> - <ApplicationProjects - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - onAddProject={[MockFunction]} - onRemoveProject={[MockFunction]} - /> - <ApplicationBranches - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - canBrowseAllChildProjects={true} - onUpdateBranches={[MockFunction]} - /> - </div> - </div> -</div> -`; - -exports[`should render correctly: is loading 1`] = ` -<i - className="spinner spacer" -/> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationProjectBranch-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationProjectBranch-test.tsx.snap deleted file mode 100644 index 4e1cbd90375..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationProjectBranch-test.tsx.snap +++ /dev/null @@ -1,83 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly: default 1`] = ` -<tr> - <td> - <BranchIcon - className="little-spacer-right" - /> - branch-6.7 - </td> - <td - className="thin nowrap" - > - <BranchRowActions - application={ - Object { - "branches": Array [ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - }, - ], - "key": "foo", - "name": "Foo", - "projects": Array [ - Object { - "branch": "master", - "isMain": true, - "key": "bar", - "name": "Bar", - }, - ], - "visibility": "private", - } - } - branch={ - Object { - "analysisDate": "2018-01-01", - "excludedFromPurge": true, - "isMain": false, - "name": "branch-6.7", - } - } - onUpdateBranches={[MockFunction]} - /> - </td> -</tr> -`; - -exports[`should render correctly: main branch 1`] = ` -<tr> - <td> - <BranchIcon - className="little-spacer-right" - /> - master - <span - className="badge spacer-left" - > - application_console.branches.main_branch - </span> - </td> - <td - className="thin nowrap" - /> -</tr> -`; - -exports[`should render correctly: readonly 1`] = ` -<tr> - <td> - <BranchIcon - className="little-spacer-right" - /> - branch-6.7 - </td> - <td - className="thin nowrap" - /> -</tr> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationProjects-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationProjects-test.tsx.snap deleted file mode 100644 index cfd64c1000d..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ApplicationProjects-test.tsx.snap +++ /dev/null @@ -1,75 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly in application mode 1`] = ` -<SelectList - disabledElements={Array []} - elements={ - Array [ - "test1", - "test2", - "test3", - ] - } - elementsTotalCount={55} - needToReload={false} - onSearch={[Function]} - onSelect={[Function]} - onUnselect={[Function]} - renderElement={[Function]} - selectedElements={ - Array [ - "test3", - ] - } - withPaging={true} -/> -`; - -exports[`should render correctly in application mode: render project: basic 1`] = ` -<div - className="views-project-item display-flex-center little-padded" -> - <QualifierIcon - className="spacer-right" - qualifier="TRK" - /> - <div> - <div - title="test1" - > - test1 - </div> - <div - className="note" - > - test1 - </div> - </div> -</div> -`; - -exports[`should render correctly in application mode: render project: inaccessible 1`] = ` -<div - className="views-project-item display-flex-center little-padded bg-warning" -> - <Tooltip - overlay="application_console.project_inaccessible" - > - <WarningIcon - className="spacer-right" - /> - </Tooltip> - <div> - <div - title="test2" - > - test2 - </div> - <div - className="note" - > - test2 - </div> - </div> -</div> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/BranchRowActions-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/BranchRowActions-test.tsx.snap deleted file mode 100644 index 7c1f10a8b4a..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/BranchRowActions-test.tsx.snap +++ /dev/null @@ -1,15 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly 1`] = ` -<Fragment> - <ConfirmButton - confirmButtonText="delete" - isDestructive={true} - modalBody="application_console.branches.delete.warning_x.branch-6.7" - modalHeader="application_console.branches.delete" - onConfirm={[Function]} - > - <Component /> - </ConfirmButton> -</Fragment> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/BranchSelectItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/BranchSelectItem-test.tsx.snap deleted file mode 100644 index a9878d576af..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/BranchSelectItem-test.tsx.snap +++ /dev/null @@ -1,22 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly 1`] = ` -<Tooltip - overlay="test" - placement="left" -> - <div - onMouseDown={[Function]} - onMouseEnter={[Function]} - onMouseMove={[Function]} - role="listitem" - > - <div> - <BranchIcon - className="little-spacer-right" - /> - test - </div> - </div> -</Tooltip> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/CreateBranchForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/CreateBranchForm-test.tsx.snap deleted file mode 100644 index 72322d18438..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/CreateBranchForm-test.tsx.snap +++ /dev/null @@ -1,12 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly 1`] = ` -<SimpleModal - header="application_console.branches.create" - onClose={[MockFunction]} - onSubmit={[Function]} - size="medium" -> - <Component /> -</SimpleModal> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/EditForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/EditForm-test.tsx.snap deleted file mode 100644 index 46f70be1267..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/EditForm-test.tsx.snap +++ /dev/null @@ -1,77 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -<Modal - contentLabel="Edit" - onRequestClose={[MockFunction]} - size="small" -> - <form - onSubmit={[Function]} - > - <div - className="modal-head" - > - <h2> - Edit - </h2> - </div> - <div - className="modal-body" - > - <div - className="modal-field" - > - <label - htmlFor="view-edit-name" - > - name - </label> - <input - autoFocus={true} - id="view-edit-name" - maxLength={100} - name="name" - onChange={[Function]} - size={50} - type="text" - value="Foo" - /> - </div> - <div - className="modal-field" - > - <label - htmlFor="view-edit-description" - > - description - </label> - <textarea - id="view-edit-description" - name="description" - onChange={[Function]} - value="" - /> - </div> - </div> - <div - className="modal-foot" - > - <DeferredSpinner - className="spacer-right" - loading={false} - /> - <SubmitButton - disabled={false} - > - save - </SubmitButton> - <ResetButtonLink - onClick={[Function]} - > - cancel - </ResetButtonLink> - </div> - </form> -</Modal> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ProjectBranchRow-test.tsx.snap b/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ProjectBranchRow-test.tsx.snap deleted file mode 100644 index 26bfbcbc76c..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/__tests__/__snapshots__/ProjectBranchRow-test.tsx.snap +++ /dev/null @@ -1,59 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Should render correctly 1`] = ` -<tr - key="bar" -> - <td - className="text-center" - > - <Checkbox - checked={true} - id="bar" - onCheck={[MockFunction]} - thirdState={false} - /> - </td> - <td - className="nowrap hide-overflow branch-name-row" - > - <Tooltip - overlay="Bar" - > - <span> - <QualifierIcon - qualifier="TRK" - /> - - Bar - </span> - </Tooltip> - </td> - <td> - <SelectLegacy - className="width100" - clearable={false} - disabled={false} - onChange={[Function]} - onClose={[MockFunction]} - onFocus={[Function]} - onOpen={[Function]} - optionComponent={[Function]} - options={ - Array [ - Object { - "isMain": true, - "label": "master", - "value": "master", - }, - ] - } - searchable={false} - /> - <DeferredSpinner - className="project-branch-row-spinner" - loading={false} - /> - </td> -</tr> -`; diff --git a/server/sonar-web/src/main/js/apps/application-console/routes.ts b/server/sonar-web/src/main/js/apps/application-console/routes.ts deleted file mode 100644 index 47601e1a1d3..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/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('./ApplicationConsoleApp')) } - } -]; - -export default routes; diff --git a/server/sonar-web/src/main/js/apps/application-console/utils.ts b/server/sonar-web/src/main/js/apps/application-console/utils.ts deleted file mode 100644 index 50e5feb581a..00000000000 --- a/server/sonar-web/src/main/js/apps/application-console/utils.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 { Branch } from '../../types/branch-like'; - -export interface SelectBranchOption { - value: string; - label: string; - isMain: boolean; -} - -export type ApplicationBranch = Pick<Branch, 'isMain' | 'name'>; diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx index 5e33911867b..300a07823de 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx @@ -50,7 +50,7 @@ it('should show form and callback when submitted - admin', async () => { await openAndSubmitForm(wrapper); expect(routerPush).toBeCalledWith({ - pathname: '/application/console', + pathname: '/project/admin/extension/developer-server/application-console', query: { id: 'new app' } diff --git a/server/sonar-web/src/main/js/helpers/mocks/application.ts b/server/sonar-web/src/main/js/helpers/mocks/application.ts index 104df2d4406..eb7089194cf 100644 --- a/server/sonar-web/src/main/js/helpers/mocks/application.ts +++ b/server/sonar-web/src/main/js/helpers/mocks/application.ts @@ -17,20 +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 { Application, ApplicationPeriod, ApplicationProject } from '../../types/application'; -import { Visibility } from '../../types/component'; -import { mockBranch } from './branch-like'; - -export function mockApplication(overrides: Partial<Application> = {}): Application { - return { - branches: [mockBranch()], - key: 'foo', - name: 'Foo', - projects: [mockApplicationProject()], - visibility: Visibility.Private, - ...overrides - }; -} +import { ApplicationPeriod } from '../../types/application'; export function mockApplicationPeriod( overrides: Partial<ApplicationPeriod> = {} @@ -42,15 +29,3 @@ export function mockApplicationPeriod( ...overrides }; } - -export function mockApplicationProject( - overrides: Partial<ApplicationProject> = {} -): ApplicationProject { - return { - branch: 'master', - isMain: true, - key: 'bar', - name: 'Bar', - ...overrides - }; -} diff --git a/server/sonar-web/src/main/js/helpers/urls.ts b/server/sonar-web/src/main/js/helpers/urls.ts index 1d3b88659b1..ee616508baa 100644 --- a/server/sonar-web/src/main/js/helpers/urls.ts +++ b/server/sonar-web/src/main/js/helpers/urls.ts @@ -78,7 +78,10 @@ export function getPortfolioAdminUrl(key: string) { } export function getApplicationAdminUrl(key: string) { - return { pathname: '/application/console', query: { id: key } }; + return { + pathname: '/project/admin/extension/developer-server/application-console', + query: { id: key } + }; } export function getComponentBackgroundTaskUrl( 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 8a5573e7201..71be2967cd2 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -556,27 +556,6 @@ visibility.private.description.long=Only members of the organization will be abl # #------------------------------------------------------------------------------ -application_console.edit=Edit Application -application_console.project_inaccessible=You do not have access to this project -application_console.branches=Application Branches -application_console.branches.cannot_access_all_child_projects=You must have access to all projects in this Application in order to administer branches. -application_console.branches.cancel=Cancel -application_console.branches.configuration=Branch configuration -application_console.branches.create=Create branch -application_console.branches.create.verb=Create -application_console.branches.create.help=For each project of your Application, choose a project branch that will be displayed inside the Application’s branch. -application_console.branches.delete=Delete branch -application_console.branches.delete.warning_x=Are you sure you want to delete "{0}" ? -application_console.branches.help=Track branches other than the main branch of this application's projects. -application_console.branches.main_branch=Main Branch -application_console.branches.update=Update branch -application_console.branches.update.verb=Update -application_console.branches.no_branches=No branches yet. You can create branches once projects are selected for this Application. -application_console.page=Edit Definition -application_console.delete_application=Delete Application -application_console.recompute=Recompute -application_console.refresh_started=Your application will be recomputed soon -application_console.do_you_want_to_delete=Are you sure that you want to delete "{0}"? application_settings.page=Application Settings application_settings.report=Application Report Settings application_settings.report.frequency=Application Reports Frequency |