* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { getJSON, RequestData } from '../helpers/request';
+import throwGlobalError from '../app/utils/throwGlobalError';
+
+export interface GetRulesAppResponse {
+ respositories: Array<{ key: string; language: string; name: string }>;
+}
+
+export function getRulesApp(): Promise<GetRulesAppResponse> {
+ return getJSON('/api/rules/app').catch(throwGlobalError);
+}
export function searchRules(data: RequestData) {
return getJSON('/api/rules/search', data);
const languages = queryLanguages && queryLanguages.length > 0 ? queryLanguages.split(',') : [];
let profiles = this.options.app.qualityProfiles;
if (languages.length > 0) {
- profiles = profiles.filter(profile => languages.indexOf(profile.lang) !== -1);
+ profiles = profiles.filter(profile => languages.indexOf(profile.language) !== -1);
}
- return profiles.filter(profile => !profile.isBuiltIn);
+ return profiles
+ .filter(profile => profile.actions && profile.actions.edit)
+ .filter(profile => !profile.isBuiltIn);
},
serializeData() {
const profileKey = query.qprofile;
const profile = this.options.app.qualityProfiles.find(p => p.key === profileKey);
const activation = '' + query.activation;
+ const canChangeProfile =
+ profile != null && !profile.isBuiltIn && profile.actions && profile.actions.edit;
return {
qualityProfile: profileKey,
qualityProfileName: profile != null ? profile.name : null,
- allowActivateOnProfile: profile != null && activation === 'false' && !profile.isBuiltIn,
- allowDeactivateOnProfile: profileKey != null && activation === 'true'
+ allowActivateOnProfile: canChangeProfile && activation === 'false',
+ allowDeactivateOnProfile: canChangeProfile && activation === 'true'
};
}
});
const languages = languagesQuery != null ? languagesQuery.split(',') : [];
const lang = languages.length === 1 ? languages[0] : null;
const values = this.options.app.qualityProfiles
- .filter(profile => (lang != null ? profile.lang === lang : true))
+ .filter(profile => (lang != null ? profile.language === lang : true))
.map(profile => ({
- extra: that.options.app.languages[profile.lang],
+ extra: that.options.app.languages[profile.language],
isBuiltIn: profile.isBuiltIn,
label: profile.name,
val: profile.key
import WorkspaceListView from './workspace-list-view';
import WorkspaceHeaderView from './workspace-header-view';
import FacetsView from './facets-view';
+import { searchQualityProfiles } from '../../api/quality-profiles';
+import { getRulesApp } from '../../api/rules';
import { areThereCustomOrganizations } from '../../store/organizations/utils';
const App = new Marionette.Application();
) {
App.organization = options.organization;
const data = options.organization ? { organization: options.organization } : {};
- $.get(window.baseUrl + '/api/rules/app', data)
- .done(r => {
+ Promise.all([getRulesApp(data), searchQualityProfiles(data)])
+ .then(([appResponse, profilesResponse]) => {
App.customRules = !areThereCustomOrganizations();
- App.canWrite = r.canWrite;
+ App.canWrite = appResponse.canWrite;
App.organization = options.organization;
- App.qualityProfiles = sortBy(r.qualityprofiles, ['name', 'lang']);
- App.languages = { ...r.languages, none: 'None' };
- App.qualityProfiles.forEach(profile => {
- profile.language = App.languages[profile.lang];
- });
- App.repositories = r.repositories;
- App.statuses = r.statuses;
- })
- .done(() => {
+ App.qualityProfiles = sortBy(profilesResponse.profiles, ['name', 'lang']);
+ App.languages = { ...appResponse.languages, none: 'None' };
+ App.repositories = appResponse.repositories;
+ App.statuses = appResponse.statuses;
+
this.layout = new Layout({ el: options.el });
this.layout.render();
$('#footer').addClass('page-footer-with-sidebar');
app: this
});
Backbone.history.start();
+ })
+ .catch(() => {
+ // do nothing in case of WS error
});
});
const inactiveProfiles = this.options.app.qualityProfiles.filter(
profile => !activeQualityProfiles.findWhere({ key: profile.key })
);
+ // choose QP which a user can administrate, which are the same language and which are not built-in
return inactiveProfiles
- .filter(profile => profile.lang === lang)
+ .filter(profile => profile.actions && profile.actions.edit)
+ .filter(profile => profile.language === lang)
.filter(profile => !profile.isBuiltIn);
},
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
parent,
+ actions: this.model.get('actions') || {},
canWrite: this.options.app.canWrite,
parameters: this.enhanceParameters(parent),
templateKey: this.options.rule.get('templateKey'),
isTemplate: this.options.rule.get('isTemplate'),
- profilePath: this.getProfilePath(this.model.get('lang'), this.model.get('name')),
- parentProfilePath: parent && this.getProfilePath(parent.lang, parent.name)
+ profilePath: this.getProfilePath(this.model.get('language'), this.model.get('name')),
+ parentProfilePath: parent && this.getProfilePath(parent.language, parent.name)
};
}
});
},
serializeData() {
+ // show "Activate" button only if user has at least one QP which he administates
+ const canActivate = this.options.app.qualityProfiles.some(
+ profile => profile.actions && profile.actions.edit
+ );
+
return {
...Marionette.ItemView.prototype.serializeData.apply(this, arguments),
- canWrite: this.options.app.canWrite
+ canActivate
};
}
});
+++ /dev/null
-{{#each activeProfiles}}
- {{severityIcon severity}}
-
- {{#eq inherit 'OVERRIDES'}}
- <i class="icon-inheritance" title="{{tp 'coding_rules.overrides' name parent.name}}"></i>
- {{/eq}}
- {{#eq inherit 'INHERITED'}}
- <i class="icon-inheritance" title="{{tp 'coding_rules.inherits' name parent.name}}"></i>
- {{/eq}}
-
- {{#if ../canWrite}}
- <div class="button-group">
- {{#unless isTemplate}}
- <button class="coding-rules-detail-quality-profile-change">{{t 'change_verb'}}</button>
- {{/unless}}
- {{#if parent}}
- {{#eq inherit 'OVERRIDES'}}
- <button class="coding-rules-detail-quality-profile-revert button-red">
- {{t 'coding_rules.revert_to_parent_definition'}}
- </button>
- {{/eq}}
- {{else}}
- <button class="coding-rules-detail-quality-profile-deactivate button-red">
- {{t 'coding_rules.deactivate'}}
- </button>
- {{/if}}
- </div>
- {{/if}}
-{{/each}}
<div class="search-navigator-header-buttons button-group">
<button class="js-reload">{{t 'reload'}}</button>
<button class="js-new-search" id="coding-rules-new-search">{{t 'coding_rules.new_search'}}</button>
- {{#if canWrite}}
+ {{#if canBulkChange}}
<button class="js-bulk-change">{{t 'bulk_change'}}</button>
{{/if}}
</div>
</td>
{{#any activation selectedProfile}}
- {{#if canWrite}}
+ {{#if canEditQualityProfile}}
{{#unless isSelectedProfileBuiltIn}}
<td class="coding-rule-table-meta-cell coding-rule-activation-actions">
<div class="button-group">
{{#if activation}}
- {{#eq activation.inherit 'NONE'}}
- <button class="coding-rules-detail-quality-profile-deactivate button-red">
- {{t 'coding_rules.deactivate'}}
- </button>
- {{/eq}}
+ <button class="coding-rules-detail-quality-profile-deactivate button-red"
+ {{#notEq activation.inherit 'NONE'}}disabled title="{{t 'coding_rules.can_not_deactivate'}}"{{/notEq}}>
+ {{t 'coding_rules.deactivate'}}
+ </button>
{{else}}
{{#unless isTemplate}}
<button class="coding-rules-detail-quality-profile-activate">{{t 'coding_rules.activate'}}</button>
</td>
{{/unless}}
- {{#if canWrite}}
+ {{#if actions.edit}}
{{#unless isBuiltIn}}
<td class="coding-rules-detail-quality-profile-actions">
<div class="button-group">
<h3 class="coding-rules-detail-title">{{t 'coding_rules.quality_profiles'}}</h3>
- {{#if canWrite}}
+ {{#if canActivate}}
{{#unless isTemplate}}
<div class="button-group coding-rules-detail-quality-profiles-activation">
<button id="coding-rules-quality-profile-activate">{{t 'coding_rules.activate'}}</button>
},
serializeData() {
+ // show "Bulk Change" button only if user has at least one QP which he administates
+ const canBulkChange = this.options.app.qualityProfiles.some(
+ profile => profile.actions && profile.actions.edit
+ );
+
return {
...WorkspaceHeaderView.prototype.serializeData.apply(this, arguments),
- canWrite: this.options.app.canWrite
+ canBulkChange
};
}
});
this.options.app.qualityProfiles.find(profile => profile.key === selectedProfileKey);
const isSelectedProfileBuiltIn = selectedProfile != null && selectedProfile.isBuiltIn;
+ const canEditQualityProfile =
+ selectedProfile && selectedProfile.actions && selectedProfile.actions.edit;
+
return {
...WorkspaceListItemView.prototype.serializeData.apply(this, arguments),
+ canEditQualityProfile,
tags: union(this.model.get('sysTags'), this.model.get('tags')),
- canWrite: this.options.app.canWrite,
selectedProfile: selectedProfileKey,
isSelectedProfileBuiltIn
};
float: left;
height: 16px;
line-height: 16px;
+ margin-top: -1px;
padding: 0 5px;
- border-radius: 3px;
+ border-radius: 2px;
font-size: 11px;
- font-weight: 300;
text-transform: lowercase;
&:hover {
coding_rules.bulk_change=Bulk Change
coding_rules.bulk_change.success={2} rule(s) changed in profile {0} - {1}
coding_rules.bulk_change.warning={2} rule(s) changed, {3} rule(s) ignored in profile {0} - {1}
+coding_rules.can_not_deactivate=This rule is inherited and can not be deactivated.
coding_rules.change_severity=Change Severity
coding_rules.change_severity_in=Change Severity In
coding_rules.change_details=Change Details of Quality Profile