diff options
34 files changed, 1 insertions, 2465 deletions
diff --git a/server/sonar-web/src/main/js/api/measures.ts b/server/sonar-web/src/main/js/api/measures.ts index fa3bc649e2e..9c026aca57d 100644 --- a/server/sonar-web/src/main/js/api/measures.ts +++ b/server/sonar-web/src/main/js/api/measures.ts @@ -17,7 +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 { getJSON, post, postJSON } from 'sonar-ui-common/helpers/request'; +import { getJSON } from 'sonar-ui-common/helpers/request'; import throwGlobalError from '../app/utils/throwGlobalError'; import { BranchParameters } from '../types/branch-like'; import { @@ -82,36 +82,3 @@ export function getMeasuresForProjects( metricKeys: metricKeys.join() }).then(r => r.measures); } - -export function getCustomMeasures(data: { - f?: string; - p?: number; - projectKey: string; - ps?: number; -}): Promise<{ customMeasures: T.CustomMeasure[]; paging: T.Paging }> { - return getJSON('/api/custom_measures/search', data).then( - r => - ({ - customMeasures: r.customMeasures, - paging: { pageIndex: r.p, pageSize: r.ps, total: r.total } - } as any), - throwGlobalError - ); -} - -export function createCustomMeasure(data: { - description?: string; - metricKey: string; - projectKey: string; - value: string; -}): Promise<T.CustomMeasure> { - return postJSON('/api/custom_measures/create', data).catch(throwGlobalError); -} - -export function updateCustomMeasure(data: { description?: string; id: string; value?: string }) { - return post('/api/custom_measures/update', data).catch(throwGlobalError); -} - -export function deleteCustomMeasure(data: { id: string }) { - return post('/api/custom_measures/delete', data).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 d9b7212b918..c56114349b5 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 @@ -28,7 +28,6 @@ import NavBarTabs from 'sonar-ui-common/components/ui/NavBarTabs'; import { hasMessage, translate } from 'sonar-ui-common/helpers/l10n'; import { withAppState } from '../../../../components/hoc/withAppState'; import { getBranchLikeQuery, isPullRequest } from '../../../../helpers/branch-like'; -import { isSonarCloud } from '../../../../helpers/system'; import { getPortfolioUrl, getProjectQueryUrl } from '../../../../helpers/urls'; import { BranchLike, BranchParameters } from '../../../../types/branch-like'; import { ComponentQualifier, isPortfolioLike } from '../../../../types/component'; @@ -42,7 +41,6 @@ const SETTINGS_URLS = [ '/project/settings', '/project/quality_profiles', '/project/quality_gate', - '/custom_measures', '/project/links', '/project_roles', '/project/history', @@ -296,7 +294,6 @@ export class Menu extends React.PureComponent<Props> { ...this.renderAdminExtensions(query, isApplication), this.renderProfilesLink(query), this.renderQualityGateLink(query), - this.renderCustomMeasuresLink(query), this.renderLinksLink(query), this.renderPermissionsLink(query), this.renderBackgroundTasksLink(query), @@ -414,19 +411,6 @@ export class Menu extends React.PureComponent<Props> { ); }; - renderCustomMeasuresLink = (query: Query) => { - if (isSonarCloud() || !this.getConfiguration().showManualMeasures) { - return null; - } - return ( - <li key="custom_measures"> - <Link activeClassName="active" to={{ pathname: '/custom_measures', query }}> - {translate('custom_measures.page')} - </Link> - </li> - ); - }; - renderLinksLink = (query: Query) => { if (!this.getConfiguration().showLinks) { return null; diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx index 041b1707fa4..3c26c39a5cd 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx @@ -36,7 +36,6 @@ import backgroundTasksRoutes from '../../apps/background-tasks/routes'; import codeRoutes from '../../apps/code/routes'; import codingRulesRoutes from '../../apps/coding-rules/routes'; import componentMeasuresRoutes from '../../apps/component-measures/routes'; -import customMeasuresRoutes from '../../apps/custom-measures/routes'; import customMetricsRoutes from '../../apps/custom-metrics/routes'; import documentationRoutes from '../../apps/documentation/routes'; import groupsRoutes from '../../apps/groups/routes'; @@ -192,7 +191,6 @@ function renderComponentRoutes() { /> <RouteWithChildRoutes path="tutorials" childRoutes={tutorialsRoutes} /> <Route component={lazyLoadComponent(() => import('../components/ProjectAdminContainer'))}> - <RouteWithChildRoutes path="custom_measures" childRoutes={customMeasuresRoutes} /> <Route path="project/admin/extension/:pluginKey/:extensionKey" component={lazyLoadComponent(() => diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/App.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/App.tsx deleted file mode 100644 index f5d3c3aca08..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/App.tsx +++ /dev/null @@ -1,159 +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 { Helmet } from 'react-helmet-async'; -import ListFooter from 'sonar-ui-common/components/controls/ListFooter'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { - createCustomMeasure, - deleteCustomMeasure, - getCustomMeasures, - updateCustomMeasure -} from '../../../api/measures'; -import Suggestions from '../../../app/components/embed-docs-modal/Suggestions'; -import Header from './Header'; -import List from './List'; - -interface Props { - component: { key: string }; -} - -interface State { - loading: boolean; - measures?: T.CustomMeasure[]; - paging?: T.Paging; -} - -const PAGE_SIZE = 50; - -export default class App extends React.PureComponent<Props, State> { - mounted = false; - state: State = { loading: true }; - - componentDidMount() { - this.mounted = true; - this.fetchMeasures(); - } - - componentWillUnmount() { - this.mounted = false; - } - - fetchMeasures = () => { - this.setState({ loading: true }); - getCustomMeasures({ projectKey: this.props.component.key, ps: PAGE_SIZE }).then( - ({ customMeasures, paging }) => { - if (this.mounted) { - this.setState({ loading: false, measures: customMeasures, paging }); - } - }, - this.stopLoading - ); - }; - - fetchMore = () => { - const { paging } = this.state; - if (paging) { - this.setState({ loading: true }); - getCustomMeasures({ - projectKey: this.props.component.key, - p: paging.pageIndex + 1, - ps: PAGE_SIZE - }).then(({ customMeasures, paging }) => { - if (this.mounted) { - this.setState(({ measures = [] }: State) => ({ - loading: false, - measures: [...measures, ...customMeasures], - paging - })); - } - }, this.stopLoading); - } - }; - - stopLoading = () => { - if (this.mounted) { - this.setState({ loading: false }); - } - }; - - handleCreate = (data: { description: string; metricKey: string; value: string }) => { - return createCustomMeasure({ ...data, projectKey: this.props.component.key }).then(measure => { - if (this.mounted) { - this.setState(({ measures = [], paging }: State) => ({ - measures: [...measures, measure], - paging: paging && { ...paging, total: paging.total + 1 } - })); - } - }); - }; - - handleEdit = (data: { description: string; id: string; value: string }) => { - return updateCustomMeasure(data).then(() => { - if (this.mounted) { - this.setState(({ measures = [] }: State) => ({ - measures: measures.map(measure => - measure.id === data.id ? { ...measure, ...data } : measure - ) - })); - } - }); - }; - - handleDelete = (measureId: string) => { - return deleteCustomMeasure({ id: measureId }).then(() => { - if (this.mounted) { - this.setState(({ measures = [], paging }: State) => ({ - measures: measures.filter(measure => measure.id !== measureId), - paging: paging && { ...paging, total: paging.total - 1 } - })); - } - }); - }; - - render() { - const { loading, measures, paging } = this.state; - - return ( - <> - <Suggestions suggestions="custom_measures" /> - <Helmet title={translate('custom_measures.page')} /> - <div className="page page-limited"> - <Header - loading={loading} - onCreate={this.handleCreate} - skipMetrics={measures && measures.map(measure => measure.metric.key)} - /> - {measures && ( - <List measures={measures} onDelete={this.handleDelete} onEdit={this.handleEdit} /> - )} - {measures && paging && ( - <ListFooter - count={measures.length} - loadMore={this.fetchMore} - ready={!loading} - total={paging.total} - /> - )} - </div> - </> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/CreateButton.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/CreateButton.tsx deleted file mode 100644 index 6c8635de190..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/CreateButton.tsx +++ /dev/null @@ -1,74 +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 'sonar-ui-common/components/controls/buttons'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import Form from './Form'; - -interface Props { - onCreate: (data: { description: string; metricKey: string; value: string }) => Promise<void>; - skipMetrics: string[] | undefined; -} - -interface State { - modal: boolean; -} - -export default class CreateButton extends React.PureComponent<Props, State> { - mounted = false; - state: State = { modal: false }; - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - handleClick = () => { - this.setState({ modal: true }); - }; - - handleClose = () => { - if (this.mounted) { - this.setState({ modal: false }); - } - }; - - render() { - return ( - <> - <Button id="custom-measures-create" onClick={this.handleClick}> - {translate('create')} - </Button> - {this.state.modal && ( - <Form - confirmButtonText={translate('create')} - header={translate('custom_measures.create_custom_measure')} - onClose={this.handleClose} - onSubmit={this.props.onCreate} - skipMetrics={this.props.skipMetrics} - /> - )} - </> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/DeleteForm.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/DeleteForm.tsx deleted file mode 100644 index 4ebfaf2111e..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/DeleteForm.tsx +++ /dev/null @@ -1,63 +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 'sonar-ui-common/components/controls/buttons'; -import SimpleModal from 'sonar-ui-common/components/controls/SimpleModal'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; - -interface Props { - measure: T.CustomMeasure; - onClose: () => void; - onSubmit: () => Promise<void>; -} - -export default function DeleteForm({ measure, onClose, onSubmit }: Props) { - const header = translate('custom_measures.delete_custom_measure'); - - return ( - <SimpleModal header={header} onClose={onClose} onSubmit={onSubmit}> - {({ onCloseClick, onFormSubmit, submitting }) => ( - <form onSubmit={onFormSubmit}> - <header className="modal-head"> - <h2>{header}</h2> - </header> - - <div className="modal-body"> - {translateWithParameters( - 'custom_measures.delete_custom_measure.confirmation', - measure.metric.name - )} - </div> - - <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> - <SubmitButton className="button-red" disabled={submitting}> - {translate('delete')} - </SubmitButton> - <ResetButtonLink disabled={submitting} onClick={onCloseClick}> - {translate('cancel')} - </ResetButtonLink> - </footer> - </form> - )} - </SimpleModal> - ); -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx deleted file mode 100644 index 766f7ba9ae8..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/Form.tsx +++ /dev/null @@ -1,208 +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 'sonar-ui-common/components/controls/buttons'; -import Select from 'sonar-ui-common/components/controls/Select'; -import SimpleModal from 'sonar-ui-common/components/controls/SimpleModal'; -import { Alert } from 'sonar-ui-common/components/ui/Alert'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import MandatoryFieldMarker from 'sonar-ui-common/components/ui/MandatoryFieldMarker'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import { getAllMetrics } from '../../../api/metrics'; - -interface Props { - confirmButtonText: string; - header: string; - measure?: T.CustomMeasure; - onClose: () => void; - onSubmit: (data: { description: string; metricKey: string; value: string }) => Promise<void>; - skipMetrics?: string[]; -} - -interface State { - description: string; - loading: boolean; - metricKey?: string; - metrics?: T.Metric[]; - value: string; -} - -export default class Form extends React.PureComponent<Props, State> { - mounted = false; - - constructor(props: Props) { - super(props); - this.state = { - description: (props.measure && props.measure.description) || '', - loading: false, - metricKey: props.measure && props.measure.metric.key, - value: (props.measure && props.measure.value) || '' - }; - } - - componentDidMount() { - this.mounted = true; - if (!this.props.measure) { - this.fetchCustomMetrics(); - } - } - - componentWillUnmount() { - this.mounted = false; - } - - handleSubmit = () => { - return this.state.metricKey - ? this.props - .onSubmit({ - description: this.state.description, - metricKey: this.state.metricKey, - value: this.state.value - }) - .then(this.props.onClose) - : Promise.reject(undefined); - }; - - fetchCustomMetrics = () => { - this.setState({ loading: true }); - getAllMetrics({ isCustom: true }).then( - metrics => { - if (this.mounted) { - this.setState({ loading: false, metrics }); - } - }, - () => { - if (this.mounted) { - this.setState({ loading: false }); - } - } - ); - }; - - handleMetricSelect = ({ value }: { value: string }) => { - this.setState({ metricKey: value }); - }; - - handleDescriptionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => { - this.setState({ description: event.currentTarget.value }); - }; - - handleValueChange = (event: React.ChangeEvent<HTMLInputElement>) => { - this.setState({ value: event.currentTarget.value }); - }; - - renderMetricSelect = (options: { label: string; value: string }[]) => { - if (!options.length && !this.state.loading) { - return <Alert variant="warning">{translate('custom_measures.all_metrics_taken')}</Alert>; - } - return ( - <div className="modal-field"> - <label htmlFor="create-custom-measure-metric"> - {translate('custom_measures.metric')} - <MandatoryFieldMarker /> - </label> - {this.state.loading ? ( - <i className="spinner" /> - ) : ( - <Select - autoFocus={true} - clearable={false} - id="create-custom-measure-metric" - onChange={this.handleMetricSelect} - options={options} - value={this.state.metricKey} - /> - )} - </div> - ); - }; - - render() { - const { skipMetrics = [] } = this.props; - const { metrics = [] } = this.state; - const options = metrics - .filter(metric => !skipMetrics.includes(metric.key)) - .map(metric => ({ label: metric.name, value: metric.key })); - const forbidSubmitting = !this.props.measure && !options.length; - - return ( - <SimpleModal - header={this.props.header} - onClose={this.props.onClose} - onSubmit={this.handleSubmit} - size="small"> - {({ onCloseClick, onFormSubmit, submitting }) => ( - <form onSubmit={onFormSubmit}> - <header className="modal-head"> - <h2>{this.props.header}</h2> - </header> - - <div className="modal-body"> - {!this.props.measure && this.renderMetricSelect(options)} - - <div className="modal-field"> - <label htmlFor="create-custom-measure-value"> - {translate('value')} - <MandatoryFieldMarker /> - </label> - <input - autoFocus={this.props.measure !== undefined} - id="create-custom-measure-value" - maxLength={200} - name="value" - onChange={this.handleValueChange} - required={true} - type="text" - value={this.state.value} - /> - </div> - <div className="modal-field"> - <label htmlFor="create-custom-measure-description"> - {translate('description')} - </label> - <textarea - id="create-custom-measure-description" - name="description" - onChange={this.handleDescriptionChange} - value={this.state.description} - /> - </div> - </div> - - <footer className="modal-foot"> - <DeferredSpinner className="spacer-right" loading={submitting} /> - <SubmitButton - disabled={forbidSubmitting || submitting} - id="create-custom-measure-submit"> - {this.props.confirmButtonText} - </SubmitButton> - <ResetButtonLink - disabled={submitting} - id="create-custom-measure-cancel" - onClick={onCloseClick}> - {translate('cancel')} - </ResetButtonLink> - </footer> - </form> - )} - </SimpleModal> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx deleted file mode 100644 index 04bfe69f197..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/Header.tsx +++ /dev/null @@ -1,48 +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 { Alert } from 'sonar-ui-common/components/ui/Alert'; -import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import CreateButton from './CreateButton'; - -interface Props { - loading: boolean; - onCreate: (data: { description: string; metricKey: string; value: string }) => Promise<void>; - skipMetrics: string[] | undefined; -} - -export default function Header({ loading, onCreate, skipMetrics }: Props) { - return ( - <header className="page-header" id="custom-measures-header"> - <h1 className="page-title">{translate('custom_measures.page')}</h1> - <DeferredSpinner loading={loading} /> - <div className="page-actions"> - <CreateButton onCreate={onCreate} skipMetrics={skipMetrics} /> - </div> - <div className="page-description"> - <Alert display="inline" variant="error"> - {translate('custom_measures.deprecated')} - </Alert> - <p>{translate('custom_measures.page.description')}</p> - </div> - </header> - ); -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/Item.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/Item.tsx deleted file mode 100644 index 0b8f91cc92e..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/Item.tsx +++ /dev/null @@ -1,163 +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 ActionsDropdown, { - ActionsDropdownDivider, - ActionsDropdownItem -} from 'sonar-ui-common/components/controls/ActionsDropdown'; -import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; -import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n'; -import { formatMeasure } from 'sonar-ui-common/helpers/measures'; -import { isUserActive } from '../../../helpers/users'; -import DeleteForm from './DeleteForm'; -import Form from './Form'; -import MeasureDate from './MeasureDate'; - -interface Props { - measure: T.CustomMeasure; - onDelete: (measureId: string) => Promise<void>; - onEdit: (data: { description: string; id: string; value: string }) => Promise<void>; -} - -interface State { - deleteForm: boolean; - editForm: boolean; -} - -export default class Item extends React.PureComponent<Props, State> { - mounted = false; - state: State = { - deleteForm: false, - editForm: false - }; - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - handleEditClick = () => { - this.setState({ editForm: true }); - }; - - handleDeleteClick = () => { - this.setState({ deleteForm: true }); - }; - - closeEditForm = () => { - if (this.mounted) { - this.setState({ editForm: false }); - } - }; - - closeDeleteForm = () => { - if (this.mounted) { - this.setState({ deleteForm: false }); - } - }; - - handleEditFormSubmit = (data: { description: string; value: string }) => { - return this.props.onEdit({ id: this.props.measure.id, ...data }); - }; - - handleDeleteFormSubmit = () => { - return this.props.onDelete(this.props.measure.id); - }; - - render() { - const { measure } = this.props; - const userName = measure.user.name || measure.user.login; - - return ( - <tr data-metric={measure.metric.key}> - <td className="nowrap"> - <div> - <span className="js-custom-measure-metric-name">{measure.metric.name}</span> - {measure.pending && ( - <Tooltip overlay={translate('custom_measures.pending_tooltip')}> - <span className="js-custom-measure-pending badge badge-warning spacer-left"> - {translate('custom_measures.pending')} - </span> - </Tooltip> - )} - </div> - <span className="js-custom-measure-domain note">{measure.metric.domain}</span> - </td> - - <td className="nowrap"> - <strong className="js-custom-measure-value"> - {formatMeasure(measure.value, measure.metric.type)} - </strong> - </td> - - <td> - <span className="js-custom-measure-description">{measure.description}</span> - </td> - - <td> - <MeasureDate measure={measure} /> {translate('by_')}{' '} - <span className="js-custom-measure-user"> - {isUserActive(measure.user) - ? userName - : translateWithParameters('user.x_deleted', userName)} - </span> - </td> - - <td className="thin nowrap"> - <ActionsDropdown> - <ActionsDropdownItem - className="js-custom-measure-update" - onClick={this.handleEditClick}> - {translate('update_verb')} - </ActionsDropdownItem> - <ActionsDropdownDivider /> - <ActionsDropdownItem - className="js-custom-measure-delete" - destructive={true} - onClick={this.handleDeleteClick}> - {translate('delete')} - </ActionsDropdownItem> - </ActionsDropdown> - </td> - - {this.state.editForm && ( - <Form - confirmButtonText={translate('update_verb')} - header={translate('custom_measures.update_custom_measure')} - measure={this.props.measure} - onClose={this.closeEditForm} - onSubmit={this.handleEditFormSubmit} - /> - )} - - {this.state.deleteForm && ( - <DeleteForm - measure={this.props.measure} - onClose={this.closeDeleteForm} - onSubmit={this.handleDeleteFormSubmit} - /> - )} - </tr> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/List.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/List.tsx deleted file mode 100644 index 8653d64d7e4..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/List.tsx +++ /dev/null @@ -1,56 +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 { sortBy } from 'lodash'; -import * as React from 'react'; -import { translate } from 'sonar-ui-common/helpers/l10n'; -import Item from './Item'; - -interface Props { - measures: T.CustomMeasure[]; - onDelete: (measureId: string) => Promise<void>; - onEdit: (data: { description: string; id: string; value: string }) => Promise<void>; -} - -export default function List({ measures, onDelete, onEdit }: Props) { - return ( - <div className="boxed-group boxed-group-inner" id="custom-measures-list"> - {measures.length > 0 ? ( - <table className="data zebra zebra-hover"> - <thead> - <tr> - <th>{translate('custom_measures.metric')}</th> - <th>{translate('value')}</th> - <th>{translate('description')}</th> - <th>{translate('date')}</th> - <th /> - </tr> - </thead> - <tbody> - {sortBy(measures, measure => measure.metric.name.toLowerCase()).map(measure => ( - <Item key={measure.id} measure={measure} onDelete={onDelete} onEdit={onEdit} /> - ))} - </tbody> - </table> - ) : ( - <p>{translate('no_results')}</p> - )} - </div> - ); -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/MeasureDate.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/MeasureDate.tsx deleted file mode 100644 index 3f6de291c1f..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/MeasureDate.tsx +++ /dev/null @@ -1,50 +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 DateFormatter from 'sonar-ui-common/components/intl/DateFormatter'; -import { translate } from 'sonar-ui-common/helpers/l10n'; - -interface Props { - measure: T.CustomMeasure; -} - -export default function MeasureDate({ measure }: Props) { - if (measure.updatedAt) { - return ( - <> - {translate('updated_on')}{' '} - <span className="js-custom-measure-created-at"> - <DateFormatter date={measure.updatedAt} /> - </span> - </> - ); - } else if (measure.createdAt) { - return ( - <> - {translate('created_on')}{' '} - <span className="js-custom-measure-created-at"> - <DateFormatter date={measure.createdAt} /> - </span> - </> - ); - } else { - return <>{translate('created')}</>; - } -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/App-test.tsx deleted file mode 100644 index 55c39650389..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/App-test.tsx +++ /dev/null @@ -1,87 +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 { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import App from '../App'; - -jest.mock('../../../../api/measures', () => ({ - getCustomMeasures: () => - Promise.resolve({ - customMeasures: [ - { - createdAt: '2017-01-01', - description: 'my custom measure', - id: '1', - metric: { key: 'custom', name: 'custom-metric', type: 'STRING' }, - projectKey: 'foo', - user: { active: true, login: 'user', name: 'user' }, - value: 'custom-value' - } - ], - paging: { pageIndex: 1, pageSize: 1, total: 1 } - }), - createCustomMeasure: () => - Promise.resolve({ - createdAt: '2018-01-01', - description: 'description', - id: '2', - metric: { key: 'metricKey', name: 'Metric Name', type: 'STRING' }, - projectKey: 'foo', - user: { active: true, login: 'user', name: 'user' }, - value: 'value' - }), - updateCustomMeasure: () => Promise.resolve(), - deleteCustomMeasure: () => Promise.resolve() -})); - -it('should work', async () => { - const wrapper = shallow<App>(<App component={{ key: 'foo' }} />); - expect(wrapper).toMatchSnapshot(); - - await waitAndUpdate(wrapper); - expect(wrapper).toMatchSnapshot(); - - // create - wrapper.find('Header').prop<Function>('onCreate')({ - description: 'description', - metricKey: 'metricKey', - value: 'value' - }); - await waitAndUpdate(wrapper); - expect(wrapper.state().measures).toMatchSnapshot(); - expect(wrapper.state().paging!.total).toBe(2); - - // edit - wrapper.find('List').prop<Function>('onEdit')({ - description: 'another', - id: '2', - value: 'other' - }); - await waitAndUpdate(wrapper); - expect(wrapper.state().measures).toMatchSnapshot(); - expect(wrapper.state().paging!.total).toBe(2); - - // delete - wrapper.find('List').prop<Function>('onDelete')('2'); - await waitAndUpdate(wrapper); - expect(wrapper.state().measures).toMatchSnapshot(); - expect(wrapper.state().paging!.total).toBe(1); -}); diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/CreateButton-test.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/CreateButton-test.tsx deleted file mode 100644 index 5b799f8c2b4..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/CreateButton-test.tsx +++ /dev/null @@ -1,43 +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 { click } from 'sonar-ui-common/helpers/testUtils'; -import CreateButton from '../CreateButton'; - -it('should create new custom measure', () => { - const onCreate = jest.fn(() => Promise.resolve()); - const wrapper = shallow(<CreateButton onCreate={onCreate} skipMetrics={[]} />); - expect(wrapper).toMatchSnapshot(); - - click(wrapper.find('#custom-measures-create')); - expect(wrapper).toMatchSnapshot(); - - wrapper.find('Form').prop<Function>('onSubmit')({ - description: 'description', - metricKey: 'metricKey', - value: 'value' - }); - expect(onCreate).toBeCalledWith({ - description: 'description', - metricKey: 'metricKey', - value: 'value' - }); -}); diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/DeleteForm-test.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/DeleteForm-test.tsx deleted file mode 100644 index fbf1c61e1a2..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/DeleteForm-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 DeleteForm from '../DeleteForm'; - -it('should render', () => { - const measure = { - createdAt: '2017-01-01', - description: 'my custom measure', - id: '1', - metric: { key: 'custom', name: 'custom-metric', type: 'STRING' }, - projectKey: 'foo', - user: { active: true, login: 'user', name: 'user' }, - value: 'custom-value' - }; - expect( - shallow(<DeleteForm measure={measure} onClose={jest.fn()} onSubmit={jest.fn()} />).dive() - ).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Form-test.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Form-test.tsx deleted file mode 100644 index f8ca6c195f6..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Form-test.tsx +++ /dev/null @@ -1,67 +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 { change, click, submit, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; -import Form from '../Form'; - -jest.mock('../../../../api/metrics', () => ({ - getAllMetrics: () => - Promise.resolve([ - { id: '1', key: 'custom-metric', name: 'Custom Metric', type: 'STRING' }, - { id: '2', key: 'skipped-metric', name: 'Skipped Metric', type: 'FLOAT' } - ]) -})); - -it('should render form', async () => { - const onClose = jest.fn(); - const onSubmit = jest.fn(() => Promise.resolve()); - const wrapper = shallow( - <Form - confirmButtonText="confirmButtonText" - header="header" - onClose={onClose} - onSubmit={onSubmit} - skipMetrics={['skipped-metric']} - /> - ); - expect(wrapper.dive()).toMatchSnapshot(); - - await waitAndUpdate(wrapper); - const form = wrapper.dive(); - expect(form).toMatchSnapshot(); - - form.find('Select').prop<Function>('onChange')({ value: 'custom-metric' }); - change(form.find('[name="value"]'), 'Foo'); - change(form.find('[name="description"]'), 'bar'); - submit(form.find('form')); - expect(onSubmit).toBeCalledWith({ - description: 'bar', - metricKey: 'custom-metric', - value: 'Foo' - }); - - await new Promise(setImmediate); - expect(onClose).toBeCalled(); - - onClose.mockClear(); - click(form.find('ResetButtonLink')); - expect(onClose).toBeCalled(); -}); diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Header-test.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Header-test.tsx deleted file mode 100644 index 3d731c3ab2a..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Header-test.tsx +++ /dev/null @@ -1,35 +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 Header from '../Header'; - -it('should create new custom measure', () => { - const onCreate = jest.fn(() => Promise.resolve()); - const wrapper = shallow(<Header loading={false} onCreate={onCreate} skipMetrics={[]} />); - expect(wrapper).toMatchSnapshot(); - - wrapper.find('CreateButton').prop<Function>('onCreate')({ - description: 'bla', - metricKey: 'custom-metric', - name: 'Foo' - }); - expect(onCreate).toBeCalledWith({ description: 'bla', metricKey: 'custom-metric', name: 'Foo' }); -}); diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Item-test.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Item-test.tsx deleted file mode 100644 index 15eafa59285..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/Item-test.tsx +++ /dev/null @@ -1,73 +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 { click } from 'sonar-ui-common/helpers/testUtils'; -import Item from '../Item'; - -const measure = { - createdAt: '2017-01-01', - description: 'my custom measure', - id: '1', - metric: { key: 'custom', name: 'custom-metric', type: 'STRING' }, - projectKey: 'foo', - user: { active: true, login: 'user', name: 'user' }, - value: 'custom-value' -}; - -it('should render', () => { - expect(shallowRender()).toMatchSnapshot(); -}); - -it('should edit metric', () => { - const onEdit = jest.fn(); - const wrapper = shallowRender({ onEdit }); - - click(wrapper.find('.js-custom-measure-update')); - wrapper.update(); - - wrapper.find('Form').prop<Function>('onSubmit')({ - ...measure, - description: 'new-description', - value: 'new-value' - }); - expect(onEdit).toBeCalledWith({ ...measure, description: 'new-description', value: 'new-value' }); -}); - -it('should delete custom measure', () => { - const onDelete = jest.fn(); - const wrapper = shallowRender({ onDelete }); - - click(wrapper.find('.js-custom-measure-delete')); - wrapper.update(); - - wrapper.find('DeleteForm').prop<Function>('onSubmit')(); - expect(onDelete).toBeCalledWith('1'); -}); - -it('should render correctly for deleted user', () => { - expect( - shallowRender({ measure: { ...measure, user: { active: false, login: 'user' } } }) - ).toMatchSnapshot(); -}); - -function shallowRender(props: Partial<Item['props']> = {}) { - return shallow(<Item measure={measure} onDelete={jest.fn()} onEdit={jest.fn()} {...props} />); -} diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/List-test.tsx b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/List-test.tsx deleted file mode 100644 index e64d7baf434..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/List-test.tsx +++ /dev/null @@ -1,51 +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 List from '../List'; - -it('should render', () => { - const measures = [ - { - createdAt: '2017-01-01', - description: 'my custom measure', - id: '1', - metric: { key: 'custom', name: 'custom-metric', type: 'STRING' }, - projectKey: 'foo', - user: { active: true, login: 'user', name: 'user' }, - value: 'custom-value' - }, - { - createdAt: '2017-01-01', - id: '2', - metric: { key: 'another', name: 'another-metric', type: 'STRING' }, - projectKey: 'foo', - user: { active: true, login: 'user', name: 'user' }, - value: 'another-value' - } - ]; - expect( - shallow(<List measures={measures} onDelete={jest.fn()} onEdit={jest.fn()} />) - ).toMatchSnapshot(); -}); - -it('should render no results', () => { - expect(shallow(<List measures={[]} onDelete={jest.fn()} onEdit={jest.fn()} />)).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/App-test.tsx.snap deleted file mode 100644 index d58a7526a53..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/App-test.tsx.snap +++ /dev/null @@ -1,179 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should work 1`] = ` -<Fragment> - <Suggestions - suggestions="custom_measures" - /> - <Helmet - defer={true} - encodeSpecialCharacters={true} - title="custom_measures.page" - /> - <div - className="page page-limited" - > - <Header - loading={true} - onCreate={[Function]} - /> - </div> -</Fragment> -`; - -exports[`should work 2`] = ` -<Fragment> - <Suggestions - suggestions="custom_measures" - /> - <Helmet - defer={true} - encodeSpecialCharacters={true} - title="custom_measures.page" - /> - <div - className="page page-limited" - > - <Header - loading={false} - onCreate={[Function]} - skipMetrics={ - Array [ - "custom", - ] - } - /> - <List - measures={ - Array [ - Object { - "createdAt": "2017-01-01", - "description": "my custom measure", - "id": "1", - "metric": Object { - "key": "custom", - "name": "custom-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "custom-value", - }, - ] - } - onDelete={[Function]} - onEdit={[Function]} - /> - <ListFooter - count={1} - loadMore={[Function]} - ready={true} - total={1} - /> - </div> -</Fragment> -`; - -exports[`should work 3`] = ` -Array [ - Object { - "createdAt": "2017-01-01", - "description": "my custom measure", - "id": "1", - "metric": Object { - "key": "custom", - "name": "custom-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "custom-value", - }, - Object { - "createdAt": "2018-01-01", - "description": "description", - "id": "2", - "metric": Object { - "key": "metricKey", - "name": "Metric Name", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "value", - }, -] -`; - -exports[`should work 4`] = ` -Array [ - Object { - "createdAt": "2017-01-01", - "description": "my custom measure", - "id": "1", - "metric": Object { - "key": "custom", - "name": "custom-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "custom-value", - }, - Object { - "createdAt": "2018-01-01", - "description": "another", - "id": "2", - "metric": Object { - "key": "metricKey", - "name": "Metric Name", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "other", - }, -] -`; - -exports[`should work 5`] = ` -Array [ - Object { - "createdAt": "2017-01-01", - "description": "my custom measure", - "id": "1", - "metric": Object { - "key": "custom", - "name": "custom-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "custom-value", - }, -] -`; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/CreateButton-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/CreateButton-test.tsx.snap deleted file mode 100644 index 14027d6a4dc..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/CreateButton-test.tsx.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should create new custom measure 1`] = ` -<Fragment> - <Button - id="custom-measures-create" - onClick={[Function]} - > - create - </Button> -</Fragment> -`; - -exports[`should create new custom measure 2`] = ` -<Fragment> - <Button - id="custom-measures-create" - onClick={[Function]} - > - create - </Button> - <Form - confirmButtonText="create" - header="custom_measures.create_custom_measure" - onClose={[Function]} - onSubmit={[MockFunction]} - skipMetrics={Array []} - /> -</Fragment> -`; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/DeleteForm-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/DeleteForm-test.tsx.snap deleted file mode 100644 index 832e98a6d61..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/DeleteForm-test.tsx.snap +++ /dev/null @@ -1,45 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render 1`] = ` -<Modal - contentLabel="custom_measures.delete_custom_measure" - onRequestClose={[MockFunction]} -> - <form - onSubmit={[Function]} - > - <header - className="modal-head" - > - <h2> - custom_measures.delete_custom_measure - </h2> - </header> - <div - className="modal-body" - > - custom_measures.delete_custom_measure.confirmation.custom-metric - </div> - <footer - className="modal-foot" - > - <DeferredSpinner - className="spacer-right" - loading={false} - /> - <SubmitButton - className="button-red" - disabled={false} - > - delete - </SubmitButton> - <ResetButtonLink - disabled={false} - onClick={[Function]} - > - cancel - </ResetButtonLink> - </footer> - </form> -</Modal> -`; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Form-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Form-test.tsx.snap deleted file mode 100644 index 09df42c1d2c..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Form-test.tsx.snap +++ /dev/null @@ -1,198 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render form 1`] = ` -<Modal - contentLabel="header" - onRequestClose={[MockFunction]} - size="small" -> - <form - onSubmit={[Function]} - > - <header - className="modal-head" - > - <h2> - header - </h2> - </header> - <div - className="modal-body" - > - <div - className="modal-field" - > - <label - htmlFor="create-custom-measure-metric" - > - custom_measures.metric - <MandatoryFieldMarker /> - </label> - <i - className="spinner" - /> - </div> - <div - className="modal-field" - > - <label - htmlFor="create-custom-measure-value" - > - value - <MandatoryFieldMarker /> - </label> - <input - autoFocus={false} - id="create-custom-measure-value" - maxLength={200} - name="value" - onChange={[Function]} - required={true} - type="text" - value="" - /> - </div> - <div - className="modal-field" - > - <label - htmlFor="create-custom-measure-description" - > - description - </label> - <textarea - id="create-custom-measure-description" - name="description" - onChange={[Function]} - value="" - /> - </div> - </div> - <footer - className="modal-foot" - > - <DeferredSpinner - className="spacer-right" - loading={false} - /> - <SubmitButton - disabled={true} - id="create-custom-measure-submit" - > - confirmButtonText - </SubmitButton> - <ResetButtonLink - disabled={false} - id="create-custom-measure-cancel" - onClick={[Function]} - > - cancel - </ResetButtonLink> - </footer> - </form> -</Modal> -`; - -exports[`should render form 2`] = ` -<Modal - contentLabel="header" - onRequestClose={[MockFunction]} - size="small" -> - <form - onSubmit={[Function]} - > - <header - className="modal-head" - > - <h2> - header - </h2> - </header> - <div - className="modal-body" - > - <div - className="modal-field" - > - <label - htmlFor="create-custom-measure-metric" - > - custom_measures.metric - <MandatoryFieldMarker /> - </label> - <Select - autoFocus={true} - clearable={false} - id="create-custom-measure-metric" - onChange={[Function]} - options={ - Array [ - Object { - "label": "Custom Metric", - "value": "custom-metric", - }, - ] - } - /> - </div> - <div - className="modal-field" - > - <label - htmlFor="create-custom-measure-value" - > - value - <MandatoryFieldMarker /> - </label> - <input - autoFocus={false} - id="create-custom-measure-value" - maxLength={200} - name="value" - onChange={[Function]} - required={true} - type="text" - value="" - /> - </div> - <div - className="modal-field" - > - <label - htmlFor="create-custom-measure-description" - > - description - </label> - <textarea - id="create-custom-measure-description" - name="description" - onChange={[Function]} - value="" - /> - </div> - </div> - <footer - className="modal-foot" - > - <DeferredSpinner - className="spacer-right" - loading={false} - /> - <SubmitButton - disabled={false} - id="create-custom-measure-submit" - > - confirmButtonText - </SubmitButton> - <ResetButtonLink - disabled={false} - id="create-custom-measure-cancel" - onClick={[Function]} - > - cancel - </ResetButtonLink> - </footer> - </form> -</Modal> -`; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap deleted file mode 100644 index 6141a109096..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Header-test.tsx.snap +++ /dev/null @@ -1,38 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should create new custom measure 1`] = ` -<header - className="page-header" - id="custom-measures-header" -> - <h1 - className="page-title" - > - custom_measures.page - </h1> - <DeferredSpinner - loading={false} - /> - <div - className="page-actions" - > - <CreateButton - onCreate={[MockFunction]} - skipMetrics={Array []} - /> - </div> - <div - className="page-description" - > - <Alert - display="inline" - variant="error" - > - custom_measures.deprecated - </Alert> - <p> - custom_measures.page.description - </p> - </div> -</header> -`; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Item-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Item-test.tsx.snap deleted file mode 100644 index a763f649723..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/Item-test.tsx.snap +++ /dev/null @@ -1,176 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render 1`] = ` -<tr - data-metric="custom" -> - <td - className="nowrap" - > - <div> - <span - className="js-custom-measure-metric-name" - > - custom-metric - </span> - </div> - <span - className="js-custom-measure-domain note" - /> - </td> - <td - className="nowrap" - > - <strong - className="js-custom-measure-value" - > - custom-value - </strong> - </td> - <td> - <span - className="js-custom-measure-description" - > - my custom measure - </span> - </td> - <td> - <MeasureDate - measure={ - Object { - "createdAt": "2017-01-01", - "description": "my custom measure", - "id": "1", - "metric": Object { - "key": "custom", - "name": "custom-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "custom-value", - } - } - /> - - by_ - - <span - className="js-custom-measure-user" - > - user - </span> - </td> - <td - className="thin nowrap" - > - <ActionsDropdown> - <ActionsDropdownItem - className="js-custom-measure-update" - onClick={[Function]} - > - update_verb - </ActionsDropdownItem> - <ActionsDropdownDivider /> - <ActionsDropdownItem - className="js-custom-measure-delete" - destructive={true} - onClick={[Function]} - > - delete - </ActionsDropdownItem> - </ActionsDropdown> - </td> -</tr> -`; - -exports[`should render correctly for deleted user 1`] = ` -<tr - data-metric="custom" -> - <td - className="nowrap" - > - <div> - <span - className="js-custom-measure-metric-name" - > - custom-metric - </span> - </div> - <span - className="js-custom-measure-domain note" - /> - </td> - <td - className="nowrap" - > - <strong - className="js-custom-measure-value" - > - custom-value - </strong> - </td> - <td> - <span - className="js-custom-measure-description" - > - my custom measure - </span> - </td> - <td> - <MeasureDate - measure={ - Object { - "createdAt": "2017-01-01", - "description": "my custom measure", - "id": "1", - "metric": Object { - "key": "custom", - "name": "custom-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": false, - "login": "user", - }, - "value": "custom-value", - } - } - /> - - by_ - - <span - className="js-custom-measure-user" - > - user.x_deleted.user - </span> - </td> - <td - className="thin nowrap" - > - <ActionsDropdown> - <ActionsDropdownItem - className="js-custom-measure-update" - onClick={[Function]} - > - update_verb - </ActionsDropdownItem> - <ActionsDropdownDivider /> - <ActionsDropdownItem - className="js-custom-measure-delete" - destructive={true} - onClick={[Function]} - > - delete - </ActionsDropdownItem> - </ActionsDropdown> - </td> -</tr> -`; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/List-test.tsx.snap b/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/List-test.tsx.snap deleted file mode 100644 index 14d2a0c362d..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/__tests__/__snapshots__/List-test.tsx.snap +++ /dev/null @@ -1,90 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render 1`] = ` -<div - className="boxed-group boxed-group-inner" - id="custom-measures-list" -> - <table - className="data zebra zebra-hover" - > - <thead> - <tr> - <th> - custom_measures.metric - </th> - <th> - value - </th> - <th> - description - </th> - <th> - date - </th> - <th /> - </tr> - </thead> - <tbody> - <Item - key="2" - measure={ - Object { - "createdAt": "2017-01-01", - "id": "2", - "metric": Object { - "key": "another", - "name": "another-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "another-value", - } - } - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> - <Item - key="1" - measure={ - Object { - "createdAt": "2017-01-01", - "description": "my custom measure", - "id": "1", - "metric": Object { - "key": "custom", - "name": "custom-metric", - "type": "STRING", - }, - "projectKey": "foo", - "user": Object { - "active": true, - "login": "user", - "name": "user", - }, - "value": "custom-value", - } - } - onDelete={[MockFunction]} - onEdit={[MockFunction]} - /> - </tbody> - </table> -</div> -`; - -exports[`should render no results 1`] = ` -<div - className="boxed-group boxed-group-inner" - id="custom-measures-list" -> - <p> - no_results - </p> -</div> -`; diff --git a/server/sonar-web/src/main/js/apps/custom-measures/routes.ts b/server/sonar-web/src/main/js/apps/custom-measures/routes.ts deleted file mode 100644 index 854cd1ef120..00000000000 --- a/server/sonar-web/src/main/js/apps/custom-measures/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 'sonar-ui-common/components/lazyLoadComponent'; - -const routes = [ - { - indexRoute: { component: lazyLoadComponent(() => import('./components/App')) } - } -]; - -export default routes; diff --git a/server/sonar-web/src/main/js/types/types.d.ts b/server/sonar-web/src/main/js/types/types.d.ts index bb030129076..f76fc328fc5 100644 --- a/server/sonar-web/src/main/js/types/types.d.ts +++ b/server/sonar-web/src/main/js/types/types.d.ts @@ -136,7 +136,6 @@ declare namespace T { showBackgroundTasks?: boolean; showHistory?: boolean; showLinks?: boolean; - showManualMeasures?: boolean; showQualityGates?: boolean; showQualityProfiles?: boolean; showPermissions?: boolean; diff --git a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/custom/ws/example-metrics.json b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/custom/ws/example-metrics.json deleted file mode 100644 index bd9b178de79..00000000000 --- a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/custom/ws/example-metrics.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "metrics": [ - { - "id": "AU-Tpxb--iU5OvuD2FLy", - "key": "team_size", - "name": "Team size", - "description": "Number of people in the team", - "domain": "Management", - "type": "INT", - "direction": 0, - "qualitative": false, - "hidden": false, - "custom": true - }, - { - "id": "AU-Tpxb--iU5OvuD3FLz", - "key": "uncovered_lines", - "name": "Uncovered lines", - "description": "Uncovered lines", - "domain": "Tests", - "type": "INT", - "direction": 1, - "qualitative": true, - "hidden": false, - "custom": false - } - ] -} diff --git a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/custom/ws/example-search.json b/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/custom/ws/example-search.json deleted file mode 100644 index bfe0c9891d0..00000000000 --- a/server/sonar-webserver-webapi/src/main/resources/org/sonar/server/measure/custom/ws/example-search.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "customMeasures": [ - { - "description": "New arrivals", - "metric": { - "key": "team_size", - "name": "Team Size", - "domain": "Tests", - "type": "INT" - }, - "projectId": "project-uuid", - "projectKey": "project-key", - "pending": true, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Stan Smith" - }, - "value": "42" - }, - { - "description": "New funds", - "metric": { - "key": "burned_budget", - "name": "Burned Budget", - "domain": "Activity", - "type": "INT" - }, - "projectId": "project-uuid", - "projectKey": "project-key", - "pending": false, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Stan Smith" - }, - "value": "1000000" - }, - { - "description": "Great coverage", - "metric": { - "key": "uncovered_lines", - "name": "Uncovered lines", - "domain": "Code Coverage", - "type": "INT" - }, - "projectId": "project-uuid", - "projectKey": "project-key", - "pending": false, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Stan Smith" - }, - "value": "1" - } - ], - "p": 1, - "ps": 100, - "total": 3 -} diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/MetricsActionTest/metrics.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/MetricsActionTest/metrics.json deleted file mode 100644 index 2b089fa619e..00000000000 --- a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/MetricsActionTest/metrics.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "metrics": [ - { - "key": "custom-key-1", - "type": "INT", - "name": "custom-name-1", - "description": "custom-description-1", - "domain": "custom-domain-1", - "direction": 1, - "qualitative": false, - "hidden": false, - "custom": true - }, - { - "key": "custom-key-2", - "type": "INT", - "name": "custom-name-2", - "description": "custom-description-2", - "domain": "custom-domain-2", - "direction": -1, - "qualitative": true, - "hidden": true, - "custom": true - }, - { - "key": "custom-key-3", - "type": "INT", - "name": "custom-name-3", - "description": "custom-description-3", - "domain": "custom-domain-3", - "direction": 0, - "qualitative": false, - "hidden": false, - "custom": true - } - ] -} diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/custom-measures.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/custom-measures.json deleted file mode 100644 index 342ef9a3ec5..00000000000 --- a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/custom-measures.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "customMeasures": [ - { - "description": "description-1", - "metric": { - "key": "metric-key-1", - "name": "metric-key-1-name", - "domain": "metric-key-1-domain", - "type": "STRING" - }, - "projectId": "project-uuid", - "projectKey": "project-key", - "pending":true, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Login" - }, - "value": "text-value-1" - }, - { - "description": "description-2", - "metric": { - "key": "metric-key-2", - "name": "metric-key-2-name", - "domain": "metric-key-2-domain", - "type": "STRING" - }, - "projectId": "project-uuid", - "projectKey": "project-key", - "pending":true, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Login" - }, - "value": "text-value-2" - }, - { - "description": "description-3", - "metric": { - "key": "metric-key-3", - "name": "metric-key-3-name", - "domain": "metric-key-3-domain", - "type": "STRING" - }, - "projectId": "project-uuid", - "projectKey": "project-key", - "pending":true, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Login" - }, - "value": "text-value-3" - } - ], - "p": 1, - "ps": 100, - "total": 3 -} diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/empty.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/empty.json deleted file mode 100644 index 07b3a2950c2..00000000000 --- a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/SearchActionTest/empty.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "customMeasures": [ - ], - "p": 1, - "ps": 100, - "total": 0 -} diff --git a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/UpdateActionTest/custom-measure.json b/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/UpdateActionTest/custom-measure.json deleted file mode 100644 index d91f151cefa..00000000000 --- a/server/sonar-webserver-webapi/src/test/resources/org/sonar/server/measure/custom/ws/UpdateActionTest/custom-measure.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "projectId": "project-uuid", - "projectKey": "project-key", - "metric": { - "key": "metric-key", - "type": "STRING" - }, - "value": "new-text-measure-value", - "description": "new-custom-measure-description", - "pending":true, - "user": { - "active": true, - "email": "login@login.com", - "login": "login", - "name": "Login" - } -} diff --git a/sonar-ws-generator/src/main/resources/snapshot-of-api.json b/sonar-ws-generator/src/main/resources/snapshot-of-api.json index bf174e9153c..2a036eb3a85 100644 --- a/sonar-ws-generator/src/main/resources/snapshot-of-api.json +++ b/sonar-ws-generator/src/main/resources/snapshot-of-api.json @@ -873,203 +873,6 @@ ] }, { - "path": "api/custom_measures", - "since": "5.2", - "description": "Manage custom measures for a project. See also api/metrics.", - "actions": [ - { - "key": "create", - "description": "Create a custom measure.<br /> The project id or the project key must be provided (only project and module custom measures can be created). The metric id or the metric key must be provided.<br/>Requires 'Administer System' permission or 'Administer' permission on the project.", - "since": "5.2", - "internal": false, - "post": true, - "hasResponseExample": false, - "changelog": [], - "params": [ - { - "key": "description", - "description": "Description", - "required": false, - "internal": false, - "exampleValue": "Team size growing." - }, - { - "key": "metricId", - "description": "Metric id", - "required": false, - "internal": false, - "exampleValue": "16" - }, - { - "key": "metricKey", - "description": "Metric key", - "required": false, - "internal": false, - "exampleValue": "ncloc" - }, - { - "key": "projectId", - "description": "Project id", - "required": false, - "internal": false, - "exampleValue": "ce4c03d6-430f-40a9-b777-ad877c00aa4d" - }, - { - "key": "projectKey", - "description": "Project key", - "required": false, - "internal": false, - "exampleValue": "my_project" - }, - { - "key": "value", - "description": "Measure value. Value type depends on metric type:<ul><li>INT - type: integer</li><li>FLOAT - type: double</li><li>PERCENT - type: double</li><li>BOOL - the possible values are true or false</li><li>STRING - type: string</li><li>MILLISEC - type: integer</li><li>DATA - type: string</li><li>LEVEL - the possible values are OK, WARN, ERROR</li><li>DISTRIB - type: string</li><li>RATING - type: double</li><li>WORK_DUR - long representing the number of minutes</li></ul>", - "required": true, - "internal": false, - "exampleValue": "47" - } - ] - }, - { - "key": "delete", - "description": "Delete a custom measure.<br /> Requires 'Administer System' permission or 'Administer' permission on the project.", - "since": "5.2", - "internal": false, - "post": true, - "hasResponseExample": false, - "changelog": [], - "params": [ - { - "key": "id", - "description": "Id", - "required": true, - "internal": false, - "exampleValue": "24" - } - ] - }, - { - "key": "metrics", - "description": "List all custom metrics for which no custom measure already exists on a given project.<br /> The project id or project key must be provided.<br />Requires 'Administer System' permission or 'Administer' permission on the project.", - "since": "5.2", - "internal": true, - "post": false, - "hasResponseExample": true, - "changelog": [], - "params": [ - { - "key": "projectId", - "description": "Project id", - "required": false, - "internal": false, - "exampleValue": "ce4c03d6-430f-40a9-b777-ad877c00aa4d" - }, - { - "key": "projectKey", - "description": "Project key", - "required": false, - "internal": false, - "exampleValue": "my_project" - } - ] - }, - { - "key": "search", - "description": "List custom measures. The project id or project key must be provided.<br />Requires 'Administer System' permission or 'Administer' permission on the project.", - "since": "5.2", - "internal": false, - "post": false, - "hasResponseExample": true, - "changelog": [], - "params": [ - { - "key": "f", - "description": "Comma-separated list of the fields to be returned in response. All the fields are returned by default.", - "required": false, - "internal": false, - "possibleValues": [ - "projectId", - "projectKey", - "value", - "description", - "metric", - "createdAt", - "updatedAt", - "user", - "pending" - ] - }, - { - "key": "p", - "description": "1-based page number", - "required": false, - "internal": false, - "defaultValue": "1", - "exampleValue": "42", - "deprecatedKey": "pageIndex", - "deprecatedKeySince": "5.2" - }, - { - "key": "projectId", - "description": "Project id", - "required": false, - "internal": false, - "exampleValue": "ce4c03d6-430f-40a9-b777-ad877c00aa4d" - }, - { - "key": "projectKey", - "description": "Project key", - "required": false, - "internal": false, - "exampleValue": "my_project" - }, - { - "key": "ps", - "description": "Page size. Must be greater than 0 and less than 500", - "required": false, - "internal": false, - "defaultValue": "100", - "exampleValue": "20", - "deprecatedKey": "pageSize", - "deprecatedKeySince": "5.2", - "maximumValue": 500 - } - ] - }, - { - "key": "update", - "description": "Update a custom measure. Value and/or description must be provided<br />Requires 'Administer System' permission or 'Administer' permission on the project.", - "since": "5.2", - "internal": false, - "post": true, - "hasResponseExample": false, - "changelog": [], - "params": [ - { - "key": "description", - "required": false, - "internal": false, - "exampleValue": "Team size growing." - }, - { - "key": "id", - "description": "id", - "required": true, - "internal": false, - "exampleValue": "42" - }, - { - "key": "value", - "description": "Measure value. Value type depends on metric type:<ul><li>INT - type: integer</li><li>FLOAT - type: double</li><li>PERCENT - type: double</li><li>BOOL - the possible values are true or false</li><li>STRING - type: string</li><li>MILLISEC - type: integer</li><li>DATA - type: string</li><li>LEVEL - the possible values are OK, WARN, ERROR</li><li>DISTRIB - type: string</li><li>RATING - type: double</li><li>WORK_DUR - long representing the number of minutes</li></ul>", - "required": false, - "internal": false, - "exampleValue": "true" - } - ] - } - ] - }, - { "path": "api/duplications", "since": "4.4", "description": "Get duplication information for a project.", |