decidim-assemblies 0.24.1 → 0.25.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/assemblies/assembly_m_cell.rb +1 -1
  3. data/app/cells/decidim/assemblies/assembly_member/show.erb +1 -1
  4. data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb +1 -1
  5. data/app/commands/decidim/assemblies/admin/copy_assembly.rb +11 -3
  6. data/app/commands/decidim/assemblies/admin/create_assembly.rb +2 -1
  7. data/app/commands/decidim/assemblies/admin/create_assembly_member.rb +5 -1
  8. data/app/commands/decidim/assemblies/admin/update_assembly.rb +7 -11
  9. data/app/controllers/decidim/assemblies/admin/assemblies_controller.rb +1 -5
  10. data/app/forms/decidim/assemblies/admin/assembly_form.rb +3 -2
  11. data/app/forms/decidim/assemblies/admin/assembly_import_form.rb +1 -0
  12. data/app/forms/decidim/assemblies/admin/assembly_member_form.rb +1 -1
  13. data/app/helpers/decidim/assemblies/admin/assemblies_admin_menu_helper.rb +0 -5
  14. data/app/models/decidim/assembly.rb +5 -5
  15. data/app/models/decidim/assembly_member.rb +1 -1
  16. data/app/packs/entrypoints/decidim_assemblies.js +5 -0
  17. data/app/packs/entrypoints/decidim_assemblies_admin.js +3 -0
  18. data/app/{assets/images/decidim/assemblies/assembly.svg → packs/images/decidim/assemblies/decidim_assemblies.svg} +0 -0
  19. data/app/packs/src/decidim/assemblies/admin/assemblies.js +63 -0
  20. data/app/{assets/javascripts/decidim/assemblies/admin/assembly_members.js.es6 → packs/src/decidim/assemblies/admin/assembly_members.js} +3 -3
  21. data/app/packs/src/decidim/assemblies/assemblies.js +14 -0
  22. data/app/packs/src/decidim/assemblies/orgchart.js +695 -0
  23. data/app/presenters/decidim/assemblies/assembly_presenter.rb +2 -12
  24. data/app/presenters/decidim/assemblies/assembly_stats_presenter.rb +3 -13
  25. data/app/queries/decidim/assemblies/admin/admin_users.rb +24 -11
  26. data/app/serializers/decidim/assemblies/assembly_importer.rb +3 -2
  27. data/app/serializers/decidim/assemblies/assembly_serializer.rb +4 -2
  28. data/app/views/decidim/assemblies/admin/assemblies/_form.html.erb +6 -3
  29. data/app/views/decidim/assemblies/admin/assemblies_types/index.html.erb +1 -1
  30. data/app/views/decidim/assemblies/admin/assembly_copies/_form.html.erb +1 -1
  31. data/app/views/decidim/assemblies/admin/assembly_imports/_form.html.erb +1 -1
  32. data/app/views/decidim/assemblies/admin/assembly_members/_form.html.erb +2 -2
  33. data/app/views/decidim/assemblies/assemblies/_promoted_assembly.html.erb +1 -1
  34. data/app/views/decidim/assemblies/assemblies/index.html.erb +2 -2
  35. data/app/views/decidim/assemblies/assemblies/show.html.erb +6 -4
  36. data/app/views/layouts/decidim/_assembly_header.html.erb +1 -1
  37. data/app/views/layouts/decidim/admin/assemblies.html.erb +1 -1
  38. data/app/views/layouts/decidim/admin/assembly.html.erb +4 -73
  39. data/app/views/layouts/decidim/assembly.html.erb +2 -2
  40. data/config/assets.rb +9 -0
  41. data/config/locales/ar.yml +0 -17
  42. data/config/locales/ca.yml +4 -38
  43. data/config/locales/cs.yml +6 -40
  44. data/config/locales/de.yml +4 -38
  45. data/config/locales/el.yml +0 -31
  46. data/config/locales/en.yml +5 -39
  47. data/config/locales/es-MX.yml +4 -38
  48. data/config/locales/es-PY.yml +4 -38
  49. data/config/locales/es.yml +4 -38
  50. data/config/locales/eu.yml +0 -17
  51. data/config/locales/fi-plain.yml +5 -39
  52. data/config/locales/fi.yml +5 -39
  53. data/config/locales/fr-CA.yml +1 -39
  54. data/config/locales/fr-LU.yml +449 -0
  55. data/config/locales/fr.yml +0 -38
  56. data/config/locales/gl.yml +4 -28
  57. data/config/locales/hu.yml +0 -31
  58. data/config/locales/id-ID.yml +0 -17
  59. data/config/locales/is-IS.yml +0 -14
  60. data/config/locales/it.yml +6 -32
  61. data/config/locales/ja.yml +5 -31
  62. data/config/locales/lb-LU.yml +1 -0
  63. data/config/locales/lv.yml +0 -30
  64. data/config/locales/nl.yml +5 -39
  65. data/config/locales/no.yml +0 -31
  66. data/config/locales/pl.yml +6 -43
  67. data/config/locales/pt-BR.yml +82 -17
  68. data/config/locales/pt.yml +0 -31
  69. data/config/locales/ro-RO.yml +5 -36
  70. data/config/locales/ru.yml +0 -17
  71. data/config/locales/sk.yml +0 -16
  72. data/config/locales/sl.yml +0 -17
  73. data/config/locales/sr-CS.yml +0 -16
  74. data/config/locales/sv.yml +3 -36
  75. data/config/locales/tr-TR.yml +0 -31
  76. data/config/locales/uk.yml +0 -17
  77. data/config/locales/zh-CN.yml +0 -31
  78. data/db/migrate/20210507063604_add_announcement_to_assemblies.rb +7 -0
  79. data/lib/decidim/api/assembly_type.rb +10 -1
  80. data/lib/decidim/assemblies/admin_engine.rb +122 -30
  81. data/lib/decidim/assemblies/engine.rb +6 -9
  82. data/lib/decidim/assemblies/participatory_space.rb +46 -8
  83. data/lib/decidim/assemblies/test/factories.rb +1 -0
  84. data/lib/decidim/assemblies/version.rb +1 -1
  85. metadata +21 -22
  86. data/app/assets/config/admin/decidim_assemblies_manifest.js +0 -2
  87. data/app/assets/config/decidim_assemblies_manifest.js +0 -2
  88. data/app/assets/javascripts/decidim/assemblies/admin/assemblies.js.es6 +0 -67
  89. data/app/assets/javascripts/decidim/assemblies/assemblies.js.es6 +0 -18
  90. data/app/assets/javascripts/decidim/assemblies/orgchart.js.es6 +0 -698
  91. data/app/cells/decidim/assemblies/statistic/show.erb +0 -9
  92. data/app/cells/decidim/assemblies/statistic_cell.rb +0 -20
  93. data/app/cells/decidim/assemblies/statistics/show.erb +0 -17
  94. data/app/cells/decidim/assemblies/statistics_cell.rb +0 -18
  95. data/config/locales/ja-JP.yml +0 -471
@@ -39,10 +39,6 @@ module Decidim
39
39
  end
40
40
  end
41
41
 
42
- initializer "decidim_assemblies.assets" do |app|
43
- app.config.assets.precompile += %w(decidim_assemblies_manifest.js)
44
- end
45
-
46
42
  initializer "decidim_assemblies.add_cells_view_paths" do
47
43
  Cell::ViewModel.view_paths << File.expand_path("#{Decidim::Assemblies::Engine.root}/app/cells")
48
44
  Cell::ViewModel.view_paths << File.expand_path("#{Decidim::Assemblies::Engine.root}/app/views") # for partials
@@ -56,11 +52,12 @@ module Decidim
56
52
 
57
53
  initializer "decidim_assemblies.menu" do
58
54
  Decidim.menu :menu do |menu|
59
- menu.item I18n.t("menu.assemblies", scope: "decidim"),
60
- decidim_assemblies.assemblies_path,
61
- position: 2.2,
62
- if: OrganizationPublishedAssemblies.new(current_organization, current_user).any?,
63
- active: :inclusive
55
+ menu.add_item :assemblies,
56
+ I18n.t("menu.assemblies", scope: "decidim"),
57
+ decidim_assemblies.assemblies_path,
58
+ position: 2.2,
59
+ if: OrganizationPublishedAssemblies.new(current_organization, current_user).any?,
60
+ active: :inclusive
64
61
  end
65
62
  end
66
63
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Decidim.register_participatory_space(:assemblies) do |participatory_space|
4
- participatory_space.icon = "decidim/assemblies/assembly.svg"
4
+ participatory_space.icon = "media/images/decidim_assemblies.svg"
5
5
  participatory_space.model_class_name = "Decidim::Assembly"
6
6
 
7
7
  participatory_space.participatory_spaces do |organization|
@@ -66,8 +66,18 @@ Decidim.register_participatory_space(:assemblies) do |participatory_space|
66
66
  Decidim::Faker::Localized.paragraph(sentence_count: 3)
67
67
  end,
68
68
  organization: organization,
69
- hero_image: File.new(File.join(seeds_root, "city.jpeg")), # Keep after organization
70
- banner_image: File.new(File.join(seeds_root, "city2.jpeg")), # Keep after organization
69
+ hero_image: ActiveStorage::Blob.create_after_upload!(
70
+ io: File.open(File.join(seeds_root, "city.jpeg")),
71
+ filename: "hero_image.jpeg",
72
+ content_type: "image/jpeg",
73
+ metadata: nil
74
+ ), # Keep after organization
75
+ banner_image: ActiveStorage::Blob.create_after_upload!(
76
+ io: File.open(File.join(seeds_root, "city2.jpeg")),
77
+ filename: "banner_image.jpeg",
78
+ content_type: "image/jpeg",
79
+ metadata: nil
80
+ ), # Keep after organization
71
81
  promoted: true,
72
82
  published_at: 2.weeks.ago,
73
83
  meta_scope: Decidim::Faker::Localized.word,
@@ -149,8 +159,18 @@ Decidim.register_participatory_space(:assemblies) do |participatory_space|
149
159
  Decidim::Faker::Localized.paragraph(sentence_count: 3)
150
160
  end,
151
161
  organization: organization,
152
- hero_image: File.new(File.join(seeds_root, "city.jpeg")), # Keep after organization
153
- banner_image: File.new(File.join(seeds_root, "city2.jpeg")), # Keep after organization
162
+ hero_image: ActiveStorage::Blob.create_after_upload!(
163
+ io: File.open(File.join(seeds_root, "city.jpeg")),
164
+ filename: "hero_image.jpeg",
165
+ content_type: "image/jpeg",
166
+ metadata: nil
167
+ ), # Keep after organization
168
+ banner_image: ActiveStorage::Blob.create_after_upload!(
169
+ io: File.open(File.join(seeds_root, "city2.jpeg")),
170
+ filename: "banner_image.jpeg",
171
+ content_type: "image/jpeg",
172
+ metadata: nil
173
+ ), # Keep after organization
154
174
  promoted: true,
155
175
  published_at: 2.weeks.ago,
156
176
  meta_scope: Decidim::Faker::Localized.word,
@@ -176,21 +196,39 @@ Decidim.register_participatory_space(:assemblies) do |participatory_space|
176
196
  description: Decidim::Faker::Localized.sentence(word_count: 5),
177
197
  attachment_collection: attachment_collection,
178
198
  attached_to: current_assembly,
179
- file: File.new(File.join(seeds_root, "Exampledocument.pdf")) # Keep after attached_to
199
+ content_type: "application/pdf",
200
+ file: ActiveStorage::Blob.create_after_upload!(
201
+ io: File.open(File.join(seeds_root, "Exampledocument.pdf")),
202
+ filename: "Exampledocument.pdf",
203
+ content_type: "application/pdf",
204
+ metadata: nil
205
+ ) # Keep after attached_to
180
206
  )
181
207
 
182
208
  Decidim::Attachment.create!(
183
209
  title: Decidim::Faker::Localized.sentence(word_count: 2),
184
210
  description: Decidim::Faker::Localized.sentence(word_count: 5),
185
211
  attached_to: current_assembly,
186
- file: File.new(File.join(seeds_root, "city.jpeg")) # Keep after attached_to
212
+ content_type: "image/jpeg",
213
+ file: ActiveStorage::Blob.create_after_upload!(
214
+ io: File.open(File.join(seeds_root, "city.jpeg")),
215
+ filename: "city.jpeg",
216
+ content_type: "image/jpeg",
217
+ metadata: nil
218
+ ) # Keep after attached_to
187
219
  )
188
220
 
189
221
  Decidim::Attachment.create!(
190
222
  title: Decidim::Faker::Localized.sentence(word_count: 2),
191
223
  description: Decidim::Faker::Localized.sentence(word_count: 5),
192
224
  attached_to: current_assembly,
193
- file: File.new(File.join(seeds_root, "Exampledocument.pdf")) # Keep after attached_to
225
+ content_type: "application/pdf",
226
+ file: ActiveStorage::Blob.create_after_upload!(
227
+ io: File.open(File.join(seeds_root, "Exampledocument.pdf")),
228
+ filename: "Exampledocument.pdf",
229
+ content_type: "application/pdf",
230
+ metadata: nil
231
+ ) # Keep after attached_to
194
232
  )
195
233
 
196
234
  2.times do
@@ -54,6 +54,7 @@ FactoryBot.define do
54
54
  youtube_handler { "others" }
55
55
  github_handler { "others" }
56
56
  weight { 1 }
57
+ announcement { generate_localized_title }
57
58
 
58
59
  trait :with_type do
59
60
  assembly_type { create :assemblies_type, organization: organization }
@@ -4,7 +4,7 @@ module Decidim
4
4
  # This holds the decidim-assemblies version.
5
5
  module Assemblies
6
6
  def self.version
7
- "0.24.1"
7
+ "0.25.0.rc2"
8
8
  end
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-assemblies
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.1
4
+ version: 0.25.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josep Jaume Rey Peroy
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-04-08 00:00:00.000000000 Z
13
+ date: 2021-09-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: decidim-core
@@ -18,42 +18,42 @@ dependencies:
18
18
  requirements:
19
19
  - - '='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.24.1
21
+ version: 0.25.0.rc2
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '='
27
27
  - !ruby/object:Gem::Version
28
- version: 0.24.1
28
+ version: 0.25.0.rc2
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: decidim-admin
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
33
  - - '='
34
34
  - !ruby/object:Gem::Version
35
- version: 0.24.1
35
+ version: 0.25.0.rc2
36
36
  type: :development
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - '='
41
41
  - !ruby/object:Gem::Version
42
- version: 0.24.1
42
+ version: 0.25.0.rc2
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: decidim-dev
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - '='
48
48
  - !ruby/object:Gem::Version
49
- version: 0.24.1
49
+ version: 0.25.0.rc2
50
50
  type: :development
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
54
  - - '='
55
55
  - !ruby/object:Gem::Version
56
- version: 0.24.1
56
+ version: 0.25.0.rc2
57
57
  description: Assemblies component for decidim.
58
58
  email:
59
59
  - josepjaume@gmail.com
@@ -65,13 +65,6 @@ extra_rdoc_files: []
65
65
  files:
66
66
  - README.md
67
67
  - Rakefile
68
- - app/assets/config/admin/decidim_assemblies_manifest.js
69
- - app/assets/config/decidim_assemblies_manifest.js
70
- - app/assets/images/decidim/assemblies/assembly.svg
71
- - app/assets/javascripts/decidim/assemblies/admin/assemblies.js.es6
72
- - app/assets/javascripts/decidim/assemblies/admin/assembly_members.js.es6
73
- - app/assets/javascripts/decidim/assemblies/assemblies.js.es6
74
- - app/assets/javascripts/decidim/assemblies/orgchart.js.es6
75
68
  - app/cells/decidim/assemblies/assembly_cell.rb
76
69
  - app/cells/decidim/assemblies/assembly_m/footer.erb
77
70
  - app/cells/decidim/assemblies/assembly_m/tags.erb
@@ -82,10 +75,6 @@ files:
82
75
  - app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb
83
76
  - app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_settings_form/show.erb
84
77
  - app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_settings_form_cell.rb
85
- - app/cells/decidim/assemblies/statistic/show.erb
86
- - app/cells/decidim/assemblies/statistic_cell.rb
87
- - app/cells/decidim/assemblies/statistics/show.erb
88
- - app/cells/decidim/assemblies/statistics_cell.rb
89
78
  - app/cells/decidim/assembly_activity_cell.rb
90
79
  - app/commands/decidim/assemblies/admin/copy_assembly.rb
91
80
  - app/commands/decidim/assemblies/admin/create_assemblies_type.rb
@@ -152,6 +141,13 @@ files:
152
141
  - app/models/decidim/assembly.rb
153
142
  - app/models/decidim/assembly_member.rb
154
143
  - app/models/decidim/assembly_user_role.rb
144
+ - app/packs/entrypoints/decidim_assemblies.js
145
+ - app/packs/entrypoints/decidim_assemblies_admin.js
146
+ - app/packs/images/decidim/assemblies/decidim_assemblies.svg
147
+ - app/packs/src/decidim/assemblies/admin/assemblies.js
148
+ - app/packs/src/decidim/assemblies/admin/assembly_members.js
149
+ - app/packs/src/decidim/assemblies/assemblies.js
150
+ - app/packs/src/decidim/assemblies/orgchart.js
155
151
  - app/permissions/decidim/assemblies/permissions.rb
156
152
  - app/presenters/decidim/admin/assembly_member_presenter.rb
157
153
  - app/presenters/decidim/assemblies/admin_log/assemblies_setting_presenter.rb
@@ -223,6 +219,7 @@ files:
223
219
  - app/views/layouts/decidim/admin/assemblies.html.erb
224
220
  - app/views/layouts/decidim/admin/assembly.html.erb
225
221
  - app/views/layouts/decidim/assembly.html.erb
222
+ - config/assets.rb
226
223
  - config/locales/am-ET.yml
227
224
  - config/locales/ar-SA.yml
228
225
  - config/locales/ar.yml
@@ -249,6 +246,7 @@ files:
249
246
  - config/locales/fi-plain.yml
250
247
  - config/locales/fi.yml
251
248
  - config/locales/fr-CA.yml
249
+ - config/locales/fr-LU.yml
252
250
  - config/locales/fr.yml
253
251
  - config/locales/ga-IE.yml
254
252
  - config/locales/gl.yml
@@ -259,10 +257,10 @@ files:
259
257
  - config/locales/is-IS.yml
260
258
  - config/locales/is.yml
261
259
  - config/locales/it.yml
262
- - config/locales/ja-JP.yml
263
260
  - config/locales/ja.yml
264
261
  - config/locales/ko-KR.yml
265
262
  - config/locales/ko.yml
263
+ - config/locales/lb-LU.yml
266
264
  - config/locales/lt-LT.yml
267
265
  - config/locales/lt.yml
268
266
  - config/locales/lv.yml
@@ -311,6 +309,7 @@ files:
311
309
  - db/migrate/20200430202456_create_decidim_assemblies_settings.rb
312
310
  - db/migrate/20210204152393_add_weight_field_to_assembly.rb
313
311
  - db/migrate/20210310120444_add_followable_counter_cache_to_assemblies.rb
312
+ - db/migrate/20210507063604_add_announcement_to_assemblies.rb
314
313
  - db/seeds/Exampledocument.pdf
315
314
  - db/seeds/city.jpeg
316
315
  - db/seeds/city2.jpeg
@@ -342,9 +341,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
342
341
  version: '2.7'
343
342
  required_rubygems_version: !ruby/object:Gem::Requirement
344
343
  requirements:
345
- - - ">="
344
+ - - ">"
346
345
  - !ruby/object:Gem::Version
347
- version: '0'
346
+ version: 1.3.1
348
347
  requirements: []
349
348
  rubygems_version: 3.1.2
350
349
  signing_key:
@@ -1,2 +0,0 @@
1
- //= link decidim/assemblies/admin/assemblies.js
2
- //= link decidim/assemblies/admin/assembly_members.js
@@ -1,2 +0,0 @@
1
- //= link_directory ../images/decidim/assemblies
2
- //= link_directory ../javascripts/decidim/assemblies
@@ -1,67 +0,0 @@
1
- $(() => {
2
- ((exports) => {
3
- const $assemblyScopeEnabled = $("#assembly_scopes_enabled");
4
- const $assemblyScopeId = $("#assembly_scope_id");
5
-
6
- if ($(".edit_assembly, .new_assembly").length > 0) {
7
- $assemblyScopeEnabled.on("change", (event) => {
8
- const checked = event.target.checked;
9
- exports.theDataPicker.enabled($assemblyScopeId, checked);
10
- })
11
- exports.theDataPicker.enabled($assemblyScopeId, $assemblyScopeEnabled.prop("checked"));
12
- }
13
-
14
-
15
- const $form = $(".assembly_form_admin");
16
-
17
- if ($form.length > 0) {
18
-
19
- const $privateSpace = $form.find("#private_space");
20
- const $isTransparent = $form.find("#is_transparent");
21
- const $specialFeatures = $form.find("#special_features");
22
-
23
-
24
- const toggleDisabledHiddenFields = () => {
25
- const enabledPrivateSpace = $privateSpace.find("input[type='checkbox']").prop("checked");
26
- $isTransparent.find("input[type='checkbox']").attr("disabled", "disabled");
27
- $specialFeatures.hide();
28
-
29
- if (enabledPrivateSpace) {
30
- $isTransparent.find("input[type='checkbox']").attr("disabled", !enabledPrivateSpace);
31
- $specialFeatures.show();
32
- }
33
- };
34
-
35
- $privateSpace.on("change", toggleDisabledHiddenFields);
36
- toggleDisabledHiddenFields();
37
-
38
- const $assemblyType = $form.find("#assembly_assembly_type");
39
- const $assemblyTypeOther = $form.find("#assembly_type_other");
40
-
41
- const $assemblyCreatedBy = $form.find("#assembly_created_by");
42
- const $assemblyCreatedByOther = $form.find("#created_by_other");
43
-
44
- const toggleDependsOnSelect = ($target, $showDiv) => {
45
- const value = $target.val();
46
- $showDiv.hide();
47
- if (value === "others") {
48
- $showDiv.show();
49
- }
50
- };
51
-
52
- $assemblyType.on("change", (ev) => {
53
- const $target = $(ev.target);
54
- toggleDependsOnSelect($target, $assemblyTypeOther);
55
- });
56
-
57
- $assemblyCreatedBy.on("change", (ev) => {
58
- const $target = $(ev.target);
59
- toggleDependsOnSelect($target, $assemblyCreatedByOther);
60
- });
61
-
62
- toggleDependsOnSelect($assemblyType, $assemblyTypeOther);
63
- toggleDependsOnSelect($assemblyCreatedBy, $assemblyCreatedByOther);
64
- }
65
-
66
- })(window);
67
- });
@@ -1,18 +0,0 @@
1
- (function() {
2
- $(() => {
3
-
4
- $(".show-more").on("click", function() {
5
- /* eslint-disable no-invalid-this */
6
- $(this).hide();
7
- $(".show-more-panel").removeClass("hide");
8
- $(".hide-more").show();
9
- });
10
-
11
- $(".hide-more").on("click", function() {
12
- $(this).hide();
13
- $(".show-more-panel").addClass("hide");
14
- $(".show-more").show();
15
- });
16
-
17
- })
18
- }(window));
@@ -1,698 +0,0 @@
1
- /* eslint-disable require-jsdoc, max-lines, no-return-assign, func-style, id-length, no-plusplus, no-use-before-define, no-negated-condition, init-declarations, no-invalid-this, no-param-reassign, no-ternary, multiline-ternary, no-nested-ternary, no-eval, no-extend-native, prefer-reflect */
2
- /* eslint dot-location: ["error", "property"], no-negated-condition: "error" */
3
- /* eslint no-unused-expressions: ["error", { "allowTernary": true }] */
4
- /* eslint no-unused-vars: ["error", { "args": "none" }] */
5
- /* global d3 */
6
-
7
- // = require_self
8
- // = require d3
9
- ((exports) => {
10
- const { Decidim: { Visualizations: render } } = exports;
11
-
12
- // lib
13
- const renderOrgCharts = () => {
14
- const $orgChartContainer = $(".js-orgchart")
15
- const $btnReset = $(".js-reset-orgchart")
16
-
17
- let dataDepicted = null
18
- let fake = false
19
- let orgchart = {}
20
-
21
- // lib - https://bl.ocks.org/bumbeishvili/b96ba47ea21d14dfce6ebb859b002d3a
22
- const renderChartCollapsibleNetwork = (params) => {
23
-
24
- // exposed variables
25
- let attrs = {
26
- id: `id${Math.floor(Math.random() * 1000000)}`,
27
- svgWidth: 960,
28
- svgHeight: 600,
29
- marginTop: 0,
30
- marginBottom: 5,
31
- marginRight: 0,
32
- marginLeft: 30,
33
- container: "body",
34
- distance: 150,
35
- hiddenChildLevel: 1,
36
- hoverOpacity: 0.2,
37
- maxTextDisplayZoomLevel: 1,
38
- lineStrokeWidth: 1.5,
39
- fakeRoot: false,
40
- nodeGutter: { x: 16, y: 8 },
41
- childrenIndicatorRadius: 15,
42
- fakeBorderWidth: 32,
43
- data: null
44
- }
45
-
46
- /* ############### IF EXISTS OVERWRITE ATTRIBUTES FROM PASSED PARAM ####### */
47
-
48
- let attrKeys = Object.keys(attrs)
49
- attrKeys.forEach(function (key) {
50
- if (params && params[key]) {
51
- attrs[key] = params[key]
52
- }
53
- })
54
-
55
- // innerFunctions which will update visuals
56
- let updateData
57
- let collapse, expand
58
- let filter
59
- let hierarchy = {}
60
-
61
- // main chart object
62
- let main = function (selection) {
63
- selection.each(function scope() {
64
-
65
- // calculated properties
66
- let calc = {}
67
- calc.chartLeftMargin = attrs.marginLeft
68
- calc.chartTopMargin = attrs.marginTop
69
- calc.chartWidth = attrs.svgWidth - attrs.marginRight - calc.chartLeftMargin
70
- calc.chartHeight = attrs.svgHeight - attrs.marginBottom - calc.chartTopMargin
71
-
72
- // ########################## HIERARCHY STUFF #########################
73
- hierarchy.root = d3.hierarchy(attrs.data.root)
74
-
75
- // ########################### BEHAVIORS #########################
76
- let behaviors = {}
77
- // behaviors.zoom = d3.zoom().scaleExtent([0.75, 100, 8]).on("zoom", zoomed)
78
- behaviors.drag = d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended)
79
-
80
- // ########################### LAYOUTS #########################
81
- let layouts = {}
82
-
83
- // custom radial layout
84
- layouts.radial = d3.radial()
85
-
86
- // ########################### FORCE STUFF #########################
87
- let force = {}
88
- force.link = d3.forceLink().id((d) => d.id)
89
- force.charge = d3.forceManyBody().strength(-240)
90
- force.center = d3.forceCenter(calc.chartWidth / 2, calc.chartHeight / 2)
91
-
92
- // prevent collide
93
- force.collide = d3.forceCollide().radius((d) => {
94
- // Creates an invented radius based on element measures: diagonal = 2 * radius = sqrt(width^2, height^2)
95
- let base = (d.bbox || {}).width + (attrs.nodeGutter.x * 2)
96
- let height = (d.bbox || {}).height + (attrs.nodeGutter.y * 2)
97
- let diagonal = Math.sqrt(Math.pow(base, 2) + Math.pow(height, 2))
98
- let fakeRadius = (diagonal / 2)
99
-
100
- // return d3.max([attrs.nodeDistance * 3, fakeRadius])
101
- return fakeRadius * 1.5
102
- })
103
-
104
- // manually set x positions (which is calculated using custom radial layout)
105
- force.x = d3.forceX()
106
- .strength(0.5)
107
- .x(function (d) {
108
-
109
- // if node does not have children and is channel (depth=2) , then position it on parent's coordinate
110
- if (!d.children && d.depth > 2) {
111
- if (d.parent) {
112
- d = d.parent
113
- }
114
- }
115
-
116
- // custom circle projection - radius will be - (d.depth - 1) * 150
117
- return projectCircle(d.proportion, (d.depth - 1) * attrs.distance)[0]
118
- })
119
-
120
- // manually set y positions (which is calculated using d3.cluster)
121
- force.y = d3.forceY()
122
- .strength(0.5)
123
- .y(function (d) {
124
-
125
- // if node does not have children and is channel (depth=2) , then position it on parent's coordinate
126
- if (!d.children && d.depth > 2) {
127
- if (d.parent) {
128
- d = d.parent
129
- }
130
- }
131
-
132
- // custom circle projection - radius will be - (d.depth - 1) * 150
133
- return projectCircle(d.proportion, (d.depth - 1) * attrs.distance)[1]
134
- })
135
-
136
- // --------------------------------- INITIALISE FORCE SIMULATION ----------------------------
137
-
138
- // get based on top parameter simulation
139
- force.simulation = d3.forceSimulation()
140
- .force("link", force.link)
141
- .force("charge", force.charge)
142
- .force("center", force.center)
143
- .force("collide", force.collide)
144
- .force("x", force.x)
145
- .force("y", force.y)
146
-
147
- // ########################### HIERARCHY STUFF #########################
148
-
149
- // flatten root
150
- let arr = flatten(hierarchy.root)
151
-
152
- // hide members based on their depth
153
- arr.forEach((d) => {
154
- // Hide fake root node
155
- if ((attrs.fakeRoot) && (d.depth === 1)) {
156
- d.hidden = true
157
- }
158
-
159
- if (d.depth > attrs.hiddenChildLevel) {
160
- d._children = d.children
161
- d.children = null
162
- }
163
- })
164
-
165
- // #################################### DRAWINGS #######################
166
-
167
- // drawing containers
168
- let container = d3.select(this)
169
-
170
- // add svg
171
- let svg = container.patternify({ tag: "svg", selector: "svg-chart-container" })
172
- .attr("width", attrs.svgWidth)
173
- .attr("height", attrs.svgHeight)
174
- // .call(behaviors.zoom)
175
-
176
- // add container g element
177
- let chart = svg.patternify({ tag: "g", selector: "chart" })
178
- .attr("transform", `translate(${calc.chartLeftMargin},${calc.chartTopMargin})`)
179
-
180
- // ################################ Chart Content Drawing ##################################
181
-
182
- // link wrapper
183
- let linksWrapper = chart.patternify({ tag: "g", selector: "links-wrapper" })
184
-
185
- // node wrapper
186
- let nodesWrapper = chart.patternify({ tag: "g", selector: "nodes-wrapper" })
187
- let links, nodes
188
-
189
- // reusable function which updates visual based on data change
190
- update()
191
-
192
- // update visual based on data change
193
- function update(clickedNode) {
194
-
195
- // Show/hide reset button
196
- (clickedNode) ? $btnReset.removeClass("invisible") : $btnReset.addClass("invisible")
197
-
198
- // set xy and proportion properties with custom radial layout
199
- layouts.radial(hierarchy.root)
200
-
201
- // nodes and links array
202
- let nodesArr = flatten(hierarchy.root, true)
203
- .orderBy((d) => d.depth)
204
- .filter((d) => !d.hidden)
205
-
206
- let linksArr = hierarchy.root.links()
207
- .filter((d) => !d.source.hidden)
208
- .filter((d) => !d.target.hidden)
209
-
210
- // make new nodes to appear near the parents
211
- nodesArr.forEach(function (d) {
212
- if (clickedNode && clickedNode.id === (d.parent && d.parent.id)) {
213
- d.x = d.parent.x
214
- d.y = d.parent.y
215
- }
216
- })
217
-
218
- // links
219
- links = linksWrapper.selectAll(".link")
220
- .data(linksArr, (d) => d.target.id)
221
- links.exit().remove()
222
-
223
- links = links.enter()
224
- .append("line")
225
- .attr("class", "link")
226
- .merge(links)
227
-
228
- // node groups
229
- nodes = nodesWrapper.selectAll(".node")
230
- .data(nodesArr, (d) => d.id)
231
- nodes.exit().remove()
232
-
233
- let enteredNodes = nodes.enter()
234
- .append("g")
235
- .attr("class", "node")
236
-
237
- // bind event handlers
238
- enteredNodes
239
- .on("click", nodeClick)
240
- .on("mouseenter", nodeMouseEnter)
241
- .on("mouseleave", nodeMouseLeave)
242
- .call(behaviors.drag)
243
-
244
- // channels grandchildren
245
- enteredNodes.append("rect")
246
- .attr("class", "as-card")
247
- .attr("rx", 4)
248
- .attr("ry", 4)
249
-
250
- enteredNodes.append("text")
251
- .attr("class", "as-text")
252
- .text((d) => d.data.name)
253
-
254
- enteredNodes.selectAll("text").each(function(d) {
255
- d.bbox = this.getBBox()
256
- })
257
-
258
- enteredNodes.selectAll("rect")
259
- .attr("x", (d) => d.bbox.x - attrs.nodeGutter.x)
260
- .attr("y", (d) => d.bbox.y - attrs.nodeGutter.y)
261
- .attr("width", (d) => d.bbox.width + (2 * attrs.nodeGutter.x))
262
- .attr("height", (d) => d.bbox.height + (2 * attrs.nodeGutter.y))
263
-
264
- // append circle & text only when there are children
265
- enteredNodes
266
- .append("circle")
267
- .filter((d) => Boolean(d.children) || Boolean(d._children))
268
- .attr("class", "as-circle")
269
- .attr("r", attrs.childrenIndicatorRadius)
270
- .attr("cx", (d) => d.bbox.x + d.bbox.width + attrs.nodeGutter.x)
271
- .attr("cy", (d) => d.bbox.y + d.bbox.height + attrs.nodeGutter.y)
272
-
273
- enteredNodes
274
- .append("text")
275
- .filter((d) => Boolean(d.children) || Boolean(d._children))
276
- .attr("class", "as-text")
277
- .attr("dx", (d) => d.bbox.x + d.bbox.width + attrs.nodeGutter.x)
278
- .attr("dy", attrs.childrenIndicatorRadius + 3)
279
- .text((d) => d3.max([(d.children || {}).length, (d._children || {}).length]))
280
-
281
- // merge node groups and style it
282
- nodes = enteredNodes.merge(nodes)
283
-
284
- // force simulation
285
- force.simulation.nodes(nodesArr).on("tick", ticked)
286
-
287
- // links simulation
288
- force.simulation.force("link").links(links).id((d) => d.id).distance(attrs.distance * 2).strength(2)
289
- }
290
-
291
- // ####################################### EVENT HANDLERS ########################
292
-
293
- // zoom handler
294
- // function zoomed() {
295
- // // get transform event
296
- // let transform = d3.event.transform
297
- // attrs.lastTransform = transform
298
- //
299
- // // apply transform event props to the wrapper
300
- // chart.attr("transform", transform)
301
- //
302
- // svg.selectAll(".node").attr("transform", (d) => `translate(${d.x},${d.y}) scale(${1 / (attrs.lastTransform ? attrs.lastTransform.k : 1)})`)
303
- // svg.selectAll(".link").attr("stroke-width", attrs.lineStrokeWidth / (attrs.lastTransform ? attrs.lastTransform.k : 1))
304
- // }
305
-
306
- // tick handler
307
- function ticked() {
308
- const fakeBorderWidth = attrs.fakeBorderWidth
309
- const maxXValueAvailable = (value) => Math.max(Math.min(calc.chartWidth - fakeBorderWidth, value), fakeBorderWidth)
310
- const maxYValueAvailable = (value) => Math.max(Math.min(calc.chartHeight - fakeBorderWidth, value), fakeBorderWidth)
311
- // set links position
312
- links
313
- .attr("x1", (d) => maxXValueAvailable(d.source.x))
314
- .attr("y1", (d) => maxYValueAvailable(d.source.y))
315
- .attr("x2", (d) => maxXValueAvailable(d.target.x))
316
- .attr("y2", (d) => maxYValueAvailable(d.target.y))
317
-
318
- // set nodes position
319
- svg.selectAll(".node")
320
- .attr("transform", (d) => `translate(${maxXValueAvailable(d.x)},${maxYValueAvailable(d.y)})`)
321
- }
322
-
323
- // handler drag start event
324
- function dragstarted() {
325
- // disable node fixing
326
- nodes.each((d) => {
327
- d.fx = null
328
- d.fy = null
329
- })
330
- }
331
-
332
- // handle dragging event
333
- function dragged(d) {
334
- // make dragged node fixed
335
- d.fx = d3.event.x
336
- d.fy = d3.event.y
337
- }
338
-
339
- // -------------------- handle drag end event ---------------
340
- function dragended() {
341
- // we are doing nothing, here , aren't we?
342
- }
343
-
344
- // -------------------------- node mouse hover handler ---------------
345
- function nodeMouseEnter(d) {
346
- // get links
347
- let _links = hierarchy.root.links()
348
-
349
- // get hovered node connected links
350
- let connectedLinks = _links.filter((l) => l.source.id === d.id || l.target.id === d.id)
351
-
352
- // get hovered node linked nodes
353
- let linkedNodes = connectedLinks.map((s) => s.source.id).concat(connectedLinks.map((c) => c.target.id))
354
-
355
- // reduce all other nodes opacity
356
- nodesWrapper.selectAll(".node")
357
- .filter((n) => linkedNodes.indexOf(n.id) === -1)
358
- .attr("opacity", attrs.hoverOpacity)
359
-
360
- // reduce all other links opacity
361
- linksWrapper.selectAll(".link")
362
- .attr("opacity", attrs.hoverOpacity)
363
-
364
- // highlight hovered nodes connections
365
- linksWrapper.selectAll(".link")
366
- .filter((l) => l.source.id === d.id || l.target.id === d.id)
367
- .attr("opacity", 1)
368
- }
369
-
370
- // --------------- handle mouseleave event ---------------
371
- function nodeMouseLeave() {
372
- // return things back to normal
373
- nodesWrapper.selectAll(".node")
374
- .attr("opacity", 1)
375
- linksWrapper.selectAll(".link")
376
- .attr("opacity", 1)
377
- }
378
-
379
- // --------------- handle node click event ---------------
380
- function nodeClick(d) {
381
- // free fixed nodes
382
- nodes.each((di) => {
383
- di.fx = null
384
- di.fy = null
385
- })
386
-
387
- // collapse or expand node
388
- if (d.children) {
389
- collapse(d)
390
- } else if (d._children) {
391
- expand(d)
392
- } else {
393
- // nothing is to collapse or expand
394
- }
395
-
396
- freeNodes()
397
- }
398
-
399
- // ######################################### UTIL FUNCS ##################################
400
- updateData = function () {
401
- main.run()
402
- }
403
-
404
- collapse = function (d, deep = false) {
405
- if (d.children) {
406
- if (deep) {
407
- d.children.forEach((e) => collapse(e, true))
408
- }
409
-
410
- d._children = d.children
411
- d.children = null
412
- }
413
-
414
- update(d)
415
- force.simulation.restart()
416
- force.simulation.alphaTarget(0.15)
417
- }
418
-
419
- expand = function (d, deep = false) {
420
- if (d._children) {
421
- if (deep) {
422
- d._children.forEach((e) => expand(e, true))
423
- }
424
-
425
- d.children = d._children
426
- d._children = null
427
- }
428
-
429
- update(d)
430
- force.simulation.restart()
431
- force.simulation.alphaTarget(0.15)
432
- }
433
-
434
- // function slowDownNodes() {
435
- // force.simulation.alphaTarget(0.05)
436
- // }
437
-
438
- // function speedUpNodes() {
439
- // force.simulation.alphaTarget(0.45)
440
- // }
441
-
442
- function freeNodes() {
443
- d3.selectAll(".node").each((n) => {
444
- n.fx = null
445
- n.fy = null
446
- })
447
- }
448
-
449
- function projectCircle(value, radius) {
450
- let r = radius || 0
451
- let corner = value * 2 * Math.PI
452
- return [Math.sin(corner) * r, -Math.cos(corner) * r]
453
- }
454
-
455
- // recursively loop on children and extract nodes as an array
456
- function flatten(root, clustered) {
457
- let nodesArray = []
458
- let i = 0
459
- function recurse(node, depth) {
460
- if (node.children) {
461
- node.children.forEach(function (child) {
462
- recurse(child, depth + 1)
463
- })
464
- }
465
-
466
- if (!node.id) {
467
- node.id = ++i
468
- } else {
469
- ++i
470
- }
471
-
472
- node.depth = depth
473
- if (clustered) {
474
- if (!node.cluster) {
475
- // if cluster coordinates are not set, set it
476
- node.cluster = { x: node.x, y: node.y }
477
- }
478
- }
479
- nodesArray.push(node)
480
- }
481
- recurse(root, 1)
482
- return nodesArray
483
- }
484
-
485
- function debug() {
486
- if (attrs.isDebug) {
487
- // stringify func
488
- let stringified = String(scope)
489
-
490
- // parse variable names
491
- let groupVariables = stringified
492
- // match var x-xx= {}
493
- .match(/var\s+([\w])+\s*=\s*{\s*}/gi)
494
- // match xxx
495
- .map((d) => d.match(/\s+\w*/gi).filter((s) => s.trim()))
496
- // get xxx
497
- .map((v) => v[0].trim())
498
-
499
- // assign local variables to the scope
500
- groupVariables.forEach((v) => {
501
- main[`P_${v}`] = eval(v)
502
- })
503
- }
504
- }
505
-
506
- debug()
507
-
508
- })
509
- }
510
-
511
- // ----------- PROTOTYEPE FUNCTIONS ----------------------
512
- d3.selection.prototype.patternify = function (_params) {
513
- let selector = _params.selector
514
- let elementTag = _params.tag
515
- let _data = _params.data || [selector]
516
-
517
- // pattern in action
518
- let selection = this.selectAll(`.${selector}`).data(_data)
519
- selection.exit().remove()
520
- selection = selection.enter().append(elementTag).merge(selection)
521
- selection.attr("class", selector)
522
-
523
- return selection
524
- }
525
-
526
- // custom radial layout
527
- d3.radial = function () {
528
- return function (root) {
529
-
530
- recurse(root, 0, 1)
531
-
532
- function recurse(node, min, max) {
533
- node.proportion = (max + min) / 2
534
- if (!node.x) {
535
-
536
- // if node has parent, match entered node positions to it's parent
537
- if (node.parent) {
538
- node.x = node.parent.x
539
- } else {
540
- node.x = 0
541
- }
542
- }
543
-
544
- // if node had parent, match entered node positions to it's parent
545
- if (!node.y) {
546
- if (node.parent) {
547
- node.y = node.parent.y
548
- } else {
549
- node.y = 0
550
- }
551
- }
552
-
553
- // recursively do the same for children
554
- if (node.children) {
555
- let offset = (max - min) / node.children.length
556
- node.children.forEach(function (child, i) {
557
- let newMin = min + (offset * i)
558
- let newMax = newMin + offset
559
-
560
- recurse(child, newMin, newMax)
561
- })
562
- }
563
- }
564
- }
565
- }
566
-
567
- // https://github.com/bumbeishvili/d3js-boilerplates#orderby
568
- Array.prototype.orderBy = function (func) {
569
- this.sort((_a, _b) => {
570
- let a = func(_a)
571
- let b = func(_b)
572
- if (typeof a === "string" || a instanceof String) {
573
- return a.localeCompare(b)
574
- }
575
- return a - b
576
- })
577
-
578
- return this
579
- }
580
-
581
- // ########################## BOILEPLATE STUFF ################
582
-
583
- // dinamic keys functions
584
- Object.keys(attrs).forEach((key) => {
585
- // Attach variables to main function
586
- return main[key] = function (_) {
587
- let string = `attrs['${key}'] = _`
588
-
589
- if (!arguments.length) {
590
- return eval(` attrs['${key}'];`)
591
- }
592
-
593
- eval(string)
594
-
595
- return main
596
- }
597
- })
598
-
599
- // set attrs as property
600
- main.attrs = attrs
601
-
602
- // debugging visuals
603
- main.debug = function (isDebug) {
604
- attrs.isDebug = isDebug
605
- if (isDebug) {
606
- if (!window.charts) {
607
- window.charts = []
608
- }
609
- window.charts.push(main)
610
- }
611
- return main
612
- }
613
-
614
- // exposed update functions
615
- main.data = function (value) {
616
- if (!arguments.length) {
617
- return attrs.data
618
- }
619
-
620
- attrs.data = value
621
- if (typeof updateData === "function") {
622
- updateData()
623
- }
624
- return main
625
- }
626
-
627
- // run visual
628
- main.run = function () {
629
- d3.selectAll(attrs.container)
630
- .call(main)
631
- return main
632
- }
633
-
634
- main.filter = function (filterParams) {
635
- if (!arguments.length) {
636
- return attrs.filterParams
637
- }
638
-
639
- attrs.filterParams = filterParams
640
- if (typeof filter === "function") {
641
- filter()
642
- }
643
- return main
644
- }
645
-
646
- main.reset = function () {
647
-
648
- hierarchy.root.children.forEach((e) => collapse(e, true))
649
- main.run()
650
-
651
- return main
652
- }
653
-
654
- return main
655
- }
656
-
657
- // initialization
658
- $orgChartContainer.each((i, container) => {
659
-
660
- let $container = $(container)
661
- let width = $container.width()
662
- let height = width / (16 / 9)
663
-
664
- d3.json($container.data("url")).then((data) => {
665
- // Make a fake previous node if the data entry is not hierarchical
666
- if (data instanceof Array) {
667
- fake = true
668
- dataDepicted = {
669
- name: null,
670
- children: data
671
- }
672
- } else {
673
- dataDepicted = data
674
- }
675
-
676
- orgchart = renderChartCollapsibleNetwork()
677
- .svgHeight(height)
678
- .svgWidth(width)
679
- .fakeRoot(fake)
680
- .container(`#${container.id}`)
681
- .data({
682
- root: dataDepicted
683
- })
684
- .debug(true)
685
- .run()
686
- })
687
- })
688
-
689
- // reset
690
- $btnReset.click(function() {
691
- orgchart.reset()
692
- })
693
- }
694
-
695
- $(() => {
696
- render(renderOrgCharts);
697
- })
698
- })(window);