diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2017-08-28 14:32:09 +0200 |
---|---|---|
committer | Janos Gyerik <janos.gyerik@sonarsource.com> | 2017-09-12 11:34:54 +0200 |
commit | f85b19f4aaefbb3e4a24ac1ae758da718f4f572b (patch) | |
tree | 95b8cd919c1b438e90ad54fd0da3d89a82f31cd0 /server/sonar-web/src | |
parent | 25140ec8ed74cc5ea5f50f05325f0d4a7f8753fd (diff) | |
download | sonarqube-f85b19f4aaefbb3e4a24ac1ae758da718f4f572b.tar.gz sonarqube-f85b19f4aaefbb3e4a24ac1ae758da718f4f572b.zip |
SONAR-9756 enable settings for long-living branches (#2438)
Diffstat (limited to 'server/sonar-web/src')
11 files changed, 121 insertions, 61 deletions
diff --git a/server/sonar-web/src/main/js/api/settings.ts b/server/sonar-web/src/main/js/api/settings.ts index fb579b166f8..ecadfadc87f 100644 --- a/server/sonar-web/src/main/js/api/settings.ts +++ b/server/sonar-web/src/main/js/api/settings.ts @@ -21,25 +21,22 @@ import { omitBy } from 'lodash'; import { getJSON, RequestData, post, postJSON } from '../helpers/request'; import { TYPE_PROPERTY_SET } from '../apps/settings/constants'; -export function getDefinitions(componentKey: string): Promise<any> { - const data: RequestData = {}; - if (componentKey) { - data.component = componentKey; - } - return getJSON('/api/settings/list_definitions', data).then(r => r.definitions); +export function getDefinitions(component: string | null, branch?: string): Promise<any> { + return getJSON('/api/settings/list_definitions', { branch, component }).then(r => r.definitions); } -export function getValues(keys: string, componentKey: string): Promise<any> { - const data: RequestData = { keys }; - if (componentKey) { - data.component = componentKey; - } - return getJSON('/api/settings/values', data).then(r => r.settings); +export function getValues(keys: string, component?: string, branch?: string): Promise<any> { + return getJSON('/api/settings/values', { keys, component, branch }).then(r => r.settings); } -export function setSettingValue(definition: any, value: any, componentKey: string): Promise<void> { +export function setSettingValue( + definition: any, + value: any, + component?: string, + branch?: string +): Promise<void> { const { key } = definition; - const data: RequestData = { key }; + const data: RequestData = { key, component, branch }; if (definition.multiValues) { data.values = value; @@ -51,19 +48,11 @@ export function setSettingValue(definition: any, value: any, componentKey: strin data.value = value; } - if (componentKey) { - data.component = componentKey; - } - return post('/api/settings/set', data); } -export function resetSettingValue(key: string, componentKey: string): Promise<void> { - const data: RequestData = { keys: key }; - if (componentKey) { - data.component = componentKey; - } - return post('/api/settings/reset', data); +export function resetSettingValue(key: string, component?: string, branch?: string): Promise<void> { + return post('/api/settings/reset', { keys: key, component, branch }); } export function sendTestEmail(to: string, subject: string, message: string): Promise<void> { diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.tsx index 3c1a4f512b7..c7ed8058de9 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.tsx @@ -23,7 +23,11 @@ import * as classNames from 'classnames'; import * as PropTypes from 'prop-types'; import { Branch, Component, ComponentExtension, ComponentConfiguration } from '../../../types'; import NavBarTabs from '../../../../components/nav/NavBarTabs'; -import { isShortLivingBranch, getBranchName } from '../../../../helpers/branches'; +import { + isShortLivingBranch, + getBranchName, + isLongLivingBranch +} from '../../../../helpers/branches'; import { translate } from '../../../../helpers/l10n'; const SETTINGS_URLS = [ @@ -173,7 +177,7 @@ export default class ComponentNavMenu extends React.PureComponent<Props> { } renderAdministration() { - if (!this.props.branch.isMain) { + if (isShortLivingBranch(this.props.branch)) { return null; } @@ -201,19 +205,21 @@ export default class ComponentNavMenu extends React.PureComponent<Props> { } renderAdministrationLinks() { - return [ - this.renderSettingsLink(), - this.renderBranchesLink(), - this.renderProfilesLink(), - this.renderQualityGateLink(), - this.renderCustomMeasuresLink(), - this.renderLinksLink(), - this.renderPermissionsLink(), - this.renderBackgroundTasksLink(), - this.renderUpdateKeyLink(), - ...this.renderAdminExtensions(), - this.renderDeletionLink() - ]; + return isLongLivingBranch(this.props.branch) + ? [this.renderSettingsLink()] + : [ + this.renderSettingsLink(), + this.renderBranchesLink(), + this.renderProfilesLink(), + this.renderQualityGateLink(), + this.renderCustomMeasuresLink(), + this.renderLinksLink(), + this.renderPermissionsLink(), + this.renderBackgroundTasksLink(), + this.renderUpdateKeyLink(), + ...this.renderAdminExtensions(), + this.renderDeletionLink() + ]; } renderSettingsLink() { @@ -223,7 +229,10 @@ export default class ComponentNavMenu extends React.PureComponent<Props> { return ( <li key="settings"> <Link - to={{ pathname: '/project/settings', query: { id: this.props.component.key } }} + to={{ + pathname: '/project/settings', + query: { branch: getBranchName(this.props.branch), id: this.props.component.key } + }} activeClassName="active"> {translate('project_settings.page')} </Link> diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.tsx b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.tsx index c69eda2ef7a..0c50f2de673 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.tsx @@ -77,7 +77,6 @@ it('should work for short-living branches', () => { isMain: false, mergeBranch: 'master', name: 'feature', - status: { bugs: 0, codeSmells: 2, vulnerabilities: 3 }, type: BranchType.SHORT }; const component = { key: 'foo', qualifier: 'TRK' } as Component; diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.tsx.snap index f406307cd81..a331e992eb6 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavMenu-test.tsx.snap @@ -93,6 +93,44 @@ exports[`should work for long-living branches 1`] = ` project_activity.page </Link> </li> + <li + className="dropdown" + > + <a + className="dropdown-toggle is-admin" + data-toggle="dropdown" + href="#" + id="component-navigation-admin" + > + layout.settings + + <i + className="icon-dropdown" + /> + </a> + <ul + className="dropdown-menu" + > + <li> + <Link + activeClassName="active" + onlyActiveOnIndex={false} + style={Object {}} + to={ + Object { + "pathname": "/project/settings", + "query": Object { + "branch": "release", + "id": "foo", + }, + } + } + > + project_settings.page + </Link> + </li> + </ul> + </li> </NavBarTabs> `; @@ -258,6 +296,7 @@ exports[`should work with extensions 1`] = ` Object { "pathname": "/project/settings", "query": Object { + "branch": undefined, "id": "foo", }, } @@ -479,6 +518,7 @@ exports[`should work with multiple extensions 1`] = ` Object { "pathname": "/project/settings", "query": Object { + "branch": undefined, "id": "foo", }, } diff --git a/server/sonar-web/src/main/js/apps/settings/components/App.js b/server/sonar-web/src/main/js/apps/settings/components/App.js index 704d742b4a2..793ca7370eb 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/App.js +++ b/server/sonar-web/src/main/js/apps/settings/components/App.js @@ -24,14 +24,16 @@ import PageHeader from './PageHeader'; import CategoryDefinitionsList from './CategoryDefinitionsList'; import AllCategoriesList from './AllCategoriesList'; import WildcardsHelp from './WildcardsHelp'; +import { getBranchName } from '../../../helpers/branches'; import { translate } from '../../../helpers/l10n'; import '../styles.css'; /*:: type Props = { + branch?: {}, component?: { key: string }, defaultCategory: ?string, - fetchSettings(componentKey: ?string): Promise<*>, + fetchSettings(componentKey: ?string, branch?: string): Promise<*>, location: { query: {} } }; */ @@ -52,13 +54,15 @@ export default class App extends React.PureComponent { html.classList.add('dashboard-page'); } const componentKey = this.props.component ? this.props.component.key : null; - this.props.fetchSettings(componentKey).then(() => this.setState({ loaded: true })); + const branch = this.props.branch && getBranchName(this.props.branch); + this.props.fetchSettings(componentKey, branch).then(() => this.setState({ loaded: true })); } componentDidUpdate(prevProps /*: Props*/) { if (prevProps.component !== this.props.component) { const componentKey = this.props.component ? this.props.component.key : null; - this.props.fetchSettings(componentKey); + const branch = this.props.branch && getBranchName(this.props.branch); + this.props.fetchSettings(componentKey, branch); } } @@ -77,21 +81,28 @@ export default class App extends React.PureComponent { const { query } = this.props.location; const selectedCategory = query.category || this.props.defaultCategory; + const branchName = this.props.branch && getBranchName(this.props.branch); + return ( <div id="settings-page" className="page page-limited"> <Helmet title={translate('settings.page')} /> - <PageHeader component={this.props.component} /> + <PageHeader branch={branchName} component={this.props.component} /> <div className="side-tabs-layout settings-layout"> <div className="side-tabs-side"> <AllCategoriesList + branch={branchName} component={this.props.component} selectedCategory={selectedCategory} defaultCategory={this.props.defaultCategory} /> </div> <div className="side-tabs-main"> - <CategoryDefinitionsList component={this.props.component} category={selectedCategory} /> + <CategoryDefinitionsList + branch={branchName} + component={this.props.component} + category={selectedCategory} + /> {selectedCategory === 'exclusions' && <WildcardsHelp />} </div> diff --git a/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js b/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js index 60365bb3562..b9f61bfc68c 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js @@ -32,6 +32,7 @@ type Category = { /*:: type Props = { + branch?: string, categories: Category[], component?: { key: string }, defaultCategory: string, @@ -43,7 +44,7 @@ export default class CategoriesList extends React.PureComponent { /*:: rops: Props; */ renderLink(category /*: Category */) { - const query = {}; + const query /*: Object */ = { branch: this.props.branch }; if (category.key !== this.props.defaultCategory) { query.category = category.key.toLowerCase(); diff --git a/server/sonar-web/src/main/js/apps/settings/components/Definition.js b/server/sonar-web/src/main/js/apps/settings/components/Definition.js index d064997d362..3ae60c1afcc 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/Definition.js +++ b/server/sonar-web/src/main/js/apps/settings/components/Definition.js @@ -47,6 +47,7 @@ class Definition extends React.PureComponent { /*:: timeout: number; */ static propTypes = { + branch: PropTypes.string, component: PropTypes.object, setting: PropTypes.object.isRequired, changedValue: PropTypes.any, @@ -90,7 +91,7 @@ class Definition extends React.PureComponent { const componentKey = this.props.component ? this.props.component.key : null; const { definition } = this.props.setting; return this.props - .resetValue(definition.key, componentKey) + .resetValue(definition.key, componentKey, this.props.branch) .then(() => { this.safeSetState({ success: true }); this.timeout = setTimeout(() => this.safeSetState({ success: false }), 3000); @@ -110,7 +111,7 @@ class Definition extends React.PureComponent { this.safeSetState({ success: false }); const componentKey = this.props.component ? this.props.component.key : null; this.props - .saveValue(this.props.setting.definition.key, componentKey) + .saveValue(this.props.setting.definition.key, componentKey, this.props.branch) .then(() => { this.safeSetState({ success: true }); this.timeout = setTimeout(() => this.safeSetState({ success: false }), 3000); diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js index 3df8d283c7d..2106bb54639 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js @@ -24,6 +24,7 @@ import Definition from './Definition'; export default class DefinitionsList extends React.PureComponent { static propTypes = { + branch: PropTypes.object, component: PropTypes.object, settings: PropTypes.array.isRequired }; @@ -33,7 +34,11 @@ export default class DefinitionsList extends React.PureComponent { <ul className="settings-definitions-list"> {this.props.settings.map(setting => <li key={setting.definition.key}> - <Definition component={this.props.component} setting={setting} /> + <Definition + branch={this.props.branch} + component={this.props.component} + setting={setting} + /> </li> )} </ul> diff --git a/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js b/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js index 394b607a715..4ae3b8fc858 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js @@ -24,6 +24,7 @@ import { translate } from '../../../helpers/l10n'; export default class PageHeader extends React.PureComponent { static propTypes = { + branch: PropTypes.string, component: PropTypes.object }; @@ -35,7 +36,9 @@ export default class PageHeader extends React.PureComponent { const description = this.props.component != null - ? translate('project_settings.page.description') + ? this.props.branch + ? translate('branch_settings.page.description') + : translate('project_settings.page.') : translate('settings.page.description'); return ( diff --git a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js index b8299136778..ca8443fbfc1 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js @@ -27,6 +27,7 @@ import { getSubCategoryName, getSubCategoryDescription } from '../utils'; export default class SubCategoryDefinitionsList extends React.PureComponent { static propTypes = { + branch: PropTypes.string, component: PropTypes.object, settings: PropTypes.array.isRequired }; @@ -63,8 +64,9 @@ export default class SubCategoryDefinitionsList extends React.PureComponent { dangerouslySetInnerHTML={{ __html: subCategory.description }} />} <DefinitionsList - settings={bySubCategory[subCategory.key]} + branch={this.props.branch} component={this.props.component} + settings={bySubCategory[subCategory.key]} /> {this.renderEmailForm(subCategory.key)} </li> diff --git a/server/sonar-web/src/main/js/apps/settings/store/actions.js b/server/sonar-web/src/main/js/apps/settings/store/actions.js index cbdd7eb63ba..25e75c2b3c3 100644 --- a/server/sonar-web/src/main/js/apps/settings/store/actions.js +++ b/server/sonar-web/src/main/js/apps/settings/store/actions.js @@ -34,13 +34,13 @@ import { isEmptyValue } from '../utils'; import { translate } from '../../../helpers/l10n'; import { getSettingsAppDefinition, getSettingsAppChangedValue } from '../../../store/rootReducer'; -export const fetchSettings = componentKey => dispatch => { - return getDefinitions(componentKey) +export const fetchSettings = (componentKey, branch) => dispatch => { + return getDefinitions(componentKey, branch) .then(definitions => { const withoutLicenses = definitions.filter(definition => definition.type !== 'LICENSE'); dispatch(receiveDefinitions(withoutLicenses)); const keys = withoutLicenses.map(definition => definition.key).join(); - return getValues(keys, componentKey); + return getValues(keys, componentKey, branch); }) .then(settings => { dispatch(receiveValues(settings, componentKey)); @@ -49,7 +49,7 @@ export const fetchSettings = componentKey => dispatch => { .catch(e => parseError(e).then(message => dispatch(addGlobalErrorMessage(message)))); }; -export const saveValue = (key, componentKey) => (dispatch, getState) => { +export const saveValue = (key, componentKey, branch) => (dispatch, getState) => { dispatch(startLoading(key)); const state = getState(); @@ -62,8 +62,8 @@ export const saveValue = (key, componentKey) => (dispatch, getState) => { return Promise.reject(); } - return setSettingValue(definition, value, componentKey) - .then(() => getValues(key, componentKey)) + return setSettingValue(definition, value, componentKey, branch) + .then(() => getValues(key, componentKey, branch)) .then(values => { dispatch(receiveValues(values, componentKey)); dispatch(cancelChange(key)); @@ -77,11 +77,11 @@ export const saveValue = (key, componentKey) => (dispatch, getState) => { }); }; -export const resetValue = (key, componentKey) => dispatch => { +export const resetValue = (key, componentKey, branch) => dispatch => { dispatch(startLoading(key)); - return resetSettingValue(key, componentKey) - .then(() => getValues(key, componentKey)) + return resetSettingValue(key, componentKey, branch) + .then(() => getValues(key, componentKey, branch)) .then(values => { if (values.length > 0) { dispatch(receiveValues(values, componentKey)); |