decidim-assemblies 0.27.10 → 0.28.0.rc4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/cells/decidim/assemblies/assemblies/show.erb +16 -0
- data/app/cells/decidim/assemblies/assemblies_cell.rb +24 -0
- data/app/cells/decidim/assemblies/assembly_cell.rb +7 -2
- data/app/cells/decidim/assemblies/assembly_dropdown_metadata_cell.rb +19 -0
- data/app/cells/decidim/assemblies/assembly_g_cell.rb +23 -0
- data/app/cells/decidim/assemblies/assembly_member/data.erb +19 -0
- data/app/cells/decidim/assemblies/assembly_member/name_and_position.erb +11 -0
- data/app/cells/decidim/assemblies/assembly_member/show.erb +8 -52
- data/app/cells/decidim/assemblies/assembly_metadata_g_cell.rb +46 -0
- data/app/cells/decidim/assemblies/assembly_s_cell.rb +15 -0
- data/app/cells/decidim/assemblies/content_block_cell.rb +21 -0
- data/app/cells/decidim/assemblies/content_blocks/children_assemblies_cell.rb +27 -0
- data/app/cells/decidim/assemblies/content_blocks/dates_metadata_cell.rb +23 -0
- data/app/cells/decidim/assemblies/content_blocks/extra_data_cell.rb +39 -0
- data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_cell.rb +15 -23
- data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies_settings_form/show.erb +1 -1
- data/app/cells/decidim/assemblies/content_blocks/main_data_cell.rb +52 -0
- data/app/cells/decidim/assemblies/content_blocks/metadata_cell.rb +23 -0
- data/app/cells/decidim/assemblies/content_blocks/related_assemblies/content.erb +1 -0
- data/app/cells/decidim/assemblies/content_blocks/related_assemblies_cell.rb +34 -0
- data/app/cells/decidim/assemblies/content_blocks/stats_cell.rb +15 -0
- data/app/commands/decidim/assemblies/admin/copy_assembly.rb +2 -2
- data/app/commands/decidim/assemblies/admin/create_assemblies_type.rb +1 -1
- data/app/commands/decidim/assemblies/admin/create_assembly.rb +2 -1
- data/app/commands/decidim/assemblies/admin/create_assembly_member.rb +3 -3
- data/app/commands/decidim/assemblies/admin/destroy_assemblies_type.rb +1 -1
- data/app/commands/decidim/assemblies/admin/destroy_assembly_member.rb +1 -1
- data/app/commands/decidim/assemblies/admin/import_assembly.rb +1 -1
- data/app/commands/decidim/assemblies/admin/update_assemblies_type.rb +1 -1
- data/app/commands/decidim/assemblies/admin/update_assembly.rb +1 -1
- data/app/commands/decidim/assemblies/admin/update_assembly_member.rb +1 -1
- data/app/constraints/decidim/assemblies/current_assembly.rb +1 -1
- data/app/controllers/concerns/decidim/assemblies/admin/assembly_context.rb +1 -1
- data/app/controllers/concerns/decidim/assemblies/admin/assembly_members/filterable.rb +39 -0
- data/app/controllers/concerns/decidim/assemblies/assembly_breadcrumb.rb +36 -0
- data/app/controllers/decidim/assemblies/admin/assemblies_controller.rb +1 -0
- data/app/controllers/decidim/assemblies/admin/assemblies_types_controller.rb +1 -1
- data/app/controllers/decidim/assemblies/admin/assembly_attachment_collections_controller.rb +5 -0
- data/app/controllers/decidim/assemblies/admin/assembly_attachments_controller.rb +5 -0
- data/app/controllers/decidim/assemblies/admin/assembly_imports_controller.rb +2 -0
- data/app/controllers/decidim/assemblies/admin/assembly_landing_page_content_blocks_controller.rb +35 -0
- data/app/controllers/decidim/assemblies/admin/assembly_landing_page_controller.rb +37 -0
- data/app/controllers/decidim/assemblies/admin/assembly_members_controller.rb +2 -6
- data/app/controllers/decidim/assemblies/admin/assembly_publications_controller.rb +9 -29
- data/app/controllers/decidim/assemblies/admin/assembly_user_roles_controller.rb +8 -91
- data/app/controllers/decidim/assemblies/admin/concerns/assembly_admin.rb +1 -1
- data/app/controllers/decidim/assemblies/assemblies_controller.rb +12 -7
- data/app/controllers/decidim/assemblies/assembly_members_controller.rb +2 -0
- data/app/events/decidim/assemblies/create_assembly_member_event.rb +1 -1
- data/app/events/decidim/role_assigned_to_assembly_event.rb +11 -6
- data/app/forms/decidim/assemblies/admin/assembly_copy_form.rb +1 -1
- data/app/forms/decidim/assemblies/admin/assembly_form.rb +1 -1
- data/app/forms/decidim/assemblies/admin/assembly_import_form.rb +1 -1
- data/app/forms/decidim/assemblies/admin/assembly_user_role_form.rb +2 -18
- data/app/helpers/decidim/assemblies/admin/assembly_members_helper.rb +11 -0
- data/app/helpers/decidim/assemblies/application_helper.rb +12 -0
- data/app/helpers/decidim/assemblies/assemblies_helper.rb +21 -19
- data/app/helpers/decidim/assemblies/filter_assemblies_helper.rb +15 -30
- data/app/models/decidim/assembly.rb +6 -5
- data/app/models/decidim/assembly_user_role.rb +5 -33
- data/app/packs/entrypoints/decidim_assemblies.js +0 -1
- data/app/packs/src/decidim/assemblies/admin/assemblies.js +2 -2
- data/app/packs/src/decidim/assemblies/orgchart.js +0 -701
- data/app/permissions/decidim/assemblies/permissions.rb +14 -27
- data/app/presenters/decidim/assemblies/admin_log/assemblies_setting_presenter.rb +2 -2
- data/app/presenters/decidim/assemblies/admin_log/assemblies_type_presenter.rb +2 -2
- data/app/presenters/decidim/assemblies/admin_log/assembly_member_presenter.rb +2 -2
- data/app/presenters/decidim/assemblies/admin_log/assembly_presenter.rb +2 -2
- data/app/presenters/decidim/assemblies/admin_log/assembly_user_role_presenter.rb +2 -2
- data/app/presenters/decidim/assemblies/assembly_presenter.rb +38 -0
- data/app/presenters/decidim/assemblies/assembly_stats_presenter.rb +2 -41
- data/app/presenters/decidim/assembly_member_presenter.rb +18 -4
- data/app/queries/decidim/assemblies/admin/admin_users.rb +1 -1
- data/app/queries/decidim/assemblies/assemblies_with_user_role.rb +2 -2
- data/app/serializers/decidim/assemblies/assembly_importer.rb +3 -3
- data/app/serializers/decidim/assemblies/assembly_serializer.rb +1 -1
- data/app/views/decidim/assemblies/admin/assemblies/_form.html.erb +218 -176
- data/app/views/decidim/assemblies/admin/assemblies/edit.html.erb +25 -11
- data/app/views/decidim/assemblies/admin/assemblies/index.html.erb +105 -115
- data/app/views/decidim/assemblies/admin/assemblies/new.html.erb +16 -9
- data/app/views/decidim/assemblies/admin/assemblies_types/_form.html.erb +6 -8
- data/app/views/decidim/assemblies/admin/assemblies_types/edit.html.erb +11 -5
- data/app/views/decidim/assemblies/admin/assemblies_types/index.html.erb +34 -35
- data/app/views/decidim/assemblies/admin/assemblies_types/new.html.erb +16 -6
- data/app/views/decidim/assemblies/admin/assembly_copies/_form.html.erb +12 -20
- data/app/views/decidim/assemblies/admin/assembly_copies/new.html.erb +17 -5
- data/app/views/decidim/assemblies/admin/assembly_imports/_form.html.erb +28 -37
- data/app/views/decidim/assemblies/admin/assembly_imports/new.html.erb +17 -5
- data/app/views/decidim/assemblies/admin/assembly_members/_form.html.erb +45 -49
- data/app/views/decidim/assemblies/admin/assembly_members/edit.html.erb +17 -6
- data/app/views/decidim/assemblies/admin/assembly_members/index.html.erb +51 -88
- data/app/views/decidim/assemblies/admin/assembly_members/new.html.erb +17 -6
- data/app/views/decidim/assemblies/admin/assembly_user_roles/_form.html.erb +14 -18
- data/app/views/decidim/assemblies/admin/assembly_user_roles/edit.html.erb +17 -6
- data/app/views/decidim/assemblies/admin/assembly_user_roles/index.html.erb +54 -55
- data/app/views/decidim/assemblies/admin/assembly_user_roles/new.html.erb +17 -6
- data/app/views/decidim/assemblies/assemblies/_collection.html.erb +7 -0
- data/app/views/decidim/assemblies/assemblies/index.html.erb +20 -19
- data/app/views/decidim/assemblies/assemblies/index.js.erb +1 -8
- data/app/views/decidim/assemblies/assemblies/show.html.erb +17 -207
- data/app/views/decidim/assemblies/assembly_members/index.html.erb +7 -5
- data/app/views/decidim/assemblies/pages/user_profile/_member_of.html.erb +6 -9
- data/app/views/layouts/decidim/admin/_manage_assemblies.html.erb +36 -0
- data/app/views/layouts/decidim/admin/assemblies.html.erb +13 -11
- data/app/views/layouts/decidim/admin/assemblies_imports.html.erb +9 -0
- data/app/views/layouts/decidim/admin/assemblies_types.html.erb +17 -0
- data/app/views/layouts/decidim/admin/assembly.html.erb +12 -13
- data/app/views/layouts/decidim/assembly.html.erb +7 -14
- data/config/locales/ar.yml +7 -68
- data/config/locales/bg.yml +0 -466
- data/config/locales/ca.yml +62 -71
- data/config/locales/cs.yml +59 -66
- data/config/locales/de.yml +60 -69
- data/config/locales/el.yml +11 -61
- data/config/locales/en.yml +57 -66
- data/config/locales/es-MX.yml +57 -66
- data/config/locales/es-PY.yml +57 -66
- data/config/locales/es.yml +63 -72
- data/config/locales/eu.yml +57 -70
- data/config/locales/fi-plain.yml +58 -67
- data/config/locales/fi.yml +57 -66
- data/config/locales/fr-CA.yml +57 -66
- data/config/locales/fr.yml +57 -66
- data/config/locales/ga-IE.yml +4 -15
- data/config/locales/gl.yml +4 -62
- data/config/locales/hu.yml +33 -65
- data/config/locales/id-ID.yml +6 -47
- data/config/locales/is-IS.yml +5 -40
- data/config/locales/it.yml +5 -62
- data/config/locales/ja.yml +51 -66
- data/config/locales/kaa.yml +0 -8
- data/config/locales/ko.yml +0 -92
- data/config/locales/lb.yml +5 -61
- data/config/locales/lt.yml +40 -63
- data/config/locales/lv.yml +5 -57
- data/config/locales/nl.yml +4 -62
- data/config/locales/no.yml +5 -62
- data/config/locales/pl.yml +3 -93
- data/config/locales/pt-BR.yml +77 -132
- data/config/locales/pt.yml +5 -62
- data/config/locales/ro-RO.yml +20 -63
- data/config/locales/ru.yml +4 -44
- data/config/locales/sk.yml +0 -26
- data/config/locales/sl.yml +5 -48
- data/config/locales/sq-AL.yml +0 -364
- data/config/locales/sr-CS.yml +0 -5
- data/config/locales/sv.yml +132 -193
- data/config/locales/tr-TR.yml +8 -69
- data/config/locales/uk.yml +4 -44
- data/config/locales/zh-CN.yml +5 -60
- data/config/locales/zh-TW.yml +7 -63
- data/db/migrate/20200108123050_migrate_decidim_assembly_types.rb +1 -1
- data/lib/decidim/api/assemblies_type_type.rb +1 -1
- data/lib/decidim/api/assembly_member_type.rb +1 -1
- data/lib/decidim/api/assembly_type.rb +1 -1
- data/lib/decidim/assemblies/admin_engine.rb +21 -126
- data/lib/decidim/assemblies/content_blocks/registry_manager.rb +184 -0
- data/lib/decidim/assemblies/engine.rb +15 -21
- data/lib/decidim/assemblies/menu.rb +161 -0
- data/lib/decidim/assemblies/participatory_space.rb +7 -229
- data/lib/decidim/assemblies/query_extensions.rb +6 -6
- data/lib/decidim/assemblies/seeds.rb +161 -0
- data/lib/decidim/assemblies/test/factories.rb +47 -55
- data/lib/decidim/assemblies/version.rb +1 -1
- metadata +54 -51
- data/app/cells/decidim/assemblies/assembly_m/footer.erb +0 -15
- data/app/cells/decidim/assemblies/assembly_m/tags.erb +0 -1
- data/app/cells/decidim/assemblies/assembly_m_cell.rb +0 -77
- data/app/cells/decidim/assemblies/content_blocks/highlighted_assemblies/show.erb +0 -30
- data/app/commands/decidim/assemblies/admin/create_assembly_admin.rb +0 -54
- data/app/commands/decidim/assemblies/admin/destroy_assembly_admin.rb +0 -58
- data/app/commands/decidim/assemblies/admin/notify_role_assigned_to_assembly.rb +0 -22
- data/app/commands/decidim/assemblies/admin/publish_assembly.rb +0 -39
- data/app/commands/decidim/assemblies/admin/unpublish_assembly.rb +0 -39
- data/app/commands/decidim/assemblies/admin/update_assemblies_setting.rb +0 -46
- data/app/commands/decidim/assemblies/admin/update_assembly_admin.rb +0 -53
- data/app/controllers/decidim/assemblies/admin/assemblies_settings_controller.rb +0 -49
- data/app/controllers/decidim/assemblies/widgets_controller.rb +0 -33
- data/app/forms/decidim/assemblies/admin/assemblies_setting_form.rb +0 -14
- data/app/models/decidim/assemblies_setting.rb +0 -17
- data/app/queries/decidim/assemblies/admin/assembly_members.rb +0 -56
- data/app/views/decidim/assemblies/_filter_by_type.html.erb +0 -19
- data/app/views/decidim/assemblies/admin/assemblies_settings/_form.html.erb +0 -10
- data/app/views/decidim/assemblies/admin/assemblies_settings/edit.html.erb +0 -7
- data/app/views/decidim/assemblies/assemblies/_count.html.erb +0 -1
- data/app/views/decidim/assemblies/assemblies/_nav_breadcumb.html.erb +0 -11
- data/app/views/decidim/assemblies/assemblies/_parent_assemblies.html.erb +0 -15
- data/app/views/decidim/assemblies/assemblies/_promoted_assembly.html.erb +0 -27
- data/app/views/layouts/decidim/_assembly_header.html.erb +0 -27
- data/app/views/layouts/decidim/_assembly_navigation.html.erb +0 -24
- data/app/views/layouts/decidim/admin/assembly_members.html.erb +0 -18
- data/config/locales/he-IL.yml +0 -110
- data/db/seeds/Exampledocument.pdf +0 -0
- data/db/seeds/city.jpeg +0 -0
- data/db/seeds/city2.jpeg +0 -0
- data/db/seeds/homepage_image.jpg +0 -0
- data/decidim-assemblies.gemspec +0 -32
@@ -1,701 +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: 0 */
|
5
|
-
|
6
|
-
import { select, selectAll, event } from "d3-selection";
|
7
|
-
import { max } from "d3-array";
|
8
|
-
import { hierarchy } from "d3-hierarchy";
|
9
|
-
import { forceManyBody, forceCollide, forceCenter, forceX, forceY, forceSimulation, forceLink } from "d3-force";
|
10
|
-
import { drag } from "d3-drag";
|
11
|
-
import { json } from "d3-fetch";
|
12
|
-
|
13
|
-
// lib
|
14
|
-
const renderOrgCharts = () => {
|
15
|
-
const $orgChartContainer = $(".js-orgchart")
|
16
|
-
const $btnReset = $(".js-reset-orgchart")
|
17
|
-
|
18
|
-
let dataDepicted = null
|
19
|
-
let fake = false
|
20
|
-
let orgchart = {}
|
21
|
-
|
22
|
-
// lib - https://bl.ocks.org/bumbeishvili/b96ba47ea21d14dfce6ebb859b002d3a
|
23
|
-
const renderChartCollapsibleNetwork = (params) => {
|
24
|
-
|
25
|
-
// exposed variables
|
26
|
-
let attrs = {
|
27
|
-
id: `id${Math.floor(Math.random() * 1000000)}`,
|
28
|
-
svgWidth: 960,
|
29
|
-
svgHeight: 600,
|
30
|
-
marginTop: 0,
|
31
|
-
marginBottom: 5,
|
32
|
-
marginRight: 0,
|
33
|
-
marginLeft: 30,
|
34
|
-
container: "body",
|
35
|
-
distance: 150,
|
36
|
-
hiddenChildLevel: 1,
|
37
|
-
hoverOpacity: 0.2,
|
38
|
-
maxTextDisplayZoomLevel: 1,
|
39
|
-
lineStrokeWidth: 1.5,
|
40
|
-
fakeRoot: false,
|
41
|
-
nodeGutter: { x: 16, y: 8 },
|
42
|
-
childrenIndicatorRadius: 15,
|
43
|
-
fakeBorderWidth: 32,
|
44
|
-
data: null
|
45
|
-
}
|
46
|
-
|
47
|
-
/* ############### IF EXISTS OVERWRITE ATTRIBUTES FROM PASSED PARAM ####### */
|
48
|
-
|
49
|
-
let attrKeys = Object.keys(attrs)
|
50
|
-
attrKeys.forEach(function (key) {
|
51
|
-
if (params && params[key]) {
|
52
|
-
attrs[key] = params[key]
|
53
|
-
}
|
54
|
-
})
|
55
|
-
|
56
|
-
// innerFunctions which will update visuals
|
57
|
-
let updateData
|
58
|
-
let collapse, expand
|
59
|
-
let filter
|
60
|
-
let _hierarchy = {}
|
61
|
-
|
62
|
-
// main chart object
|
63
|
-
let main = function (_selection) {
|
64
|
-
_selection.each(function scope() {
|
65
|
-
|
66
|
-
// calculated properties
|
67
|
-
let calc = {}
|
68
|
-
calc.chartLeftMargin = attrs.marginLeft
|
69
|
-
calc.chartTopMargin = attrs.marginTop
|
70
|
-
calc.chartWidth = attrs.svgWidth - attrs.marginRight - calc.chartLeftMargin
|
71
|
-
calc.chartHeight = attrs.svgHeight - attrs.marginBottom - calc.chartTopMargin
|
72
|
-
|
73
|
-
// ########################## HIERARCHY STUFF #########################
|
74
|
-
_hierarchy.root = hierarchy(attrs.data.root)
|
75
|
-
|
76
|
-
// ########################### BEHAVIORS #########################
|
77
|
-
let behaviors = {}
|
78
|
-
// behaviors.zoom = zoom().scaleExtent([0.75, 100, 8]).on("zoom", zoomed)
|
79
|
-
behaviors.drag = drag().on("start", dragstarted).on("drag", dragged).on("end", dragended)
|
80
|
-
|
81
|
-
// ########################### LAYOUTS #########################
|
82
|
-
let layouts = {}
|
83
|
-
|
84
|
-
// custom radial layout
|
85
|
-
layouts.radial = radial()
|
86
|
-
|
87
|
-
// ########################### FORCE STUFF #########################
|
88
|
-
let force = {}
|
89
|
-
force.link = forceLink().id((d) => d.id)
|
90
|
-
force.charge = forceManyBody().strength(-240)
|
91
|
-
force.center = forceCenter(calc.chartWidth / 2, calc.chartHeight / 2)
|
92
|
-
|
93
|
-
// prevent collide
|
94
|
-
force.collide = forceCollide().radius((d) => {
|
95
|
-
// Creates an invented radius based on element measures: diagonal = 2 * radius = sqrt(width^2, height^2)
|
96
|
-
let base = (d.bbox || {}).width + (attrs.nodeGutter.x * 2)
|
97
|
-
let height = (d.bbox || {}).height + (attrs.nodeGutter.y * 2)
|
98
|
-
let diagonal = Math.sqrt(Math.pow(base, 2) + Math.pow(height, 2))
|
99
|
-
let fakeRadius = (diagonal / 2)
|
100
|
-
|
101
|
-
// return max([attrs.nodeDistance * 3, fakeRadius])
|
102
|
-
return fakeRadius * 1.5
|
103
|
-
})
|
104
|
-
|
105
|
-
// manually set x positions (which is calculated using custom radial layout)
|
106
|
-
force.x = forceX()
|
107
|
-
.strength(0.5)
|
108
|
-
.x(function (d) {
|
109
|
-
|
110
|
-
// if node does not have children and is channel (depth=2) , then position it on parent's coordinate
|
111
|
-
if (!d.children && d.depth > 2) {
|
112
|
-
if (d.parent) {
|
113
|
-
d = d.parent
|
114
|
-
}
|
115
|
-
}
|
116
|
-
|
117
|
-
// custom circle projection - radius will be - (d.depth - 1) * 150
|
118
|
-
return projectCircle(d.proportion, (d.depth - 1) * attrs.distance)[0]
|
119
|
-
})
|
120
|
-
|
121
|
-
// manually set y positions (which is calculated using cluster)
|
122
|
-
force.y = forceY()
|
123
|
-
.strength(0.5)
|
124
|
-
.y(function (d) {
|
125
|
-
|
126
|
-
// if node does not have children and is channel (depth=2) , then position it on parent's coordinate
|
127
|
-
if (!d.children && d.depth > 2) {
|
128
|
-
if (d.parent) {
|
129
|
-
d = d.parent
|
130
|
-
}
|
131
|
-
}
|
132
|
-
|
133
|
-
// custom circle projection - radius will be - (d.depth - 1) * 150
|
134
|
-
return projectCircle(d.proportion, (d.depth - 1) * attrs.distance)[1]
|
135
|
-
})
|
136
|
-
|
137
|
-
// --------------------------------- INITIALISE FORCE SIMULATION ----------------------------
|
138
|
-
|
139
|
-
// get based on top parameter simulation
|
140
|
-
force.simulation = forceSimulation()
|
141
|
-
.force("link", force.link)
|
142
|
-
.force("charge", force.charge)
|
143
|
-
.force("center", force.center)
|
144
|
-
.force("collide", force.collide)
|
145
|
-
.force("x", force.x)
|
146
|
-
.force("y", force.y)
|
147
|
-
|
148
|
-
// ########################### HIERARCHY STUFF #########################
|
149
|
-
|
150
|
-
// flatten root
|
151
|
-
let arr = flatten(_hierarchy.root)
|
152
|
-
|
153
|
-
// hide members based on their depth
|
154
|
-
arr.forEach((d) => {
|
155
|
-
// Hide fake root node
|
156
|
-
if ((attrs.fakeRoot) && (d.depth === 1)) {
|
157
|
-
d.hidden = true
|
158
|
-
}
|
159
|
-
|
160
|
-
if (d.depth > attrs.hiddenChildLevel) {
|
161
|
-
d._children = d.children
|
162
|
-
d.children = null
|
163
|
-
}
|
164
|
-
})
|
165
|
-
|
166
|
-
// #################################### DRAWINGS #######################
|
167
|
-
|
168
|
-
// drawing containers
|
169
|
-
let container = select(this)
|
170
|
-
|
171
|
-
// add svg
|
172
|
-
let svg = patternify(container, { tag: "svg", selector: "svg-chart-container" })
|
173
|
-
.attr("width", attrs.svgWidth)
|
174
|
-
.attr("height", attrs.svgHeight)
|
175
|
-
// .call(behaviors.zoom)
|
176
|
-
|
177
|
-
// add container g element
|
178
|
-
let chart = patternify(svg, { tag: "g", selector: "chart" })
|
179
|
-
.attr("transform", `translate(${calc.chartLeftMargin},${calc.chartTopMargin})`)
|
180
|
-
|
181
|
-
// ################################ Chart Content Drawing ##################################
|
182
|
-
|
183
|
-
// link wrapper
|
184
|
-
let linksWrapper = patternify(chart, { tag: "g", selector: "links-wrapper" })
|
185
|
-
|
186
|
-
// node wrapper
|
187
|
-
let nodesWrapper = patternify(chart, { tag: "g", selector: "nodes-wrapper" })
|
188
|
-
let links, nodes
|
189
|
-
|
190
|
-
// reusable function which updates visual based on data change
|
191
|
-
update()
|
192
|
-
|
193
|
-
// update visual based on data change
|
194
|
-
function update(clickedNode) {
|
195
|
-
|
196
|
-
// Show/hide reset button
|
197
|
-
(clickedNode) ? $btnReset.removeClass("invisible") : $btnReset.addClass("invisible")
|
198
|
-
|
199
|
-
// set xy and proportion properties with custom radial layout
|
200
|
-
layouts.radial(_hierarchy.root)
|
201
|
-
|
202
|
-
// nodes and links array
|
203
|
-
let nodesArr = flatten(_hierarchy.root, true)
|
204
|
-
.orderBy((d) => d.depth)
|
205
|
-
.filter((d) => !d.hidden)
|
206
|
-
|
207
|
-
let linksArr = _hierarchy.root.links()
|
208
|
-
.filter((d) => !d.source.hidden)
|
209
|
-
.filter((d) => !d.target.hidden)
|
210
|
-
|
211
|
-
// make new nodes to appear near the parents
|
212
|
-
nodesArr.forEach(function (d) {
|
213
|
-
if (clickedNode && clickedNode.id === (d.parent && d.parent.id)) {
|
214
|
-
d.x = d.parent.x
|
215
|
-
d.y = d.parent.y
|
216
|
-
}
|
217
|
-
})
|
218
|
-
|
219
|
-
// links
|
220
|
-
links = linksWrapper.selectAll(".link")
|
221
|
-
.data(linksArr, (d) => d.target.id)
|
222
|
-
links.exit().remove()
|
223
|
-
|
224
|
-
links = links.enter()
|
225
|
-
.append("line")
|
226
|
-
.attr("class", "link")
|
227
|
-
.merge(links)
|
228
|
-
|
229
|
-
// node groups
|
230
|
-
nodes = nodesWrapper.selectAll(".node")
|
231
|
-
.data(nodesArr, (d) => d.id)
|
232
|
-
nodes.exit().remove()
|
233
|
-
|
234
|
-
let enteredNodes = nodes.enter()
|
235
|
-
.append("g")
|
236
|
-
.attr("class", "node")
|
237
|
-
|
238
|
-
// bind event handlers
|
239
|
-
enteredNodes
|
240
|
-
.on("click", nodeClick)
|
241
|
-
.on("mouseenter", nodeMouseEnter)
|
242
|
-
.on("mouseleave", nodeMouseLeave)
|
243
|
-
.call(behaviors.drag)
|
244
|
-
|
245
|
-
// channels grandchildren
|
246
|
-
enteredNodes.append("rect")
|
247
|
-
.attr("class", "as-card")
|
248
|
-
.attr("rx", 4)
|
249
|
-
.attr("ry", 4)
|
250
|
-
|
251
|
-
enteredNodes.append("text")
|
252
|
-
.attr("class", "as-text")
|
253
|
-
.text((d) => d.data.name)
|
254
|
-
|
255
|
-
enteredNodes.selectAll("text").each(function(d) {
|
256
|
-
d.bbox = this.getBBox()
|
257
|
-
})
|
258
|
-
|
259
|
-
enteredNodes.selectAll("rect")
|
260
|
-
.attr("x", (d) => d.bbox.x - attrs.nodeGutter.x)
|
261
|
-
.attr("y", (d) => d.bbox.y - attrs.nodeGutter.y)
|
262
|
-
.attr("width", (d) => d.bbox.width + (2 * attrs.nodeGutter.x))
|
263
|
-
.attr("height", (d) => d.bbox.height + (2 * attrs.nodeGutter.y))
|
264
|
-
|
265
|
-
// append circle & text only when there are children
|
266
|
-
enteredNodes
|
267
|
-
.append("circle")
|
268
|
-
.filter((d) => Boolean(d.children) || Boolean(d._children))
|
269
|
-
.attr("class", "as-circle")
|
270
|
-
.attr("r", attrs.childrenIndicatorRadius)
|
271
|
-
.attr("cx", (d) => d.bbox.x + d.bbox.width + attrs.nodeGutter.x)
|
272
|
-
.attr("cy", (d) => d.bbox.y + d.bbox.height + attrs.nodeGutter.y)
|
273
|
-
|
274
|
-
enteredNodes
|
275
|
-
.append("text")
|
276
|
-
.filter((d) => Boolean(d.children) || Boolean(d._children))
|
277
|
-
.attr("class", "as-text")
|
278
|
-
.attr("dx", (d) => d.bbox.x + d.bbox.width + attrs.nodeGutter.x)
|
279
|
-
.attr("dy", attrs.childrenIndicatorRadius + 3)
|
280
|
-
.text((d) => max([(d.children || {}).length, (d._children || {}).length]))
|
281
|
-
|
282
|
-
// merge node groups and style it
|
283
|
-
nodes = enteredNodes.merge(nodes)
|
284
|
-
|
285
|
-
// force simulation
|
286
|
-
force.simulation.nodes(nodesArr).on("tick", ticked)
|
287
|
-
|
288
|
-
// links simulation
|
289
|
-
force.simulation.force("link").links(links).id((d) => d.id).distance(attrs.distance * 2).strength(2)
|
290
|
-
}
|
291
|
-
|
292
|
-
// ####################################### EVENT HANDLERS ########################
|
293
|
-
|
294
|
-
// zoom handler
|
295
|
-
// function zoomed() {
|
296
|
-
// // get transform event
|
297
|
-
// let transform = event.transform
|
298
|
-
// attrs.lastTransform = transform
|
299
|
-
//
|
300
|
-
// // apply transform event props to the wrapper
|
301
|
-
// chart.attr("transform", transform)
|
302
|
-
//
|
303
|
-
// svg.selectAll(".node").attr("transform", (d) => `translate(${d.x},${d.y}) scale(${1 / (attrs.lastTransform ? attrs.lastTransform.k : 1)})`)
|
304
|
-
// svg.selectAll(".link").attr("stroke-width", attrs.lineStrokeWidth / (attrs.lastTransform ? attrs.lastTransform.k : 1))
|
305
|
-
// }
|
306
|
-
|
307
|
-
// tick handler
|
308
|
-
function ticked() {
|
309
|
-
const fakeBorderWidth = attrs.fakeBorderWidth
|
310
|
-
const maxXValueAvailable = (value) => Math.max(Math.min(calc.chartWidth - fakeBorderWidth, value), fakeBorderWidth)
|
311
|
-
const maxYValueAvailable = (value) => Math.max(Math.min(calc.chartHeight - fakeBorderWidth, value), fakeBorderWidth)
|
312
|
-
// set links position
|
313
|
-
links
|
314
|
-
.attr("x1", (d) => maxXValueAvailable(d.source.x))
|
315
|
-
.attr("y1", (d) => maxYValueAvailable(d.source.y))
|
316
|
-
.attr("x2", (d) => maxXValueAvailable(d.target.x))
|
317
|
-
.attr("y2", (d) => maxYValueAvailable(d.target.y))
|
318
|
-
|
319
|
-
// set nodes position
|
320
|
-
svg.selectAll(".node")
|
321
|
-
.attr("transform", (d) => `translate(${maxXValueAvailable(d.x)},${maxYValueAvailable(d.y)})`)
|
322
|
-
}
|
323
|
-
|
324
|
-
// handler drag start event
|
325
|
-
function dragstarted() {
|
326
|
-
// disable node fixing
|
327
|
-
nodes.each((d) => {
|
328
|
-
d.fx = null
|
329
|
-
d.fy = null
|
330
|
-
})
|
331
|
-
}
|
332
|
-
|
333
|
-
// handle dragging event
|
334
|
-
function dragged(d) {
|
335
|
-
// make dragged node fixed
|
336
|
-
d.fx = event.x
|
337
|
-
d.fy = event.y
|
338
|
-
}
|
339
|
-
|
340
|
-
// -------------------- handle drag end event ---------------
|
341
|
-
function dragended() {
|
342
|
-
// we are doing nothing, here , aren't we?
|
343
|
-
}
|
344
|
-
|
345
|
-
// -------------------------- node mouse hover handler ---------------
|
346
|
-
function nodeMouseEnter(d) {
|
347
|
-
// get links
|
348
|
-
let _links = _hierarchy.root.links()
|
349
|
-
|
350
|
-
// get hovered node connected links
|
351
|
-
let connectedLinks = _links.filter((l) => l.source.id === d.id || l.target.id === d.id)
|
352
|
-
|
353
|
-
// get hovered node linked nodes
|
354
|
-
let linkedNodes = connectedLinks.map((s) => s.source.id).concat(connectedLinks.map((c) => c.target.id))
|
355
|
-
|
356
|
-
// reduce all other nodes opacity
|
357
|
-
nodesWrapper.selectAll(".node")
|
358
|
-
.filter((n) => linkedNodes.indexOf(n.id) === -1)
|
359
|
-
.attr("opacity", attrs.hoverOpacity)
|
360
|
-
|
361
|
-
// reduce all other links opacity
|
362
|
-
linksWrapper.selectAll(".link")
|
363
|
-
.attr("opacity", attrs.hoverOpacity)
|
364
|
-
|
365
|
-
// highlight hovered nodes connections
|
366
|
-
linksWrapper.selectAll(".link")
|
367
|
-
.filter((l) => l.source.id === d.id || l.target.id === d.id)
|
368
|
-
.attr("opacity", 1)
|
369
|
-
}
|
370
|
-
|
371
|
-
// --------------- handle mouseleave event ---------------
|
372
|
-
function nodeMouseLeave() {
|
373
|
-
// return things back to normal
|
374
|
-
nodesWrapper.selectAll(".node")
|
375
|
-
.attr("opacity", 1)
|
376
|
-
linksWrapper.selectAll(".link")
|
377
|
-
.attr("opacity", 1)
|
378
|
-
}
|
379
|
-
|
380
|
-
// --------------- handle node click event ---------------
|
381
|
-
function nodeClick(d) {
|
382
|
-
// free fixed nodes
|
383
|
-
nodes.each((di) => {
|
384
|
-
di.fx = null
|
385
|
-
di.fy = null
|
386
|
-
})
|
387
|
-
|
388
|
-
// collapse or expand node
|
389
|
-
if (d.children) {
|
390
|
-
collapse(d)
|
391
|
-
} else if (d._children) {
|
392
|
-
expand(d)
|
393
|
-
} else {
|
394
|
-
// nothing is to collapse or expand
|
395
|
-
}
|
396
|
-
|
397
|
-
freeNodes()
|
398
|
-
}
|
399
|
-
|
400
|
-
// ######################################### UTIL FUNCS ##################################
|
401
|
-
updateData = function () {
|
402
|
-
main.run()
|
403
|
-
}
|
404
|
-
|
405
|
-
collapse = function (d, deep = false) {
|
406
|
-
if (d.children) {
|
407
|
-
if (deep) {
|
408
|
-
d.children.forEach((e) => collapse(e, true))
|
409
|
-
}
|
410
|
-
|
411
|
-
d._children = d.children
|
412
|
-
d.children = null
|
413
|
-
}
|
414
|
-
|
415
|
-
update(d)
|
416
|
-
force.simulation.restart()
|
417
|
-
force.simulation.alphaTarget(0.15)
|
418
|
-
}
|
419
|
-
|
420
|
-
expand = function (d, deep = false) {
|
421
|
-
if (d._children) {
|
422
|
-
if (deep) {
|
423
|
-
d._children.forEach((e) => expand(e, true))
|
424
|
-
}
|
425
|
-
|
426
|
-
d.children = d._children
|
427
|
-
d._children = null
|
428
|
-
}
|
429
|
-
|
430
|
-
update(d)
|
431
|
-
force.simulation.restart()
|
432
|
-
force.simulation.alphaTarget(0.15)
|
433
|
-
}
|
434
|
-
|
435
|
-
// function slowDownNodes() {
|
436
|
-
// force.simulation.alphaTarget(0.05)
|
437
|
-
// }
|
438
|
-
|
439
|
-
// function speedUpNodes() {
|
440
|
-
// force.simulation.alphaTarget(0.45)
|
441
|
-
// }
|
442
|
-
|
443
|
-
function freeNodes() {
|
444
|
-
selectAll(".node").each((n) => {
|
445
|
-
n.fx = null
|
446
|
-
n.fy = null
|
447
|
-
})
|
448
|
-
}
|
449
|
-
|
450
|
-
function projectCircle(value, radius) {
|
451
|
-
let r = radius || 0
|
452
|
-
let corner = value * 2 * Math.PI
|
453
|
-
return [Math.sin(corner) * r, -Math.cos(corner) * r]
|
454
|
-
}
|
455
|
-
|
456
|
-
// recursively loop on children and extract nodes as an array
|
457
|
-
function flatten(root, clustered) {
|
458
|
-
let nodesArray = []
|
459
|
-
let i = 0
|
460
|
-
function recurse(node, depth) {
|
461
|
-
if (node.children) {
|
462
|
-
node.children.forEach(function (child) {
|
463
|
-
recurse(child, depth + 1)
|
464
|
-
})
|
465
|
-
}
|
466
|
-
|
467
|
-
if (!node.id) {
|
468
|
-
node.id = ++i
|
469
|
-
} else {
|
470
|
-
++i
|
471
|
-
}
|
472
|
-
|
473
|
-
node.depth = depth
|
474
|
-
if (clustered) {
|
475
|
-
if (!node.cluster) {
|
476
|
-
// if cluster coordinates are not set, set it
|
477
|
-
node.cluster = { x: node.x, y: node.y }
|
478
|
-
}
|
479
|
-
}
|
480
|
-
nodesArray.push(node)
|
481
|
-
}
|
482
|
-
recurse(root, 1)
|
483
|
-
return nodesArray
|
484
|
-
}
|
485
|
-
|
486
|
-
function debug() {
|
487
|
-
if (attrs.isDebug) {
|
488
|
-
// stringify func
|
489
|
-
let stringified = String(scope)
|
490
|
-
|
491
|
-
// parse variable names
|
492
|
-
let groupVariables = stringified
|
493
|
-
// match var x-xx= {}
|
494
|
-
.match(/var\s+([\w])+\s*=\s*{\s*}/gi)
|
495
|
-
// match xxx
|
496
|
-
.map((d) => d.match(/\s+\w*/gi).filter((s) => s.trim()))
|
497
|
-
// get xxx
|
498
|
-
.map((v) => v[0].trim())
|
499
|
-
|
500
|
-
// assign local variables to the scope
|
501
|
-
groupVariables.forEach((v) => {
|
502
|
-
main[`P_${v}`] = eval(v)
|
503
|
-
})
|
504
|
-
}
|
505
|
-
}
|
506
|
-
|
507
|
-
debug()
|
508
|
-
|
509
|
-
})
|
510
|
-
}
|
511
|
-
|
512
|
-
// ----------- PROTOTYEPE FUNCTIONS ----------------------
|
513
|
-
function patternify(node, _params) {
|
514
|
-
let selector = _params.selector
|
515
|
-
let elementTag = _params.tag
|
516
|
-
let _data = _params.data || [selector]
|
517
|
-
|
518
|
-
// pattern in action
|
519
|
-
let _selection = node.selectAll(`.${selector}`).data(_data)
|
520
|
-
_selection.exit().remove()
|
521
|
-
_selection = _selection.enter().append(elementTag).merge(_selection)
|
522
|
-
_selection.attr("class", selector)
|
523
|
-
|
524
|
-
return _selection
|
525
|
-
}
|
526
|
-
|
527
|
-
// custom radial layout
|
528
|
-
function radial() {
|
529
|
-
return function (root) {
|
530
|
-
|
531
|
-
recurse(root, 0, 1)
|
532
|
-
|
533
|
-
function recurse(node, min, _max) {
|
534
|
-
node.proportion = (_max + min) / 2
|
535
|
-
if (!node.x) {
|
536
|
-
|
537
|
-
// if node has parent, match entered node positions to it's parent
|
538
|
-
if (node.parent) {
|
539
|
-
node.x = node.parent.x
|
540
|
-
} else {
|
541
|
-
node.x = 0
|
542
|
-
}
|
543
|
-
}
|
544
|
-
|
545
|
-
// if node had parent, match entered node positions to it's parent
|
546
|
-
if (!node.y) {
|
547
|
-
if (node.parent) {
|
548
|
-
node.y = node.parent.y
|
549
|
-
} else {
|
550
|
-
node.y = 0
|
551
|
-
}
|
552
|
-
}
|
553
|
-
|
554
|
-
// recursively do the same for children
|
555
|
-
if (node.children) {
|
556
|
-
let offset = (_max - min) / node.children.length
|
557
|
-
node.children.forEach(function (child, i) {
|
558
|
-
let newMin = min + (offset * i)
|
559
|
-
let newMax = newMin + offset
|
560
|
-
|
561
|
-
recurse(child, newMin, newMax)
|
562
|
-
})
|
563
|
-
}
|
564
|
-
}
|
565
|
-
}
|
566
|
-
}
|
567
|
-
|
568
|
-
// https://github.com/bumbeishvili/d3js-boilerplates#orderby
|
569
|
-
Array.prototype.orderBy = function (func) {
|
570
|
-
this.sort((_a, _b) => {
|
571
|
-
let a = func(_a)
|
572
|
-
let b = func(_b)
|
573
|
-
if (typeof a === "string" || a instanceof String) {
|
574
|
-
return a.localeCompare(b)
|
575
|
-
}
|
576
|
-
return a - b
|
577
|
-
})
|
578
|
-
|
579
|
-
return this
|
580
|
-
}
|
581
|
-
|
582
|
-
// ########################## BOILEPLATE STUFF ################
|
583
|
-
|
584
|
-
// dinamic keys functions
|
585
|
-
Object.keys(attrs).forEach((key) => {
|
586
|
-
// Attach variables to main function
|
587
|
-
return main[key] = function (_) {
|
588
|
-
let string = `attrs['${key}'] = _`
|
589
|
-
|
590
|
-
if (!arguments.length) {
|
591
|
-
return eval(` attrs['${key}'];`)
|
592
|
-
}
|
593
|
-
|
594
|
-
eval(string)
|
595
|
-
|
596
|
-
return main
|
597
|
-
}
|
598
|
-
})
|
599
|
-
|
600
|
-
// set attrs as property
|
601
|
-
main.attrs = attrs
|
602
|
-
|
603
|
-
// debugging visuals
|
604
|
-
main.debug = function (isDebug) {
|
605
|
-
attrs.isDebug = isDebug
|
606
|
-
if (isDebug) {
|
607
|
-
if (!window.charts) {
|
608
|
-
window.charts = []
|
609
|
-
}
|
610
|
-
window.charts.push(main)
|
611
|
-
}
|
612
|
-
return main
|
613
|
-
}
|
614
|
-
|
615
|
-
// exposed update functions
|
616
|
-
main.data = function (value) {
|
617
|
-
if (!arguments.length) {
|
618
|
-
return attrs.data
|
619
|
-
}
|
620
|
-
|
621
|
-
attrs.data = value
|
622
|
-
if (typeof updateData === "function") {
|
623
|
-
updateData()
|
624
|
-
}
|
625
|
-
return main
|
626
|
-
}
|
627
|
-
|
628
|
-
// run visual
|
629
|
-
main.run = function () {
|
630
|
-
selectAll(attrs.container)
|
631
|
-
.call(main)
|
632
|
-
return main
|
633
|
-
}
|
634
|
-
|
635
|
-
main.filter = function (filterParams) {
|
636
|
-
if (!arguments.length) {
|
637
|
-
return attrs.filterParams
|
638
|
-
}
|
639
|
-
|
640
|
-
attrs.filterParams = filterParams
|
641
|
-
if (typeof filter === "function") {
|
642
|
-
filter()
|
643
|
-
}
|
644
|
-
return main
|
645
|
-
}
|
646
|
-
|
647
|
-
main.reset = function () {
|
648
|
-
|
649
|
-
_hierarchy.root.children.forEach((e) => collapse(e, true))
|
650
|
-
main.run()
|
651
|
-
|
652
|
-
return main
|
653
|
-
}
|
654
|
-
|
655
|
-
return main
|
656
|
-
}
|
657
|
-
|
658
|
-
// initialization
|
659
|
-
$orgChartContainer.each((i, container) => {
|
660
|
-
|
661
|
-
let $container = $(container)
|
662
|
-
let width = $container.width()
|
663
|
-
let height = width / (16 / 9)
|
664
|
-
|
665
|
-
json($container.data("url")).then((data) => {
|
666
|
-
// Make a fake previous node if the data entry is not hierarchical
|
667
|
-
if (data instanceof Array) {
|
668
|
-
fake = true
|
669
|
-
dataDepicted = {
|
670
|
-
name: null,
|
671
|
-
children: data
|
672
|
-
}
|
673
|
-
} else {
|
674
|
-
dataDepicted = data
|
675
|
-
}
|
676
|
-
|
677
|
-
orgchart = renderChartCollapsibleNetwork()
|
678
|
-
.svgHeight(height)
|
679
|
-
.svgWidth(width)
|
680
|
-
.fakeRoot(fake)
|
681
|
-
.container(`#${container.id}`)
|
682
|
-
.data({
|
683
|
-
root: dataDepicted
|
684
|
-
})
|
685
|
-
.debug(true)
|
686
|
-
.run()
|
687
|
-
})
|
688
|
-
})
|
689
|
-
|
690
|
-
// reset
|
691
|
-
$btnReset.click(function() {
|
692
|
-
orgchart.reset()
|
693
|
-
})
|
694
|
-
}
|
695
|
-
|
696
|
-
$(() => {
|
697
|
-
renderOrgCharts()
|
698
|
-
$(document).on("change.zf.tabs", () => {
|
699
|
-
renderOrgCharts()
|
700
|
-
});
|
701
|
-
})
|