import ComponentViewer from './component-viewer/main';
import HomeView from './workspace-home-view';
-const FACET_DATA_FIELDS = ['components', 'users', 'rules', 'actionPlans', 'languages'];
+const FACET_DATA_FIELDS = ['components', 'users', 'rules', 'languages'];
export default Controller.extend({
_facetsFromServer () {
import TagFacet from './facets/tag-facet';
import ResolutionFacet from './facets/resolution-facet';
import CreationDateFacet from './facets/creation-date-facet';
-import ActionPlanFacet from './facets/action-plan-facet';
import FileFacet from './facets/file-facet';
import ReporterFacet from './facets/reporter-facet';
import LanguageFacet from './facets/language-facet';
moduleUuids: ModuleFacet,
rules: RuleFacet,
tags: TagFacet,
- actionPlans: ActionPlanFacet,
fileUuids: FileFacet,
reporters: ReporterFacet,
languages: LanguageFacet,
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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 $ from 'jquery';
-import _ from 'underscore';
-import BaseFacet from './base-facet';
-import Template from '../templates/facets/issues-action-plan-facet.hbs';
-
-export default BaseFacet.extend({
- template: Template,
-
- onRender () {
- BaseFacet.prototype.onRender.apply(this, arguments);
- const value = this.options.app.state.get('query').planned;
- if ((value != null) && (!value || value === 'false')) {
- return this.$('.js-facet').filter('[data-unplanned]').addClass('active');
- }
- },
-
- toggleFacet (e) {
- const unplanned = $(e.currentTarget).is('[data-unplanned]');
- $(e.currentTarget).toggleClass('active');
- if (unplanned) {
- const checked = $(e.currentTarget).is('.active');
- const value = checked ? 'false' : null;
- return this.options.app.state.updateFilter({
- planned: value,
- actionPlans: null
- });
- } else {
- return this.options.app.state.updateFilter({
- planned: null,
- actionPlans: this.getValue()
- });
- }
- },
-
- getValuesWithLabels () {
- const values = this.model.getValues();
- const actionPlans = this.options.app.facets.actionPlans;
- values.forEach(function (v) {
- const key = v.val;
- let label = null;
- if (key) {
- const actionPlan = _.findWhere(actionPlans, { key });
- if (actionPlan != null) {
- label = actionPlan.name;
- }
- }
- v.label = label;
- });
- return values;
- },
-
- disable () {
- return this.options.app.state.updateFilter({
- planned: null,
- actionPlans: null
- });
- },
-
- serializeData () {
- return _.extend(BaseFacet.prototype.serializeData.apply(this, arguments), {
- values: this.getValuesWithLabels()
- });
- }
-});
-
-
issue = that._injectRelational(issue, r.rules, 'rule', 'key');
issue = that._injectRelational(issue, r.users, 'assignee', 'login');
issue = that._injectRelational(issue, r.users, 'reporter', 'login');
- issue = that._injectRelational(issue, r.actionPlans, 'actionPlan', 'key');
issue = that._injectCommentsRelational(issue, r.users);
issue = that._prepareClosed(issue);
issue = that.ensureTextRange(issue);
'assignees',
'reporters',
'authors',
- 'languages',
- 'actionPlans'
+ 'languages'
],
facetsFromServer: [
'types',
'severities',
'statuses',
'resolutions',
- 'actionPlans',
'projectUuids',
'directories',
'rules',
transform: {
'resolved': 'resolutions',
'assigned': 'assignees',
- 'planned': 'actionPlans',
'createdBefore': 'createdAt',
'createdAfter': 'createdAt',
'createdInLast': 'createdAt'
+++ /dev/null
-{{> "_issues-facet-header"}}
-
-<div class="search-navigator-facet-list">
- {{#each values}}
- {{#eq val ""}}
- {{! unplanned }}
- <a class="facet search-navigator-facet js-facet" data-unplanned title="{{t "issue.unplanned"}}">
- <span class="facet-name">{{t "issue.unplanned"}}</span>
- <span class="facet-stat">
- {{formatFacetValue count ../../state.facetMode}}
- </span>
- </a>
- {{else}}
- <a class="facet search-navigator-facet js-facet" data-value="{{val}}" title="{{label}}">
- <span class="facet-name">{{label}}</span>
- <span class="facet-stat">
- {{formatFacetValue count ../../state.facetMode}}
- </span>
- </a>
- {{/eq}}
- {{/each}}
-</div>
{{/if}}
</li>
- <li>
- {{#if actionPlan}}
- <a href="#" data-property="actionPlans" data-value="{{actionPlan}}">
- {{t "issue.planned_for"}} {{actionPlanName}}
- </a>
- {{else}}
- <a href="#" data-property="planned" data-value="false">
- {{t "issue.unplanned"}}
- </a>
- {{/if}}
- </li>
-
<li class="divider"></li>
<li>
resolutions: ['resolved'],
resolved: ['resolutions'],
assignees: ['assigned'],
- assigned: ['assignees'],
- actionPlans: ['planned'],
- planned: ['actionPlans']
+ assigned: ['assignees']
};
export default IssueView.extend({
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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 Backbone from 'backbone';
-
-export default Backbone.Collection.extend({
- url () {
- return '/api/action_plans/search';
- },
-
- parse (r) {
- return r.actionPlans;
- }
-});
-
-
issue = that._injectRelational(issue, r.rules, 'rule', 'key');
issue = that._injectRelational(issue, r.users, 'assignee', 'login');
issue = that._injectRelational(issue, r.users, 'reporter', 'login');
- issue = that._injectRelational(issue, r.actionPlans, 'actionPlan', 'key');
issue = that._injectCommentsRelational(issue, r.users);
issue = that._prepareClosed(issue);
issue = that.ensureTextRange(issue);
import Marionette from 'backbone.marionette';
import ChangeLog from './models/changelog';
import ChangeLogView from './views/changelog-view';
-import ActionPlans from './collections/action-plans';
import TransitionsFormView from './views/transitions-form-view';
import AssignFormView from './views/assign-form-view';
import CommentFormView from './views/comment-form-view';
-import PlanFormView from './views/plan-form-view';
import SetSeverityFormView from './views/set-severity-form-view';
import SetTypeFormView from './views/set-type-form-view';
import TagsFormView from './views/tags-form-view';
view.destroy();
},
- plan (e) {
- const that = this;
- const t = $(e.currentTarget);
- const actionPlans = new ActionPlans();
- return actionPlans.fetch({
- reset: true,
- data: { project: this.model.get('project') }
- }).done(function () {
- e.stopPropagation();
- $('body').click();
- that.popup = new PlanFormView({
- triggerEl: t,
- bottom: true,
- model: that.model,
- collection: actionPlans
- });
- that.popup.render();
- });
- },
-
showRule () {
const ruleKey = this.model.get('rule');
Workspace.openRule({ key: ruleKey });
issue = this._injectRelational(issue, r.rules, 'rule', 'key');
issue = this._injectRelational(issue, r.users, 'assignee', 'login');
issue = this._injectRelational(issue, r.users, 'reporter', 'login');
- issue = this._injectRelational(issue, r.actionPlans, 'actionPlan', 'key');
issue = this._injectCommentsRelational(issue, r.users);
issue = this._prepareClosed(issue);
issue = this.ensureTextRange(issue);
{{/inArray}}
</li>
- <li class="issue-meta">
- {{#inArray actions "plan"}}
- <button class="button-link issue-action issue-action-with-options js-issue-plan">
- <span
- class="issue-meta-label">{{#if actionPlan}}{{default actionPlanName actionPlan}}{{else}}{{t 'issue.unplanned'}}{{/if}}</span> <i
- class="icon-dropdown"></i>
- </button>
- {{else}}
- <span
- class="issue-meta-label">{{#if actionPlan}}{{default actionPlanName actionPlan}}{{else}}{{t 'issue.unplanned'}}{{/if}}</span>
- {{/inArray}}
- </li>
-
{{#if debt}}
<li class="issue-meta">
<span class="issue-meta-label">
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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 $ from 'jquery';
-import _ from 'underscore';
-import ActionOptionsView from '../../common/action-options-view';
-import Template from '../templates/issue-plan-form.hbs';
-import { translate } from '../../../helpers/l10n';
-
-export default ActionOptionsView.extend({
- template: Template,
-
- getActionPlan () {
- return this.model.get('actionPlan') || '';
- },
-
- selectInitialOption () {
- this.makeActive(this.getOptions().filter(`[data-value="${this.getActionPlan()}"]`));
- },
-
- selectOption (e) {
- const actionPlan = $(e.currentTarget).data('value');
- const actionPlanName = $(e.currentTarget).data('text');
- this.submit(actionPlan, actionPlanName);
- return ActionOptionsView.prototype.selectOption.apply(this, arguments);
- },
-
- submit (actionPlan) {
- return this.model.plan(actionPlan);
- },
-
- getActionPlans () {
- return [{ key: '', name: translate('issue.unplanned') }].concat(this.collection.toJSON());
- },
-
- serializeData () {
- return _.extend(ActionOptionsView.prototype.serializeData.apply(this, arguments), {
- items: this.getActionPlans()
- });
- }
-});
data: {
componentUuids: this.model.id,
f: 'component,componentId,project,subProject,rule,status,resolution,author,reporter,assignee,debt,' +
- 'line,message,severity,actionPlan,creationDate,updateDate,closeDate,tags,comments,attr,actions,' +
- 'transitions,actionPlanName',
+ 'line,message,severity,creationDate,updateDate,closeDate,tags,comments,attr,actions,' +
+ 'transitions',
additionalFields: '_all',
resolved: false,
s: 'FILE_LINE',
renderAdministration() {
const shouldShowAdministration =
- this.props.conf.showActionPlans ||
this.props.conf.showBackgroundTasks ||
this.props.conf.showDeletion ||
this.props.conf.showHistory ||
{this.renderProfilesLink()}
{this.renderQualityGatesLink()}
{this.renderCustomMeasuresLink()}
- {this.renderActionPlansLink()}
{this.renderLinksLink()}
{this.renderPermissionsLink()}
{this.renderHistoryLink()}
return this.renderLink(url, translate('custom_measures.page'), '/custom_measures');
},
- renderActionPlansLink() {
- if (!this.props.conf.showActionPlans) {
- return null;
- }
- const url = `/action_plans?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('action_plans.page'), '/action_plans');
- },
-
renderLinksLink() {
if (!this.props.conf.showLinks) {
return null;
+++ /dev/null
-<table class="data zebra">
- {{> '_widget-issue-filter-total'}}
- {{#each items}}
- <tr>
- <td>
- {{#eq val ''}}
- <a href="{{issueFilterItemLink ../../parsedQuery 'planned' 'false' ../../displayMode}}">{{t 'issue.unplanned'}}</a>
- {{else}}
- <a href="{{issueFilterItemLink ../../parsedQuery 'actionPlans' val ../../displayMode}}">{{default label val}}</a>
- {{/eq}}
- </td>
- <td class="text-right nowrap">
- {{#notNull ../periodDate}}+{{/notNull}}{{issueFilterValue count ../displayMode}}
- </td>
- <td class="barchart">
- <div class="barchart" style="width: 100%;">
- <div style="width: {{percent count ../total}};"></div>
- </div>
- </td>
- </tr>
- {{/each}}
-</table>
-
-{{#if maxResultsReached}}
- {{> '_widget-issue-filter-limit'}}
-{{/if}}
import Marionette from 'backbone.marionette';
import Template from './templates/widget-issue-filter.hbs';
-import ActionPlansTemplate from './templates/widget-issue-filter-action-plans.hbs';
import AssigneesTemplate from './templates/widget-issue-filter-assignees.hbs';
import ResolutionsTemplate from './templates/widget-issue-filter-resolutions.hbs';
import SeveritiesTemplate from './templates/widget-issue-filter-severities.hbs';
}
}
},
- 'actionPlans': {
- template: ActionPlansTemplate,
- label (item, r) {
- if (_.isArray(r.actionPlans)) {
- const actionPlan = _.findWhere(r.actionPlans, { key: item.val });
- if (actionPlan != null) {
- return actionPlan.name;
- }
- }
- },
- filter (item) {
- if ('' + this.query.planned === 'false') {
- return item.val === '';
- } else {
- return defaultFilter.call(this, item);
- }
- }
- },
'createdAt': {
comparator (item) {
return -moment(item.val).unix();
+++ /dev/null
-#
-# SonarQube, open source software quality management tool.
-# Copyright (C) 2008-2014 SonarSource
-# mailto:contact AT sonarsource DOT com
-#
-# SonarQube 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.
-#
-# SonarQube 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.
-#
-
-class ActionPlansController < ApplicationController
-
- SECTION=Navigation::SECTION_RESOURCE
- before_filter :load_resource
-
- def index
- load_action_plans()
- end
-
- def create_form
- load_action_plans()
- render :partial => 'action_plans/create_form'
- end
-
- def edit_form
- @action_plan = find_by_key(params[:plan_key])
- load_action_plans()
- render :partial => 'action_plans/edit_form'
- end
-
- def edit
- verify_post_request
- options = {'project' => @resource.key, 'name' => params[:name], 'description' => params[:description], 'deadLine' => params[:deadline]}
-
- action_plan_result = Internal.issues.updateActionPlan(params[:plan_key], options)
-
- if action_plan_result.ok()
- @action_plan = action_plan_result.get()
- flash[:notice] = 'Successfully edited.'
- render :text => 'ok', :status => 200
- else
- render :text => action_plan_result.errors().map{|error| error.text ? error.text : Api::Utils.message(error.l10nKey, :params => error.l10nParams)}.join('<br/>'),
- :status => 400
- end
- end
-
- def save
- verify_post_request
- options = {'project' => @resource.key, 'name' => params[:name], 'description' => params[:description], 'deadLine' => params[:deadline]}
-
- action_plan_result = Internal.issues.createActionPlan(options)
-
- if action_plan_result.ok()
- @action_plan = action_plan_result.get()
- flash[:notice] = 'Successfully created.'
- render :text => 'ok', :status => 200
- else
- render :text => action_plan_result.errors().map{|error| error.text ? error.text : Api::Utils.message(error.l10nKey, :params => error.l10nParams)}.join('<br/>'),
- :status => 400
- end
- end
-
- def delete
- verify_post_request
- Internal.issues.deleteActionPlan(params[:plan_key])
- flash[:notice] = 'Successfully deleted.'
- redirect_to :action => 'index', :id => @resource.id
- end
-
- def change_status
- verify_post_request
- action_plan = find_by_key(params[:plan_key])
- if action_plan
- if action_plan.status == 'OPEN'
- Internal.issues.closeActionPlan(params[:plan_key])
- else
- Internal.issues.openActionPlan(params[:plan_key])
- end
- end
- redirect_to :action => 'index', :id => @resource.id
- end
-
- private
-
- def load_resource
- @resource=Project.by_key(params[:id])
- return redirect_to(home_path) unless @resource
- access_denied unless has_role?(:admin, @resource)
- @snapshot=@resource.last_snapshot
- end
-
- def load_action_plans
- action_plans = Internal.issues.findActionPlanStats(@resource.key)
- @open_action_plans = action_plans.select {|plan| plan.isOpen()}
- @closed_action_plans = action_plans.reject {|plan| plan.isOpen()}
- users = Api.users.find('logins' => (@open_action_plans + @closed_action_plans).collect {|action_plan| action_plan.userLogin()}.join(","))
- @users = Hash[users.collect { |user| [user.login(), user.name()] }]
- end
-
- def find_by_key(key)
- Internal.issues.findActionPlan(key)
- end
-
-end
+++ /dev/null
-<form action="<%= url_for :action => 'save' -%>" method="POST" id="create-action-plan-form">
- <input type="hidden" name="id" value="<%= @resource.id -%>"/>
- <input type="hidden" name="plan_key" value="<%= @action_plan.key() if @action_plan -%>"/>
-
- <fieldset>
- <div class="modal-head">
- <h2><%=message('action_plans.create_form_title') -%></h2>
- </div>
- <div class="modal-body">
- <div class="modal-error"></div>
-
- <div class="modal-field">
- <label for="user[login]"><%= message('action_plans.col.name') -%> <em class="mandatory">*</em></label>
- <input type="text" name="name" id="name" value="<%= @action_plan ? @action_plan.name() : params[:name] -%>"/><br/>
- </div>
- <div class="modal-field">
- <label for="user[login]"> <%= message('action_plans.col.due_for') -%> </label>
- <input type="text" name="deadline" id="deadline" value="<%= @action_plan && @action_plan.deadLine() ? Api::Utils.format_date(@action_plan.deadLine()) : params[:deadline] -%>"/>
- <br/>
- <span class="note"><%= message('action_plans.date_format_help') -%></span>
- <br/>
- </div>
- <div class="modal-field">
- <label for="user[login]"><%= message('action_plans.col.description') -%> </label>
- <textarea rows="5" cols="80" name="description" id="description" class="width100"><%= @action_plan ? @action_plan.description() : params['description'] -%></textarea>
- </div>
- </div>
-
- <div class="modal-foot">
- <input type="submit" value="<%= h(message('create')) -%>"/>
- <%= link_to message('cancel'), { :controller => 'action_plans', :action => 'index', :id => @resource.id}, { :class => 'action' } %>
- </div>
- </fieldset>
-</form>
-
-<script>
- $j("#create-action-plan-form").modalForm();
- $j("[name=deadline]").datepicker({
- dateFormat: 'yy-mm-dd',
- changeMonth: true,
- changeYear: true
- });
-</script>
-
+++ /dev/null
-<form action="<%= url_for :action => 'edit' -%>" method="POST" id="edit-action-plan-form">
- <input type="hidden" name="id" value="<%= @resource.id -%>"/>
- <input type="hidden" name="plan_key" value="<%= @action_plan.key() if @action_plan -%>"/>
-
- <fieldset>
- <div class="modal-head">
- <h2><%= message('action_plans.edit_action_plan') -%>: <%= @action_plan ? @action_plan.name() : params[:name] -%></h2>
- </div>
- <div class="modal-body">
- <div class="modal-error"></div>
-
- <div class="modal-field">
- <label for="user[login]"><%= message('action_plans.col.name') -%> <em class="mandatory">*</em></label>
- <input type="text" name="name" id="name" value="<%= @action_plan ? @action_plan.name() : params[:name] -%>"/><br/>
- </div>
- <div class="modal-field">
- <label for="user[login]"> <%= message('action_plans.col.due_for') -%> </label>
- <input type="text" name="deadline" id="deadline" value="<%= @action_plan && @action_plan.deadLine() ? Api::Utils.format_date(@action_plan.deadLine()) : params[:deadline] -%>"/>
- <br/>
- <span class="note"><%= message('action_plans.date_format_help') -%></span>
- <br/>
- </div>
- <div class="modal-field">
- <label for="user[login]"><%= message('action_plans.col.description') -%> </label>
- <textarea rows="5" cols="80" name="description" id="description" class="width100"><%= @action_plan ? @action_plan.description() : params['description'] -%></textarea>
- </div>
- </div>
-
- <div class="modal-foot">
- <input type="submit" value="<%= h(message('save')) -%>"/>
- <%= link_to message('cancel'), { :controller => 'action_plans', :action => 'index', :id => @resource.id}, { :class => 'action' } %>
- </div>
- </fieldset>
-</form>
-
-<script>
- $j("#edit-action-plan-form").modalForm();
- $j("[name=deadline]").datepicker({
- dateFormat: 'yy-mm-dd',
- changeMonth: true,
- changeYear: true
- });
-</script>
-
+++ /dev/null
-<%
- unless action_plan.totalIssues()==0
- project = @project
- project = @resource if project.nil?
- options = {:actionPlans => action_plan.key}
-
- resolved_issues_link = action_plan.resolvedIssues().to_s
- resolved_issues_link = link_to action_plan.resolvedIssues().to_s, url_for_component_issues(@project, options.merge(:resolved => 'true')) unless action_plan.resolvedIssues()==0
- total_issues_link = link_to action_plan.totalIssues().to_s, url_for_component_issues(@project, options)
-
- if action_plan.resolvedIssues() > 0
- resolved_issues_url = url_for_component_issues(@project, options.merge({:resolved => 'true'}))
- percent_resolved = (action_plan.resolvedIssues()*100 / action_plan.totalIssues()).to_i
- tooltip_resolved = message('action_plans.resolved_issues_x_percent', :params => [percent_resolved.to_s, action_plan.resolvedIssues().to_s])
- end
-
- if action_plan.unresolvedIssues() > 0
- unresolved_issues_url = url_for_component_issues(@project, options.merge({:resolved => 'false'}))
- percent_open = (action_plan.unresolvedIssues()*100 / action_plan.totalIssues()).to_i
- tooltip_open = message('action_plans.unresolved_issues_x_percent', :params => [percent_open.to_s, action_plan.unresolvedIssues().to_s])
- end
-%>
-
- <div class="progress">
- <table>
- <tbody>
- <tr>
- <% if action_plan.resolvedIssues() > 0 %>
- <td class="resolved" style="width:<%= percent_resolved -%>%;">
- <a href="<%= resolved_issues_url -%>" title="<%= resolved_issues_url -%>" alt="<%= tooltip_resolved -%>"></a>
- </td>
- <% end %>
- <% if action_plan.unresolvedIssues() > 0 %>
- <td class="open" style="width:<%= percent_open -%>%;">
- <a href="<%= unresolved_issues_url -%>" title="<%= unresolved_issues_url -%>" alt="<%= tooltip_open -%>"></a>
- </td>
- <% end %>
- </tr>
- </tbody>
- </table>
- <div class="note"><%= message('action_plans.x_out_of_x_issues_solved', :params => [resolved_issues_link, total_issues_link]) -%></div>
- </div>
-
-<% end %>
+++ /dev/null
-<div class="page">
- <header class="page-header">
- <h1 class="page-title"><%= message('action_plans.page') -%></h1>
- <% if is_admin?(@resource.id) %>
- <div class="page-actions">
- <a id="create-link-action_plans"
- href="/action_plans/create_form/<%= h(@resource.id) -%>"
- class="open-modal button"><%= message('action_plans.add_new_action_plan') -%></a>
- </div>
- <% end %>
- <p class="page-description"><%= message('action_plans.page.description') -%></p>
- </header>
-
- <table width="100%" id="action-plans">
- <tr>
- <td valign="top">
- <table class="width100 data sortable actionPlans" id="open-action-plans">
- <thead>
- <tr>
- <th class="thin nowrap"><%= message('action_plans.col.status') -%></th>
- <th class="thin nowrap"><%= message('action_plans.col.name') -%></th>
- <th class="thin nowrap righticon sortfirstasc" style="text-align: right"><%= message('action_plans.col.due_for') -%></th>
- <th class="nowrap text-center"><%= message('action_plans.col.progress') -%></th>
- <th class="nowrap"><%= message('action_plans.col.description') -%></th>
- <th class="nowrap"><%= message('action_plans.col.author') -%></th>
- <th class="thin nowrap text-right"><%= message('action_plans.col.operations') -%></th>
- </tr>
- </thead>
- <tbody>
- <% if @open_action_plans.empty? %>
- <td colspan="7" class="even"><%= message('action_plans.no_action_plan') -%></td>
- <% end %>
- <%
- @open_action_plans.each do |plan|
- %>
- <tr class="<%= cycle('even', 'odd', :name => 'open_plans') -%>">
- <td class="thin nowrap text-center">
- <img src="/images/status/<%= plan.status() -%>.png" title="<%= message("action_plans.status.#{plan.status}") -%>"/></td>
- <td class="thin nowrap"><%= h(plan.name()) -%></td>
- <td class="thin nowrap <%= 'over-due' if plan.overDue() -%>" align="right"><%= format_date(plan.deadLine()) -%></td>
- <% if plan.totalIssues()==0 %>
- <td class="noprogress thin nowrap">
- <%= message('action_plans.no_issues_linked_to_action_plan') -%>
- </td>
- <% else %>
- <td class="progress thin">
- <%= render :partial => 'progress', :locals => {:action_plan => plan} -%>
- </td>
- <% end %>
- <td id="desc"><%= h(plan.description()) -%></td>
- <td id="desc"><%= h(@users[plan.userLogin()]) -%></td>
- <td class="thin nowrap text-right">
- <%= link_to message('edit'), {:action => 'edit_form', :id => @resource.id, :plan_key => plan.key()}, :class => 'open-modal link-action' -%>
-
- <%
- close_confirmation_message = {}
- if plan.isOpen() && plan.unresolvedIssues() > 0
- close_confirmation_message = {:confirm => message('action_plans.confirm_close')}
- end
- %>
- <%= link_to message('close'),
- {:action => 'change_status', :id => @resource.id, :plan_key => plan.key()}, {:method => 'POST', :class => 'link-action'}.merge(close_confirmation_message) -%>
-
- <%= link_to_action message('delete'), "/action_plans/delete/#{h(@resource.id)}?plan_key=#{h(plan.key)}",
- :class => 'link-action link-red',
- :id => "delete_#{h(plan.key)}",
- :confirm_button => message('delete'),
- :confirm_title => message('action_plans.delete'),
- :confirm_msg => message('action_plans.delete_message', :params => [h(plan.name)]),
- :confirm_msg_params => ''
- -%>
- </td>
- </tr>
- <% end %>
- </tbody>
- </table>
-
- <% unless @closed_action_plans.empty? %>
- <br/><br/>
-
- <h1><%= message('action_plans.closed_action_plan') -%></h1>
-
- <table class="width100 data sortable actionPlans" id="closed-action-plans">
- <thead>
- <tr>
- <th class="thin nowrap"><%= message('action_plans.col.status') -%></th>
- <th class="thin nowrap"><%= message('action_plans.col.name') -%></th>
- <th class="thin nowrap righticon sortfirstdesc" style="text-align: right"><%= message('action_plans.col.due_for') -%></th>
- <th class="thin nowrap righticon" style="text-align: right"><%= message('action_plans.col.closed_on') -%></th>
- <th class="nowrap text-center"><%= message('action_plans.col.progress') -%></th>
- <th class="nowrap"><%= message('action_plans.col.description') -%></th>
- <th class="nowrap"><%= message('action_plans.col.author') -%></th>
- <th class="thin nowrap text-right"><%= message('action_plans.col.operations') -%></th>
- </tr>
- </thead>
- <tbody>
- <%
- @closed_action_plans.each do |plan|
- %>
- <tr class="<%= cycle('even', 'odd', :name => 'closed_plans') -%>">
- <td class="thin nowrap text-center"><img src="/images/status/<%= plan.status() -%>.png" title="<%= message("action_plans.status.#{plan.status}") -%>"/>
- </td>
- <td class="thin nowrap"><%= h(plan.name) -%></td>
- <td class="thin nowrap <%= 'over-due' if plan.overDue() -%>" align="right"><%= format_date(plan.deadLine()) -%></td>
- <td class="thin nowrap" align="right"><%= format_date(plan.updatedAt()) -%></td>
- <% if plan.totalIssues()==0 %>
- <td class="noprogress thin nowrap">
- <%= message('action_plans.no_issues_linked_to_action_plan') -%>
- </td>
- <% else %>
- <td class="progress thin">
- <%= render :partial => 'progress', :locals => {:action_plan => plan} -%>
- </td>
- <% end %>
- <td id="desc"><%= h(plan.description()) -%></td>
- <td id="desc"><%= h(@users[plan.userLogin()]) -%></td>
- <td class="thin nowrap text-right">
- <%= link_to message('action_plans.reopen'),
- {:action => 'change_status', :id => @resource.id, :plan_key => plan.key}, {:method => 'POST', :class => 'link-action'} -%>
-
- <%= link_to_action message('delete'), "/action_plans/delete/#{h(@resource.id)}?plan_key=#{h(plan.key)}",
- :class => 'link-action link-red',
- :id => "delete_#{h(plan.key)}",
- :confirm_button => message('delete'),
- :confirm_title => 'Delete action plan: '+ h(plan.name()),
- :confirm_msg => message('action_plans.confirm_delete'),
- :confirm_msg_params => ''
- -%>
- </td>
- </tr>
- <% end %>
- </tbody>
- </table>
- <% end %>
- </td>
- </tr>
- </table>
-</div>
transitions_by_issues = {}
unresolved_issues = 0
unresolved_issues_user_can_admin = 0
- at_least_one_issue_is_planned = false
at_least_one_issue_is_assigned = false
all_issues_are_assigned_to_current_user = true
@issues.each do |issue|
if Internal.issues.isUserIssueAdmin(issue.projectUuid)
unresolved_issues_user_can_admin += 1 unless issue.resolution()
end
- at_least_one_issue_is_planned ||= issue.actionPlanKey()
at_least_one_issue_is_assigned ||= issue.assignee()
all_issues_are_assigned_to_current_user &&= issue.assignee() == current_user.login
end
-%>
<span style="float:right" class="note">(<%= message('issue_bulk_change.x_issues', :params => unresolved_issues.to_s) -%>)</span>
</div>
- <%
- if project_key
- plans = Internal.issues.findOpenActionPlans(project_key)
- # Display action plan combo box if there are some action plans defined on the project
- unless plans.empty?
- first_plan = plans[0]
- options = plans.map { |plan|
- label = plan.deadLine ? "#{h plan.name} (#{format_date(plan.deadLine)})" : h(plan.name)
- [label, plan.key]
- }
- # SONAR-4728 Display 'Unplan' option only if at least one issue is planned
- options.unshift([escape_javascript(message('issue.unplan.submit')), '']) if at_least_one_issue_is_planned
- plan_options = options_for_select(options, first_plan.key)
- %>
- <div class="modal-field">
- <label for="plan">
- <%= message('issue.do_plan') -%>
- </label>
- <input id="plan-action" name="actions[]" type="checkbox" value="plan"/>
- <%= dropdown_tag('plan.plan', plan_options, {:show_search_box => false}, {:id => 'plan'}) -%>
- <span style="float:right" class="note">(<%= message('issue_bulk_change.x_issues', :params => unresolved_issues.to_s) -%>)</span>
- </div>
- <% end %>
- <% end %>
<%
type_options = [
<input id="remove_tags" name="remove_tags.tags" type="text"/>
<span style="float:right" class="note">(<%= message('issue_bulk_change.x_issues', :params => unresolved_issues.to_s) -%>)</span>
</div>
-
<% end %>
<% if transitions_by_issues.size > 0 %>
* Attach some events on select boxes to automatically select associate check box when selecting an option
*/
$j('#assignee').click(function() { check('assign-action'); });
- $j('#plan').click(function() { check('plan-action'); });
$j('#severity').click(function() { check('set-severity-action'); });
$j('#type').click(function() { check('set-type-action'); });
$j('#add_tags').select2({tags: [ '<%= @tags.join("', '") -%>' ], width: '250px' });