decidim-plans 0.16.6 → 0.16.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/app/assets/javascripts/decidim/plans/admin/plans.js.es6 +93 -1
- data/app/assets/javascripts/decidim/plans/multifield/dynamic_fields.component.js.es6 +39 -0
- data/app/assets/javascripts/decidim/plans/multifield.js.es6 +1 -0
- data/app/cells/decidim/plans/plan_m/tags.erb +1 -0
- data/app/cells/decidim/plans/plan_m_cell.rb +1 -1
- data/app/cells/decidim/plans/tags/show.erb +7 -0
- data/app/cells/decidim/plans/tags/taggings.erb +3 -0
- data/app/cells/decidim/plans/tags_cell.rb +52 -0
- data/app/commands/decidim/plans/admin/answer_plan.rb +3 -0
- data/app/commands/decidim/plans/admin/create_tag.rb +44 -0
- data/app/commands/decidim/plans/admin/destroy_tag.rb +44 -0
- data/app/commands/decidim/plans/admin/update_plan_taggings.rb +53 -0
- data/app/commands/decidim/plans/admin/update_tag.rb +47 -0
- data/app/commands/decidim/plans/close_plan.rb +9 -1
- data/app/commands/decidim/plans/reopen_plan.rb +9 -1
- data/app/controllers/decidim/plans/admin/plans_controller.rb +32 -2
- data/app/controllers/decidim/plans/admin/tags_controller.rb +126 -0
- data/app/controllers/decidim/plans/plans_controller.rb +7 -2
- data/app/forms/decidim/plans/admin/tag_form.rb +22 -0
- data/app/forms/decidim/plans/admin/taggings_form.rb +20 -0
- data/app/helpers/decidim/plans/attached_proposals_helper.rb +18 -2
- data/app/helpers/decidim/plans/plan_cells_helper.rb +1 -1
- data/app/models/decidim/plans/plan.rb +14 -0
- data/app/models/decidim/plans/plan_tagging.rb +13 -0
- data/app/models/decidim/plans/tag.rb +20 -0
- data/app/permissions/decidim/plans/admin/permissions.rb +14 -4
- data/app/permissions/decidim/plans/permissions.rb +3 -1
- data/app/presenters/decidim/plans/plan_presenter.rb +4 -0
- data/app/queries/decidim/plans/component_plan_tags.rb +35 -0
- data/app/queries/decidim/plans/organization_tags.rb +25 -0
- data/app/services/decidim/plans/plan_search.rb +6 -0
- data/app/views/decidim/plans/admin/plans/_plan-tr.html.erb +13 -2
- data/app/views/decidim/plans/admin/plans/index.html.erb +9 -0
- data/app/views/decidim/plans/admin/plans/taggings.html.erb +67 -0
- data/app/views/decidim/plans/admin/tags/_form.html.erb +21 -0
- data/app/views/decidim/plans/admin/tags/edit.html.erb +7 -0
- data/app/views/decidim/plans/admin/tags/index.html.erb +52 -0
- data/app/views/decidim/plans/admin/tags/new.html.erb +7 -0
- data/app/views/decidim/plans/plans/_evaluation_modal.html.erb +22 -0
- data/app/views/decidim/plans/plans/_filters.html.erb +4 -0
- data/app/views/decidim/plans/plans/show.html.erb +9 -1
- data/app/views/decidim/plans/shared/_attachments.html.erb +2 -2
- data/app/views/decidim/plans/shared/_tags.html.erb +1 -0
- data/config/locales/en.yml +57 -2
- data/config/locales/fi.yml +57 -2
- data/config/locales/sv.yml +57 -2
- data/db/migrate/20190329161710_fix_plan_closing_workflow_states.rb +13 -0
- data/db/migrate/20190331141058_create_decidim_plans_tags_and_plan_taggings.rb +17 -0
- data/lib/decidim/content_parsers/plan_parser.rb +82 -0
- data/lib/decidim/content_renderers/plan_renderer.rb +33 -0
- data/lib/decidim/plans/admin_engine.rb +3 -0
- data/lib/decidim/plans/component.rb +11 -2
- data/lib/decidim/plans/engine.rb +6 -0
- data/lib/decidim/plans/test/factories.rb +17 -0
- data/lib/decidim/plans/version.rb +1 -1
- data/lib/decidim/plans.rb +8 -0
- metadata +29 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 210bbe22dc50de4ec472503edc4ec7cc7944ccf4623cbd0602ba2f56ac73c59c
|
4
|
+
data.tar.gz: 4b6ba7db25df3fc75fcd770511918ad71aeb38247769f0df384b2090f7d7d389
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2c04c5480bad9093b12345eedb2ae702867fa770b3a76eb7b548349620492db1997091c453424f1e5b01f7640a7a404e13cb80d4d1790921bafce4faa4fd79e
|
7
|
+
data.tar.gz: 374f57e0e4ce29c5ea888c631b3b6623251a24dbd58890292977d9f9dec60ff7631fb5ea57d781ec4e95b7a30ee20f59481e944826234b571d95a5c8bd2a2147
|
data/README.md
CHANGED
@@ -59,7 +59,8 @@ can start writing the plans when plan creation is enabled.
|
|
59
59
|
|
60
60
|
## Contributing
|
61
61
|
|
62
|
-
For instructions how to setup your development environment for Decidim, see
|
62
|
+
For instructions how to setup your development environment for Decidim, see
|
63
|
+
[Decidim](https://github.com/decidim/decidim). Also follow Decidim's general
|
63
64
|
instructions for development for this project as well.
|
64
65
|
|
65
66
|
### Developing
|
@@ -1,3 +1,95 @@
|
|
1
1
|
$(() => {
|
2
|
-
|
2
|
+
const $search = $("#data_picker-autocomplete");
|
3
|
+
const $results = $("#plan-tags-results");
|
4
|
+
const $template = $(".decidim-template", $results);
|
5
|
+
const $form = $search.parents("form");
|
6
|
+
const addRowItem = function(id, title) {
|
7
|
+
let template = $template.html();
|
8
|
+
template = template.replace(new RegExp("{{tag_id}}", "g"), id);
|
9
|
+
template = template.replace(new RegExp("{{tag_name}}", "g"), title);
|
10
|
+
const $newRow = $(template);
|
11
|
+
$("table tbody", $results).append($newRow);
|
12
|
+
$results.removeClass("hide");
|
13
|
+
|
14
|
+
// Add it to the autocomplete form
|
15
|
+
const $field = $(`<input type="hidden" name="tags[]" value="${id}">`);
|
16
|
+
$form.append($field);
|
17
|
+
|
18
|
+
// Listen to the click event on the remove button
|
19
|
+
$(".remove-tagging", $newRow).on("click", function(ev) {
|
20
|
+
ev.preventDefault();
|
21
|
+
$newRow.remove();
|
22
|
+
$field.remove();
|
23
|
+
|
24
|
+
if ($("table tbody tr", $results).length < 1) {
|
25
|
+
$results.addClass("hide");
|
26
|
+
}
|
27
|
+
});
|
28
|
+
};
|
29
|
+
let xhr = null;
|
30
|
+
let currentSearch = "";
|
31
|
+
|
32
|
+
$search.on("keyup", function() {
|
33
|
+
currentSearch = $search.val();
|
34
|
+
});
|
35
|
+
|
36
|
+
$search.autoComplete({
|
37
|
+
minChars: 2,
|
38
|
+
cache: 0,
|
39
|
+
source: function(term, response) {
|
40
|
+
try {
|
41
|
+
xhr.abort();
|
42
|
+
} catch (exception) { xhr = null; }
|
43
|
+
|
44
|
+
const url = $form.attr("action");
|
45
|
+
xhr = $.getJSON(
|
46
|
+
url,
|
47
|
+
$form.serializeArray(),
|
48
|
+
function(data) {
|
49
|
+
if (data.length > 0) {
|
50
|
+
response(data);
|
51
|
+
} else {
|
52
|
+
response([
|
53
|
+
[null, $search.data("no-results-text"), term]
|
54
|
+
]);
|
55
|
+
}
|
56
|
+
}
|
57
|
+
);
|
58
|
+
},
|
59
|
+
renderItem: function (item, search) {
|
60
|
+
const sanitizedSearch = search.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
61
|
+
const re = new RegExp(`(${sanitizedSearch.split(" ").join("|")})`, "gi");
|
62
|
+
const modelId = item[0];
|
63
|
+
const title = item[1];
|
64
|
+
const val = `${title}`;
|
65
|
+
|
66
|
+
if (modelId === null) {
|
67
|
+
// Empty result
|
68
|
+
const term = item[2];
|
69
|
+
const url = $search.data("no-results-url").replace("{{term}}", encodeURIComponent(term));
|
70
|
+
return `<div><a href="${url}">${val.replace("{{term}}", term)}</a></div>`;
|
71
|
+
}
|
72
|
+
return `<div class="autocomplete-suggestion" data-model-id="${modelId}" data-val="${title}">${val.replace(re, "<b>$1</b>")}</div>`;
|
73
|
+
},
|
74
|
+
onSelect: function(event, term, item) {
|
75
|
+
const $suggestions = $search.data("sc");
|
76
|
+
const modelId = item.data("modelId");
|
77
|
+
const title = item.data("val");
|
78
|
+
|
79
|
+
addRowItem(modelId, title);
|
80
|
+
|
81
|
+
$search.val(currentSearch);
|
82
|
+
setTimeout(function() {
|
83
|
+
$(`[data-model-id="${modelId}"]`, $suggestions).remove();
|
84
|
+
$suggestions.show();
|
85
|
+
}, 20);
|
86
|
+
}
|
87
|
+
});
|
88
|
+
|
89
|
+
const resultsArray = $results.data("results");
|
90
|
+
if (Array.isArray(resultsArray)) {
|
91
|
+
resultsArray.forEach((value) => {
|
92
|
+
addRowItem(value[0], value[1]);
|
93
|
+
});
|
94
|
+
}
|
3
95
|
});
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/**
|
2
|
+
* Extends / overrides:
|
3
|
+
* decidim/admin/dynamic_fields.component
|
4
|
+
*
|
5
|
+
* Fixes broken attachments in IE11 by overriding the `_addField` method in the
|
6
|
+
*`DynamicFieldsComponent` coming from the `decidim-admin` component.
|
7
|
+
*
|
8
|
+
* For further details, see:
|
9
|
+
* https://github.com/mainio/decidim-module-plans/issues/13
|
10
|
+
**/
|
11
|
+
|
12
|
+
((exports) => {
|
13
|
+
const { DynamicFieldsComponent } = exports.DecidimAdmin;
|
14
|
+
|
15
|
+
class DynamicFieldsComponentExtended extends DynamicFieldsComponent {
|
16
|
+
_addField() {
|
17
|
+
const $container = $(this.wrapperSelector).find(this.containerSelector);
|
18
|
+
// START OVERRIDE
|
19
|
+
const $template = $(this.wrapperSelector).children(".decidim-template");
|
20
|
+
// END OVERRIDE
|
21
|
+
const $newField = $($template.html()).template(this.placeholderId, this._getUID());
|
22
|
+
|
23
|
+
$newField.find("ul.tabs").attr("data-tabs", true);
|
24
|
+
|
25
|
+
$newField.appendTo($container);
|
26
|
+
$newField.foundation();
|
27
|
+
|
28
|
+
if (this.onAddField) {
|
29
|
+
this.onAddField($newField);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
exports.DecidimAdmin = exports.DecidimAdmin || {};
|
35
|
+
exports.DecidimAdmin.DynamicFieldsComponent = DynamicFieldsComponentExtended;
|
36
|
+
exports.DecidimAdmin.createDynamicFields = (options) => {
|
37
|
+
return new DynamicFieldsComponentExtended(options);
|
38
|
+
};
|
39
|
+
})(window);
|
@@ -1,5 +1,6 @@
|
|
1
1
|
// = require decidim/admin/auto_buttons_by_position.component
|
2
2
|
// = require decidim/admin/auto_label_by_position.component
|
3
3
|
// = require decidim/admin/dynamic_fields.component
|
4
|
+
// = require decidim/plans/multifield/dynamic_fields.component
|
4
5
|
// = require decidim/admin/sort_list.component
|
5
6
|
// = require decidim/plans/multifield/component
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render partial: "decidim/plans/shared/tags.html", locals: { resource: model, tags_class_extra: "tags--proposal" } %>
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Plans
|
5
|
+
# This cell renders:
|
6
|
+
# - The category of a resource shown with the translated name (parent)
|
7
|
+
# - The scope of a resource shown with the translated name (parent)
|
8
|
+
# - The assigned tags from the plans
|
9
|
+
#
|
10
|
+
# The context `resource` must be present example use inside another `cell`:
|
11
|
+
# <%= cell("decidim/category", model.category, context: {resource: model}) %>
|
12
|
+
#
|
13
|
+
class TagsCell < Decidim::TagsCell
|
14
|
+
def show
|
15
|
+
render if category? || scope? || taggings?
|
16
|
+
end
|
17
|
+
|
18
|
+
def taggings
|
19
|
+
render if taggings?
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def category?
|
25
|
+
model.category.present?
|
26
|
+
end
|
27
|
+
|
28
|
+
def scope?
|
29
|
+
has_visible_scopes?(model)
|
30
|
+
end
|
31
|
+
|
32
|
+
def taggings?
|
33
|
+
model.tags.any?
|
34
|
+
end
|
35
|
+
|
36
|
+
def link_to_tag(tag)
|
37
|
+
end
|
38
|
+
|
39
|
+
def link_to_tag(tag)
|
40
|
+
link_to tag_name(tag), tag_path(tag)
|
41
|
+
end
|
42
|
+
|
43
|
+
def tag_name(tag)
|
44
|
+
translated_attribute(tag.name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def tag_path(tag)
|
48
|
+
resource_locator(model).index(filter: { tag_id: [tag.id] })
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Plans
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when a user creates a new tag.
|
7
|
+
class CreateTag < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A form object with the params.
|
11
|
+
def initialize(form)
|
12
|
+
@form = form
|
13
|
+
end
|
14
|
+
|
15
|
+
# Executes the command. Broadcasts these events:
|
16
|
+
#
|
17
|
+
# - :ok when everything is valid, together with the tag.
|
18
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
def call
|
22
|
+
return broadcast(:invalid) if form.invalid?
|
23
|
+
|
24
|
+
create_tag
|
25
|
+
|
26
|
+
broadcast(:ok, tag)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :form, :tag
|
32
|
+
|
33
|
+
def create_tag
|
34
|
+
@tag = Decidim.traceability.create(
|
35
|
+
Tag,
|
36
|
+
form.current_user,
|
37
|
+
name: form.name,
|
38
|
+
organization: form.organization
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Plans
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when a user destroys a tag.
|
7
|
+
class DestroyTag < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# tag - The target object to be destroyed.
|
11
|
+
# current_user - the user performing the action.
|
12
|
+
def initialize(tag, current_user)
|
13
|
+
@tag = tag
|
14
|
+
@current_user = current_user
|
15
|
+
end
|
16
|
+
|
17
|
+
# Destroys the tag if valid.
|
18
|
+
#
|
19
|
+
# Broadcasts :ok if successful, :invalid otherwise.
|
20
|
+
#
|
21
|
+
# Returns nothing.
|
22
|
+
def call
|
23
|
+
destroy_tag
|
24
|
+
|
25
|
+
broadcast(:ok)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :tag, :current_user
|
31
|
+
|
32
|
+
def destroy_tag
|
33
|
+
Decidim.traceability.perform_action!(
|
34
|
+
:delete,
|
35
|
+
tag,
|
36
|
+
current_user
|
37
|
+
) do
|
38
|
+
tag.destroy!
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Plans
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when a user updates a tag.
|
7
|
+
class UpdatePlanTaggings < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A form object with the params.
|
11
|
+
# plan - The target object to be updated.
|
12
|
+
def initialize(form, plan)
|
13
|
+
@form = form
|
14
|
+
@plan = plan
|
15
|
+
end
|
16
|
+
|
17
|
+
# Executes the command. Broadcasts these events:
|
18
|
+
#
|
19
|
+
# - :ok when everything is valid, together with the plan.
|
20
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
def call
|
24
|
+
return broadcast(:invalid) if form.invalid?
|
25
|
+
|
26
|
+
update_plan_taggings
|
27
|
+
|
28
|
+
broadcast(:ok, plan)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :form, :plan
|
34
|
+
|
35
|
+
def update_plan_taggings
|
36
|
+
Decidim.traceability.perform_action!(
|
37
|
+
:update,
|
38
|
+
plan,
|
39
|
+
form.current_user
|
40
|
+
) do
|
41
|
+
plan.taggings.destroy_all
|
42
|
+
plan.update!(
|
43
|
+
tags: Tag.where(
|
44
|
+
id: form.tags,
|
45
|
+
organization: plan.component.organization
|
46
|
+
)
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Plans
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when a user updates a tag.
|
7
|
+
class UpdateTag < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A form object with the params.
|
11
|
+
# tag - The target object to be updated.
|
12
|
+
def initialize(form, tag)
|
13
|
+
@form = form
|
14
|
+
@tag = tag
|
15
|
+
end
|
16
|
+
|
17
|
+
# Executes the command. Broadcasts these events:
|
18
|
+
#
|
19
|
+
# - :ok when everything is valid, together with the plan.
|
20
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
21
|
+
#
|
22
|
+
# Returns nothing.
|
23
|
+
def call
|
24
|
+
return broadcast(:invalid) if form.invalid?
|
25
|
+
|
26
|
+
update_tag
|
27
|
+
|
28
|
+
broadcast(:ok, tag)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :form, :tag
|
34
|
+
|
35
|
+
def update_tag
|
36
|
+
Decidim.traceability.perform_action!(
|
37
|
+
:update,
|
38
|
+
tag,
|
39
|
+
form.current_user
|
40
|
+
) do
|
41
|
+
tag.update!(name: form.name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -36,7 +36,15 @@ module Decidim
|
|
36
36
|
@current_user,
|
37
37
|
visibility: "public-only"
|
38
38
|
) do
|
39
|
-
|
39
|
+
# Unless the plan has already been answered, change the state to
|
40
|
+
# "evaluating".
|
41
|
+
state = @plan.state
|
42
|
+
state = "evaluating" unless @plan.answered?
|
43
|
+
|
44
|
+
@plan.update!(
|
45
|
+
state: state,
|
46
|
+
closed_at: Time.current
|
47
|
+
)
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -36,7 +36,15 @@ module Decidim
|
|
36
36
|
@current_user,
|
37
37
|
visibility: "public-only"
|
38
38
|
) do
|
39
|
-
|
39
|
+
# Unless the plan has already been answered, change the state back to
|
40
|
+
# "open".
|
41
|
+
state = @plan.state
|
42
|
+
state = "open" unless @plan.answered?
|
43
|
+
|
44
|
+
@plan.update!(
|
45
|
+
state: state,
|
46
|
+
closed_at: nil
|
47
|
+
)
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -11,7 +11,7 @@ module Decidim
|
|
11
11
|
helper Plans::ApplicationHelper
|
12
12
|
helper Plans::AttachmentsHelper
|
13
13
|
helper Plans::RemainingCharactersHelper
|
14
|
-
helper_method :plans, :query, :form_presenter, :attached_proposals_picker_field
|
14
|
+
helper_method :plans, :plan, :query, :counts, :form_presenter, :attached_proposals_picker_field
|
15
15
|
|
16
16
|
def new
|
17
17
|
enforce_permission_to :create, :plans
|
@@ -89,16 +89,46 @@ module Decidim
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
+
def taggings
|
93
|
+
enforce_permission_to :edit_taggings, :plan, plan: plan
|
94
|
+
|
95
|
+
@form = form(Admin::TaggingsForm).from_model(plan)
|
96
|
+
end
|
97
|
+
|
98
|
+
def update_taggings
|
99
|
+
enforce_permission_to :edit_taggings, :plan, plan: plan
|
100
|
+
|
101
|
+
@form = form(Admin::TaggingsForm).from_params(params)
|
102
|
+
Admin::UpdatePlanTaggings.call(@form, plan) do
|
103
|
+
on(:ok) do
|
104
|
+
flash[:notice] = I18n.t("plans.update_taggings.success", scope: "decidim.plans.admin")
|
105
|
+
redirect_to plans_path
|
106
|
+
end
|
107
|
+
|
108
|
+
on(:invalid) do
|
109
|
+
flash.now[:alert] = I18n.t("plans.update_taggings.invalid", scope: "decidim.plans.admin")
|
110
|
+
render :taggings
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
92
115
|
private
|
93
116
|
|
94
117
|
def query
|
95
|
-
@query ||= Plan.where(component: current_component).ransack(params[:q])
|
118
|
+
@query ||= Plan.published.where(component: current_component).ransack(params[:q])
|
96
119
|
end
|
97
120
|
|
98
121
|
def plans
|
99
122
|
@plans ||= query.result.page(params[:page]).per(15)
|
100
123
|
end
|
101
124
|
|
125
|
+
def counts
|
126
|
+
@counts ||= {
|
127
|
+
published: Plan.published.where(component: current_component).count,
|
128
|
+
drafts: Plan.drafts.where(component: current_component).count
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
102
132
|
def plan
|
103
133
|
@plan ||= Plan.where(component: current_component).find(params[:id])
|
104
134
|
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Plans
|
5
|
+
module Admin
|
6
|
+
# This controller allows admins to the tags related to plans.
|
7
|
+
class TagsController < Admin::ApplicationController
|
8
|
+
include TranslatableAttributes
|
9
|
+
|
10
|
+
helper_method :plan, :tags
|
11
|
+
|
12
|
+
def index
|
13
|
+
enforce_permission_to :read, :plan_tag
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html do
|
17
|
+
render :index
|
18
|
+
end
|
19
|
+
format.json do
|
20
|
+
return render json: [] unless params.has_key?(:term)
|
21
|
+
|
22
|
+
tags = OrganizationTags.new(current_organization).query.where(
|
23
|
+
"name ->> '#{current_locale}' ILIKE ?",
|
24
|
+
"%#{params[:term]}%"
|
25
|
+
).where.not(
|
26
|
+
id: plan.tags.pluck(:id)
|
27
|
+
)
|
28
|
+
render json: tags.map { |t| [t.id, translated_attribute(t.name)] }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def new
|
34
|
+
enforce_permission_to :create, :plan_tags
|
35
|
+
|
36
|
+
dummy_tag = Tag.new(organization: current_organization)
|
37
|
+
dummy_tag.name = {}
|
38
|
+
current_organization.available_locales.map do |locale|
|
39
|
+
dummy_tag.name[locale] = params[:name]
|
40
|
+
end
|
41
|
+
|
42
|
+
@form = form(Admin::TagForm).from_model(dummy_tag)
|
43
|
+
@form.back_to_plan = true if params[:back_to_plan].to_i == 1
|
44
|
+
end
|
45
|
+
|
46
|
+
def create
|
47
|
+
enforce_permission_to :create, :plan_tags
|
48
|
+
@form = form(Admin::TagForm).from_params(params)
|
49
|
+
|
50
|
+
Admin::CreateTag.call(@form) do
|
51
|
+
on(:ok) do
|
52
|
+
flash[:notice] = I18n.t("create.success", scope: i18n_flashes_scope)
|
53
|
+
|
54
|
+
return redirect_to taggings_plan_path(plan) if @form.back_to_plan
|
55
|
+
|
56
|
+
redirect_to plan_tags_path(plan)
|
57
|
+
end
|
58
|
+
|
59
|
+
on(:invalid) do
|
60
|
+
flash.now[:alert] = I18n.t("create.invalid", scope: i18n_flashes_scope)
|
61
|
+
render action: "new"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def edit
|
67
|
+
enforce_permission_to :edit, :plan_tags, tag: tag
|
68
|
+
@form = form(Admin::TagForm).from_model(tag)
|
69
|
+
end
|
70
|
+
|
71
|
+
def update
|
72
|
+
enforce_permission_to :edit, :plan_tags, tag: tag
|
73
|
+
|
74
|
+
@form = form(Admin::TagForm).from_params(params)
|
75
|
+
Admin::UpdateTag.call(@form, @tag) do
|
76
|
+
on(:ok) do
|
77
|
+
flash[:notice] = I18n.t("update.success", scope: i18n_flashes_scope)
|
78
|
+
redirect_to plan_tags_path(plan)
|
79
|
+
end
|
80
|
+
|
81
|
+
on(:invalid) do
|
82
|
+
flash.now[:alert] = I18n.t("update.invalid", scope: i18n_flashes_scope)
|
83
|
+
render :edit
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def destroy
|
89
|
+
enforce_permission_to :destroy, :plan_tags, tag: tag
|
90
|
+
|
91
|
+
Admin::DestroyTag.call(@tag, current_user) do
|
92
|
+
on(:ok) do
|
93
|
+
flash[:notice] = I18n.t("destroy.success", scope: i18n_flashes_scope)
|
94
|
+
redirect_to plan_tags_path(plan)
|
95
|
+
end
|
96
|
+
|
97
|
+
on(:invalid) do
|
98
|
+
flash.now[:alert] = I18n.t("destroy.error", scope: i18n_flashes_scope)
|
99
|
+
redirect_to plan_tags_path(plan)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def i18n_flashes_scope
|
107
|
+
"decidim.plans.admin.tags"
|
108
|
+
end
|
109
|
+
|
110
|
+
def tag
|
111
|
+
@tag ||= Tag.where(organization: current_organization).find(params[:id])
|
112
|
+
end
|
113
|
+
|
114
|
+
def plan
|
115
|
+
@plan ||= Plan.where(component: current_component).find(params[:plan_id])
|
116
|
+
end
|
117
|
+
|
118
|
+
def tags
|
119
|
+
@tags ||= OrganizationTags.new(
|
120
|
+
current_organization
|
121
|
+
).query.page(params[:page]).per(30)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|