import AboutScanners from './AboutScanners';
import { searchProjects } from '../../../api/components';
import { getFacet } from '../../../api/issues';
-import { getCurrentUser, getSettingValue } from '../../../store/rootReducer';
+import { getAppState, getCurrentUser, getSettingValue } from '../../../store/rootReducer';
import { translate } from '../../../helpers/l10n';
import { fetchAboutPageSettings } from '../actions';
import AboutAppForSonarQubeDotCom from './AboutAppForSonarQubeDotCom';
mounted: boolean;
props: {
+ appState: {
+ defaultOrganization: string,
+ organizationsEnabled: boolean
+ },
currentUser: { isLoggedIn: boolean },
customText?: string,
fetchAboutPageSettings: () => Promise<*>,
if (sonarqubeDotCom && sonarqubeDotCom.value === 'true') {
return (
<AboutAppForSonarQubeDotCom
+ appState={this.props.appState}
bugs={bugs}
codeSmells={codeSmells}
currentUser={this.props.currentUser}
<AboutQualityGates />
</div>
<div className="flex-column flex-column-half about-page-group-boxes">
- <AboutStandards />
+ <AboutStandards appState={this.props.appState} />
</div>
</div>
}
const mapStateToProps = state => ({
+ appState: getAppState(state),
currentUser: getCurrentUser(state),
customText: getSettingValue(state, 'sonar.lf.aboutText'),
sonarqubeDotCom: getSettingValue(state, 'sonar.lf.sonarqube.com.enabled')
export default class AboutAppForSonarQubeDotCom extends React.Component {
props: {
+ appState: {
+ defaultOrganization: string,
+ organizationsEnabled: boolean
+ },
bugs: number,
codeSmells: number,
currentUser: { isLoggedIn: boolean },
</div>
</div>
- <AboutRulesForSonarQubeDotCom />
+ <AboutRulesForSonarQubeDotCom appState={this.props.appState} />
<div className="about-page-container">
{customText != null &&
<AboutQualityGates />
</div>
<div className="flex-column flex-column-half about-page-group-boxes">
- <AboutStandards />
+ <AboutStandards appState={this.props.appState} />
</div>
</div>
import { getRulesUrl } from '../../../helpers/urls';
export default class AboutRulesForSonarQubeDotCom extends React.Component {
+ props: {
+ appState: {
+ defaultOrganization: string,
+ organizationsEnabled: boolean
+ }
+ };
+
render() {
+ const organization = this.props.appState.defaultOrganization;
+
return (
<div className="sqcom-about-rules">
<div className="about-page-container">
- <Link to={getRulesUrl()} className="sqcom-about-rules-link">
+ <Link to={getRulesUrl(null, organization)} className="sqcom-about-rules-link">
+3,000 rules
<span className="spacer-left">
<svg width="15" height="36" viewBox="0 0 15 36">
</svg>
</span>
</Link>
- <Link to={getRulesUrl({ languages: 'js' })} className="sqcom-about-rules-link">
+ <Link
+ to={getRulesUrl({ languages: 'js' }, organization)}
+ className="sqcom-about-rules-link">
JavaScript
</Link>
- <Link to={getRulesUrl({ languages: 'java' })} className="sqcom-about-rules-link">
+ <Link
+ to={getRulesUrl({ languages: 'java' }, organization)}
+ className="sqcom-about-rules-link">
Java
</Link>
- <Link to={getRulesUrl({ languages: 'c,cpp' })} className="sqcom-about-rules-link">
+ <Link
+ to={getRulesUrl({ languages: 'c,cpp' }, organization)}
+ className="sqcom-about-rules-link">
C/C++
</Link>
- <Link to={getRulesUrl({ languages: 'cs' })} className="sqcom-about-rules-link">C#</Link>
- <Link to={getRulesUrl()} className="button">And More</Link>
+ <Link
+ to={getRulesUrl({ languages: 'cs' }, organization)}
+ className="sqcom-about-rules-link">
+ C#
+ </Link>
+ <Link to={getRulesUrl(null, organization)} className="button">And More</Link>
</div>
</div>
);
const owaspTags = 'owasp-a1,owasp-a2,owasp-a3,owasp-a4,owasp-a5,' +
'owasp-a6,owasp-a7,owasp-a8,owasp-a9,owasp-a10';
+const sans25Tags = 'sans-top25-porous,sans-top25-risky,sans-top25-insecure';
export default class AboutStandards extends React.Component {
+ props: {
+ appState: {
+ defaultOrganization: string,
+ organizationsEnabled: boolean
+ }
+ };
+
render() {
+ const organization = this.props.appState.organizationsEnabled
+ ? this.props.appState.defaultOrganization
+ : null;
+
return (
<div className="boxed-group">
<h2>{translate('about_page.standards')}</h2>
<div className="spacer-top">
<ul className="list-inline">
<li>
- <Link to={getRulesUrl({ tags: 'misra' })} className="link-with-icon">
+ <Link to={getRulesUrl({ tags: 'misra' }, organization)} className="link-with-icon">
<i className="icon-tags" />
<span className="little-spacer-left">MISRA</span>
</Link>
</li>
<li>
- <Link to={getRulesUrl({ tags: 'cert' })} className="link-with-icon">
+ <Link to={getRulesUrl({ tags: 'cert' }, organization)} className="link-with-icon">
<i className="icon-tags" />
<span className="little-spacer-left">CERT</span>
</Link>
</li>
<li>
- <Link to={getRulesUrl({ tags: 'cwe' })} className="link-with-icon">
+ <Link to={getRulesUrl({ tags: 'cwe' }, organization)} className="link-with-icon">
<i className="icon-tags" />
<span className="little-spacer-left">CWE</span>
</Link>
</li>
<li>
- <Link to={getRulesUrl({ tags: owaspTags })} className="link-with-icon">
+ <Link
+ to={getRulesUrl({ tags: owaspTags }, organization)}
+ className="link-with-icon">
<i className="icon-tags" />
<span className="little-spacer-left">OWASP Top 10</span>
</Link>
</li>
<li>
<Link
- to={getRulesUrl({
- tags: 'sans-top25-porous,sans-top25-risky,sans-top25-insecure'
- })}
+ to={getRulesUrl({ tags: sans25Tags }, organization)}
className="link-with-icon">
<i className="icon-tags" />
<span className="little-spacer-left">SANS Top 25</span>
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+// @flow
import React from 'react';
import init from '../init';
-export default class CodingRulesAppContainer extends React.Component {
+export default class CodingRulesAppContainer extends React.PureComponent {
+ stop: ?() => void;
+ props: {
+ params: {
+ organizationKey?: string
+ }
+ };
+
componentDidMount() {
- this.stop = init(this.refs.container);
+ this.stop = init(this.refs.container, this.props.params.organizationKey);
}
componentWillUnmount() {
- this.stop();
+ if (this.stop) {
+ this.stop();
+ }
}
render() {
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+// @flow
import $ from 'jquery';
import { sortBy } from 'lodash';
import Backbone from 'backbone';
const App = new Marionette.Application();
-App.on('start', function(el) {
- $.get(window.baseUrl + '/api/rules/app')
+App.on('start', function(options: { el: HTMLElement, organization: ?string }) {
+ const data = options.organization ? { organization: options.organization } : {};
+ $.get(window.baseUrl + '/api/rules/app', data)
.done(r => {
+ App.canCreateCustomRule = r.canCreateCustomRule;
+ App.canCustomizeRule = r.canCustomizeRule;
App.canWrite = r.canWrite;
+ App.organization = options.organization;
App.qualityProfiles = sortBy(r.qualityprofiles, ['name', 'lang']);
App.languages = { ...r.languages, none: 'None' };
App.qualityProfiles.forEach(profile => {
App.statuses = r.statuses;
})
.done(() => {
- this.layout = new Layout({ el });
+ this.layout = new Layout({ el: options.el });
this.layout.render();
$('#footer').addClass('search-navigator-footer');
});
this.layout.filtersRegion.show(this.filtersView);
- key.setScope('list');
+ window.key.setScope('list');
this.router = new Router({
app: this
});
});
});
-export default function(el) {
- App.start(el);
+export default function(el: HTMLElement, organization: ?string) {
+ App.start({ el, organization });
return () => {
+ // $FlowFixMe
Backbone.history.stop();
App.layout.destroy();
$('#footer').removeClass('search-navigator-footer');
serializeData() {
const isCustom = this.model.has('templateKey');
- const isEditable = this.options.app.canWrite && isCustom;
+ const isEditable = this.options.app.canCustomizeRule && isCustom;
let qualityProfilesVisible = true;
if (this.model.get('isTemplate')) {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
isEditable,
qualityProfilesVisible,
- canWrite: this.options.app.canWrite,
allTags: union(this.model.get('sysTags'), this.model.get('tags'))
};
}
serializeData() {
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
- canWrite: this.options.app.canWrite,
+ canDeleteCustomRule: this.options.app.canCreateCustomRule,
templateRule: this.options.templateRule,
permalink: window.baseUrl + '/coding_rules/#rule_key=' + encodeURIComponent(this.model.id)
};
serializeData() {
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
- canWrite: this.options.app.canWrite
+ canCreateCustomRule: this.options.app.canCreateCustomRule
};
}
});
},
serializeData() {
- const isEditable = this.options.app.canWrite && this.model.get('isCustom');
-
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
- isEditable,
- canWrite: this.options.app.canWrite
+ isCustom: this.model.get('isCustom'),
+ canCustomizeRule: this.options.app.canCustomizeRule
};
}
});
import $ from 'jquery';
import Marionette from 'backbone.marionette';
import Template from '../templates/rule/coding-rules-rule-issues.hbs';
+import { getComponentIssuesUrl } from '../../../helpers/urls';
export default Marionette.ItemView.extend({
template: Template,
},
requestIssues() {
- const that = this;
const url = window.baseUrl + '/api/issues/search';
const options = {
rules: this.model.id,
ps: 1,
facets: 'projectUuids'
};
+ const { organization } = this.options.app;
+ if (organization) {
+ Object.assign(options, { organization });
+ }
return $.get(url, options).done(r => {
const projectsFacet = r.facets.find(facet => facet.property === 'projectUuids');
let projects = projectsFacet != null ? projectsFacet.values : [];
const projectBase = r.components.find(component => component.uuid === project.val);
return {
...project,
- name: projectBase != null ? projectBase.longName : ''
+ name: projectBase != null ? projectBase.longName : '',
+ issuesUrl: projectBase != null &&
+ getComponentIssuesUrl(projectBase.key, {
+ resolved: 'false',
+ rules: this.model.id
+ })
};
});
- that.projects = projects;
- that.total = r.total;
+ this.projects = projects;
+ this.total = r.total;
});
},
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
total: this.total,
- projects: this.projects,
- baseSearchUrl: window.baseUrl +
- '/issues/search#resolved=false|rules=' +
- encodeURIComponent(this.model.id)
+ projects: this.projects
};
}
});
},
serializeData() {
+ const permalinkPath = this.options.app.organization
+ ? `/organizations/${this.options.app.organization}/rules`
+ : '/coding_rules';
+
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
- canWrite: this.options.app.canWrite,
+ canCustomizeRule: this.options.app.canCustomizeRule,
allTags: union(this.model.get('sysTags'), this.model.get('tags')),
- permalink: window.baseUrl + '/coding_rules#rule_key=' + encodeURIComponent(this.model.id)
+ permalink: window.baseUrl + permalinkPath + '#rule_key=' + encodeURIComponent(this.model.id)
};
}
});
onRender() {
const params = this.model.get('params');
this.$el.toggleClass('hidden', params == null || params.length === 0);
- },
-
- serializeData() {
- const isEditable = this.options.app.canWrite && this.model.get('isCustom');
-
- return {
- ...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
- isEditable,
- canWrite: this.options.app.canWrite
- };
}
});
const myProfile = this.options.app.qualityProfiles.find(
p => p.key === this.model.get('qProfile')
);
+ if (!myProfile) {
+ return null;
+ }
const parentKey = myProfile.parentKey;
const parent = { ...this.options.app.qualityProfiles.find(p => p.key === parentKey) };
const parentActiveInfo = this.model.collection.findWhere({ qProfile: parentKey }) ||
});
},
+ getProfilePath(profileKey) {
+ const { organization } = this.options.app;
+ const encodedKey = encodeURIComponent(profileKey);
+ return organization
+ ? `${window.baseUrl}/organizations/${organization}/quality_profiles/show?key=${encodedKey}`
+ : `${window.baseUrl}/profiles/show?key=${encodedKey}`;
+ },
+
serializeData() {
+ const parent = this.getParent();
+
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
+ parent,
canWrite: this.options.app.canWrite,
- parent: this.getParent(),
parameters: this.enhanceParameters(),
templateKey: this.options.rule.get('templateKey'),
- isTemplate: this.options.rule.get('isTemplate')
+ isTemplate: this.options.rule.get('isTemplate'),
+ profilePath: this.getProfilePath(this.model.get('key')),
+ parentProfilePath: parent && this.getProfilePath(parent.key)
};
}
});
</td>
-{{#if canWrite}}
+{{#if canDeleteCustomRule}}
<td class="coding-rules-detail-list-actions">
<div class="button-group">
<button class="js-delete-custom-rule button-red">
<h3 class="coding-rules-detail-title">{{t 'coding_rules.custom_rules'}}</h3>
- {{#if canWrite}}
+ {{#if canCreateCustomRule}}
<div class="button-group coding-rules-detail-quality-profiles-activation">
<button class="js-create-custom-rule">{{t 'coding_rules.create'}}</button>
</div>
<div class="coding-rules-detail-description rule-desc markdown">{{{htmlDesc}}}</div>
-{{#unless isEditable}}
+{{#unless isCustom}}
<div class="coding-rules-detail-description coding-rules-detail-description-extra">
<div id="coding-rules-detail-description-extra">
{{#if htmlNote}}
<div class="rule-desc spacer-bottom markdown">{{{htmlNote}}}</div>
{{/if}}
- {{#if canWrite}}
+ {{#if canCustomizeRule}}
<div class="button-group">
<button id="coding-rules-detail-extend-description">{{t 'coding_rules.extend_description'}}</button>
</div>
{{/if}}
</div>
- {{#if canWrite}}
+ {{#if canCustomizeRule}}
<div class="coding-rules-detail-extend-description-form hidden">
<table class="width100">
<tbody>
<div class="coding-rule-section-separator"></div>
<h3 class="coding-rules-detail-title">
- {{t 'coding_rules.issues'}} (<a class="js-rule-issues" href="{{baseSearchUrl}}">{{total}}</a>)
+ {{t 'coding_rules.issues'}} ({{total}})
</h3>
{{#notEmpty projects}}
<tr>
<td class="coding-rules-detail-list-name">{{name}}</td>
<td class="coding-rules-detail-list-parameters">
- <a href="{{../baseSearchUrl}}|projectUuids={{val}}" target="_blank">{{count}}</a>
+ <a href="{{issuesUrl}}" target="_blank">{{count}}</a>
</td>
</tr>
{{/each}}
</li>
{{/notEq}}
- <li class="coding-rules-detail-property coding-rules-detail-tag-list {{#if canWrite}}coding-rules-detail-tags-change{{/if}}"
+ <li class="coding-rules-detail-property coding-rules-detail-tag-list {{#if canCustomizeRule}}coding-rules-detail-tags-change{{/if}}"
data-toggle="tooltip" data-placement="bottom" title="Rule tags">
<i class="icon-tags"></i>
<span>{{#if allTags}}{{join allTags ', '}}{{else}}{{t 'coding_rules.no_tags'}}{{/if}}</span>
{{#if canWrite}}<i class="icon-dropdown"></i>{{/if}}
</li>
- {{#if canWrite}}
+ {{#if canCustomizeRule}}
<li class="coding-rules-detail-property coding-rules-detail-tag-edit hidden">
{{#if sysTags}}<i class="icon-tags"></i>
<span>{{join sysTags ', '}}</span>{{/if}}
<td class="coding-rules-detail-quality-profile-name">
- <a href="{{profileUrl key}}">
+ <a href="{{profilePath}}">
{{name}}
</a>
{{#if parent}}
{{#eq inherit 'INHERITED'}}
<i class="icon-inheritance" title="{{tp 'coding_rules.inherits' name parent.name}}"></i>
{{/eq}}
- <a class="link-base-color" href="{{profileUrl parent.key}}">
+ <a class="link-base-color" href="{{parentProfilePath}}">
{{parent.name}}
</a>
</div>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.
+ */
+// @flow
+import React from 'react';
+import CodingRulesAppContainer from '../../coding-rules/components/CodingRulesAppContainer';
+
+export default class OrganizationRules extends React.PureComponent {
+ render() {
+ return <CodingRulesAppContainer {...this.props} />;
+ }
+}
{translate('quality_profiles.page')}
</Link>
</li>
+ <li>
+ <Link to={`/organizations/${organization.key}/rules`} activeClassName="active">
+ {translate('coding_rules.page')}
+ </Link>
+ </li>
{organization.canAdmin && this.renderAdministration()}
</ul>
</div>
quality_profiles.page
</Link>
</li>
+ <li>
+ <Link
+ activeClassName="active"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules">
+ coding_rules.page
+ </Link>
+ </li>
<li
className="">
<a
quality_profiles.page
</Link>
</li>
+ <li>
+ <Link
+ activeClassName="active"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules">
+ coding_rules.page
+ </Link>
+ </li>
</ul>
</div>
</div>
quality_profiles.page
</Link>
</li>
+ <li>
+ <Link
+ activeClassName="active"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules">
+ coding_rules.page
+ </Link>
+ </li>
<li
className="">
<a
import OrganizationPage from './components/OrganizationPage';
import OrganizationProjects from './components/OrganizationProjects';
import OrganizationFavoriteProjects from './components/OrganizationFavoriteProjects';
+import OrganizationRules from './components/OrganizationRules';
import OrganizationAdmin from './components/OrganizationAdmin';
import OrganizationEdit from './components/OrganizationEdit';
import OrganizationGroups from './components/OrganizationGroups';
path: 'members',
component: OrganizationMembersContainer
},
+ {
+ path: 'rules',
+ component: OrganizationRules
+ },
{
path: 'quality_profiles',
childRoutes: qualityProfilesRoutes
params?: {},
ruleKey: string,
ruleName: string
- }>
+ }>,
+ organization: ?string
};
export default class Changelog extends React.PureComponent {
</td>
<td style={{ lineHeight: '1.5' }}>
- <Link to={getRulesUrl({ rule_key: event.ruleKey })}>
+ <Link to={getRulesUrl({ rule_key: event.ruleKey }, this.props.organization)}>
{event.ruleName}
</Link>
</td>
{this.state.events != null &&
this.state.events.length > 0 &&
- <Changelog events={this.state.events} />}
+ <Changelog events={this.state.events} organization={this.props.organization} />}
{shouldDisplayFooter &&
<footer className="text-center spacer-top small">
inLeft={inLeft}
inRight={inRight}
modified={modified}
+ organization={this.props.organization}
/>}
</div>
);
right: { name: string },
inLeft: Array<*>,
inRight: Array<*>,
- modified: Array<*>
+ modified: Array<*>,
+ organization: ?string
};
export default class ComparisonResults extends React.PureComponent {
<div>
<SeverityIcon severity={severity} />
{' '}
- <Link to={getRulesUrl({ rule_key: rule.key })}>
+ <Link to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}>
{rule.name}
</Link>
</div>
'/api/qualityprofiles/backup?profileKey=' +
encodeURIComponent(profile.key);
- // FIXME getRulesUrl
- const activateMoreUrl = getRulesUrl({
- qprofile: profile.key,
- activation: 'false'
- });
+ const activateMoreUrl = getRulesUrl(
+ {
+ qprofile: profile.key,
+ activation: 'false'
+ },
+ this.props.organization
+ );
return (
<ul className="dropdown-menu dropdown-menu-right">
type Props = {
canAdmin: boolean,
+ organization: ?string,
profile: Profile
};
}
renderActiveCount() {
- const rulesUrl = getRulesUrl({
- qprofile: this.props.profile.key,
- activation: 'true'
- });
+ const rulesUrl = getRulesUrl(
+ {
+ qprofile: this.props.profile.key,
+ activation: 'true'
+ },
+ this.props.organization
+ );
if (this.state.activatedTotal == null) {
return null;
}
renderActiveTotal() {
- const rulesUrl = getRulesUrl({
- qprofile: this.props.profile.key,
- activation: 'false'
- });
+ const rulesUrl = getRulesUrl(
+ {
+ qprofile: this.props.profile.key,
+ activation: 'false'
+ },
+ this.props.organization
+ );
if (this.state.total == null || this.state.activatedTotal == null) {
return null;
}
renderCountForType(type: string) {
- const rulesUrl = getRulesUrl({
- qprofile: this.props.profile.key,
- activation: 'true',
- types: type
- });
+ const rulesUrl = getRulesUrl(
+ {
+ qprofile: this.props.profile.key,
+ activation: 'true',
+ types: type
+ },
+ this.props.organization
+ );
const count = this.state.activatedByType && this.state.activatedByType[type]
? this.state.activatedByType[type].count
}
renderTotalForType(type: string) {
- const rulesUrl = getRulesUrl({
- qprofile: this.props.profile.key,
- activation: 'false',
- types: type
- });
+ const rulesUrl = getRulesUrl(
+ {
+ qprofile: this.props.profile.key,
+ activation: 'false',
+ types: type
+ },
+ this.props.organization
+ );
const count = this.state.activatedByType && this.state.activatedByType[type]
? this.state.activatedByType[type].count
return null;
}
- const url = getDeprecatedActiveRulesUrl({ qprofile: profile.key });
+ const url = getDeprecatedActiveRulesUrl({ qprofile: profile.key }, this.props.organization);
return (
<div className="quality-profile-rules-deprecated clearfix">
}
render() {
- const activateMoreUrl = getRulesUrl({
- qprofile: this.props.profile.key,
- activation: 'false'
- });
+ const activateMoreUrl = getRulesUrl(
+ {
+ qprofile: this.props.profile.key,
+ activation: 'false'
+ },
+ this.props.organization
+ );
return (
<div className="quality-profile-rules">
<div className="quality-profiles-evolution">
<EvolutionDeprecated organization={organization} profiles={profiles} />
<EvolutionStagnant organization={organization} profiles={profiles} />
- <EvolutionRules />
+ <EvolutionRules organization={organization} />
</div>
);
}
props: Props;
render() {
- // FIXME getDeprecatedActiveRulesUrl
-
const profilesWithDeprecations = this.props.profiles.filter(
profile => profile.activeDeprecatedRuleCount > 0
);
{profile.languageName}
{', '}
<Link
- to={getDeprecatedActiveRulesUrl({ qprofile: profile.key })}
+ to={getDeprecatedActiveRulesUrl(
+ { qprofile: profile.key },
+ this.props.organization
+ )}
className="text-muted">
{translateWithParameters(
'quality_profile.x_rules',
});
}
-type Props = {};
+type Props = {
+ organization: ?string
+};
export default class EvolutionRules extends React.PureComponent {
mounted: boolean;
}
render() {
- // FIXME getRulesUrl
-
if (!this.state.latestRulesTotal) {
return null;
}
- const newRulesUrl = getRulesUrl({
- available_since: PERIOD_START_MOMENT.format('YYYY-MM-DD')
- });
+ const newRulesUrl = getRulesUrl(
+ {
+ available_since: PERIOD_START_MOMENT.format('YYYY-MM-DD')
+ },
+ this.props.organization
+ );
return (
<div className="quality-profile-box quality-profiles-evolution-rules">
{this.state.latestRules.map(rule => (
<li key={rule.key} className="spacer-top">
<div className="text-ellipsis">
- <Link to={getRulesUrl({ rule_key: rule.key })} className="link-no-underline">
+ <Link
+ to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}
+ className="link-no-underline">
{' '}
{rule.name}
</Link>
}
renderRules() {
- // FIXME getRulesUrl
-
const { profile } = this.props;
- const activeRulesUrl = getRulesUrl({
- qprofile: profile.key,
- activation: 'true'
- });
+ const activeRulesUrl = getRulesUrl(
+ {
+ qprofile: profile.key,
+ activation: 'true'
+ },
+ this.props.organization
+ );
- const deprecatedRulesUrl = getRulesUrl({
- qprofile: profile.key,
- activation: 'true',
- statuses: 'DEPRECATED'
- });
+ const deprecatedRulesUrl = getRulesUrl(
+ {
+ qprofile: profile.key,
+ activation: 'true',
+ statuses: 'DEPRECATED'
+ },
+ this.props.organization
+ );
return (
<div>
const ruleKey = this.model.get('rule');
// lazy load Workspace
const Workspace = require('../workspace/main').default;
- Workspace.openRule({ key: ruleKey });
+ Workspace.openRule({ key: ruleKey, organization: this.model.get('projectOrganization') });
},
action(action) {
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+// @flow
import $ from 'jquery';
import Item from './models/item';
import Items from './models/items';
return this.open({ ...options, __type__: 'component' });
},
- openRule(options) {
+ openRule(options: { key: string, organization: string }) {
return this.open({ ...options, __type__: 'rule' });
},
{{/if}}
<li class="pull-right spacer-left">
- <a class="icon-link" target="_blank" href="{{rulePermalink key}}"></a>
+ <a class="icon-link" target="_blank" href="{{permalink}}"></a>
</li>
<li class="pull-right">
import Marionette from 'backbone.marionette';
import BaseView from './base-viewer-view';
import Template from '../templates/workspace-rule.hbs';
+import { getRulesUrl } from '../../../helpers/urls';
+import { areThereCustomOrganizations } from '../../../store/organizations/utils';
export default BaseView.extend({
template: Template,
},
serializeData() {
+ const query = { rule_key: this.model.get('key') };
+ const permalink = areThereCustomOrganizations()
+ ? getRulesUrl(query, this.model.get('organization'))
+ : getRulesUrl(query);
+
return {
...Marionette.LayoutView.prototype.serializeData.apply(this, arguments),
- allTags: union(this.model.get('sysTags'), this.model.get('tags'))
+ allTags: union(this.model.get('sysTags'), this.model.get('tags')),
+ permalink
};
}
});
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 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.
- */
-module.exports = function(key) {
- return window.baseUrl + '/profiles/show?key=' + encodeURIComponent(key);
-};
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 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.
- */
-module.exports = function(ruleKey) {
- return window.baseUrl + '/coding_rules#rule_key=' + encodeURIComponent(ruleKey);
-};
* @param {object} query
* @returns {string}
*/
-export function getRulesUrl(query) {
+export function getRulesUrl(query, organization?: string) {
+ const path = organization ? `/organizations/${organization}/rules` : '/coding_rules';
+
if (query) {
const serializedQuery = Object.keys(query)
.map(criterion => `${encodeURIComponent(criterion)}=${encodeURIComponent(query[criterion])}`)
.join('|');
// return a string (not { pathname }) to help react-router's Link handle this properly
- return '/coding_rules#' + serializedQuery;
+ return path + '#' + serializedQuery;
}
- return '/coding_rules';
+ return path;
}
/**
* @param {object} query
* @returns {string}
*/
-export function getDeprecatedActiveRulesUrl(query = {}) {
+export function getDeprecatedActiveRulesUrl(query = {}, organization?: string) {
const baseQuery = { activation: 'true', statuses: 'DEPRECATED' };
- return getRulesUrl({ ...query, ...baseQuery });
+ return getRulesUrl({ ...query, ...baseQuery }, organization);
}
export const getProjectsUrl = () => {