activeadmin_ancestry_view 0.0.1

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.
Files changed (27) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +37 -0
  4. data/app/assets/javascripts/activeadmin_ancestry_view/base.coffee +206 -0
  5. data/app/assets/stylesheets/activeadmin_ancestry_view/base.scss +41 -0
  6. data/app/helpers/active_admin/activeadmin_ancestry_view/nodes_helper.rb +68 -0
  7. data/app/models/concerns/activeadmin_ancestry_view/model_methods.rb +26 -0
  8. data/app/views/activeadmin_ancestry_view/_content_table.slim +8 -0
  9. data/app/views/activeadmin_ancestry_view/_main.slim +7 -0
  10. data/app/views/activeadmin_ancestry_view/_panel_header_links.slim +17 -0
  11. data/config/locales/activeadmin_ancestry_view.en.yml +6 -0
  12. data/lib/activeadmin_ancestry_view.rb +20 -0
  13. data/lib/activeadmin_ancestry_view/action_builder/action_builder.rb +33 -0
  14. data/lib/activeadmin_ancestry_view/action_builder/index_action_builder.rb +10 -0
  15. data/lib/activeadmin_ancestry_view/action_builder/show_action_builder.rb +13 -0
  16. data/lib/activeadmin_ancestry_view/action_generator.rb +16 -0
  17. data/lib/activeadmin_ancestry_view/ancestry_view.rb +18 -0
  18. data/lib/activeadmin_ancestry_view/controller_builder/controller_builder.rb +27 -0
  19. data/lib/activeadmin_ancestry_view/controller_builder/index_controller_builder.rb +54 -0
  20. data/lib/activeadmin_ancestry_view/controller_builder/show_controller_builder.rb +8 -0
  21. data/lib/activeadmin_ancestry_view/controller_generator.rb +11 -0
  22. data/lib/activeadmin_ancestry_view/engine.rb +7 -0
  23. data/lib/activeadmin_ancestry_view/exceptions.rb +4 -0
  24. data/lib/activeadmin_ancestry_view/finder.rb +30 -0
  25. data/lib/activeadmin_ancestry_view/version.rb +3 -0
  26. data/lib/generators/activeadmin_ancestry_view/install/install_generator.rb +47 -0
  27. metadata +167 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d07e9759682daaa8b8e0e0d427c9b23c284433ec
4
+ data.tar.gz: 2ac4ae635cb328170bd3d29ba771700e6d91e36b
5
+ SHA512:
6
+ metadata.gz: 72142cae1891472366758dd06604aeafea71fa491d8674c298f706d625ca7b73514d41a46ae48bb4ecea973de49c52adaaa3a423c128452bc29e952625af203f
7
+ data.tar.gz: e619dfc2fef4d44f688239dc16dbc26d487b5d3406b38818424642face6c7140ec30b9be1dd74bc4950f91b5bdc70005f1129e405bbe907ef007f8f0b8d080b1
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Dimkarodinz
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'ActiveadminAncestryView'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,206 @@
1
+ $(document).on 'ready page:load turbolinks:load', ->
2
+ CSSRule =
3
+ get: (ruleName, deleteFlag) ->
4
+ ruleName = ruleName.toLowerCase()
5
+ if document.styleSheets
6
+ i = 0
7
+ while i < document.styleSheets.length
8
+ styleSheet = document.styleSheets[i]
9
+ ii = 0
10
+ cssRule = false
11
+ loop
12
+ if styleSheet.cssRules
13
+ cssRule = styleSheet.cssRules[ii]
14
+ else
15
+ cssRule = styleSheet.rules[ii]
16
+ if cssRule
17
+ if cssRule.selectorText.toLowerCase() == ruleName
18
+ if deleteFlag == 'delete'
19
+ if styleSheet.cssRules
20
+ styleSheet.deleteRule ii
21
+ else
22
+ styleSheet.removeRule ii
23
+ return true
24
+ else
25
+ return cssRule
26
+ ii++
27
+ unless cssRule
28
+ break
29
+ i++
30
+ false
31
+
32
+ add: (ruleName, properies) ->
33
+ if document.styleSheets
34
+ if !this.get(ruleName)
35
+ if document.styleSheets[0].addRule
36
+ document.styleSheets[0].addRule ruleName, properies, 0
37
+ else
38
+ document.styleSheets[0].insertRule ruleName + " { #{properies} }", 0
39
+
40
+ distance =
41
+ middleHeight: (node) ->
42
+ Math.abs $(node).height() / 2
43
+
44
+ betweenTop: (sourceNode, targetNode) ->
45
+ Math.abs $(sourceNode).offset().top - $(targetNode).offset().top
46
+
47
+ verticalBranch: (node, lastChild) ->
48
+ @betweenTop(node, lastChild) + @middleHeight(lastChild)
49
+
50
+ branchProp =
51
+ baseMargin: 2 # em
52
+
53
+ base:
54
+ "transition: 150ms ease; " +
55
+ "content: ''; " +
56
+ "position: absolute; " +
57
+ "border: 0.1em solid gray; "
58
+
59
+ vertical: (height) ->
60
+ "margin-left: #{@baseMargin}em; " +
61
+ "height: #{height}px; " +
62
+ "z-index: -1; " +
63
+ @base
64
+
65
+ horizontal: (marginTop, marginLeft) ->
66
+ "margin-top: -#{marginTop}px; " +
67
+ "margin-left: -#{marginLeft - @baseMargin}em; " +
68
+ "width: #{marginLeft - @baseMargin}em; " +
69
+ "z-index: -2; " +
70
+ @base
71
+
72
+ pseudoElement =
73
+ addHorizontal: (node) ->
74
+ id = $(node).attr('id')
75
+ height = distance.middleHeight(node)
76
+ marginLeft = $(node).attr('data-shift-multiplicator')
77
+ CSSRule.add(
78
+ "[id='#{id}']::after",
79
+ branchProp.horizontal(height, marginLeft)
80
+ )
81
+
82
+ addVertical: (node, purposeNode) ->
83
+ dist = distance.verticalBranch(node, purposeNode)
84
+ id = $(node).attr('id')
85
+ CSSRule.add "[id='#{id}']::before", branchProp.vertical(dist)
86
+
87
+ updHorizontal: (node) ->
88
+ if $(node).hasClass('panel-root') then false
89
+ else
90
+ id = $(node).attr 'id'
91
+ newHeight = -Math.abs distance.middleHeight(node)
92
+ line = CSSRule.get '[id="' + id + '"]::after'
93
+ line.style.marginTop = newHeight.toString().concat('px')
94
+
95
+ updVertical: (node) ->
96
+ nodeId = $(node).attr('id')
97
+ lastChild = $(node).parent().find(
98
+ ".panel-container[data-last-child=#{nodeId}]")
99
+
100
+ if $(lastChild).length
101
+ newDistance = distance.verticalBranch(node, lastChild)
102
+ line = CSSRule.get('[id="' + nodeId + '"]::before')
103
+ line.style.height = newDistance.toString().concat('px')
104
+
105
+ updEachVertical: (node) ->
106
+ # find actual parents
107
+ nodeClasses = $(node).attr('class').split(' ')
108
+ allParents = $(node).prevAll('.panel-parent')
109
+ parentIds = $.map(allParents, (el) -> $(el).attr 'id')
110
+ actualIds = similarItems(nodeClasses, parentIds)
111
+
112
+ # add current node id
113
+ actualIds.push $(node).attr('id')
114
+ # get array of jquery elements from actual ids
115
+ actualCollection = getElements(actualIds)
116
+ # update vertical pseudoelement of actual elements
117
+ that = this
118
+ $.each(actualCollection, (i, element) ->
119
+ that.updVertical(element)
120
+ )
121
+
122
+ findPanelHeader = (object) ->
123
+ object.find('.panel').find('.panel-header')
124
+
125
+ clearAllColors = ->
126
+ $('.panel-header').css('background-color', '')
127
+ $('.panel-header').each ->
128
+ if $(this).hasClass('selectable')
129
+ $(this).removeClass('selectable')
130
+
131
+ similarItems = (arr1, arr2) ->
132
+ item for item in arr2 when item in arr1
133
+
134
+ getElements = (arrayOfIds) ->
135
+ $.map arrayOfIds, (id) -> $("##{id}").get()
136
+
137
+ # inherit color from parent panel on load
138
+ # if parent has no color, inherit from parent of parent
139
+ $('.panel-parent').each ->
140
+ id = $(this).attr('id')
141
+ parentColor = findPanelHeader($(this)).css('background-color')
142
+
143
+ $('.panel-childless').each ->
144
+ if $(this).hasClass(id)
145
+ findPanelHeader($(this)).css('background-color', parentColor)
146
+
147
+ # show-hide content table of single div
148
+ $('.show-content').click ->
149
+ node = $(this).parents('.panel-container')
150
+ nodeId = $(node).attr 'id'
151
+ content = $(this).parent().next('.panel_contents')
152
+
153
+ oldNodeHeight = $(node).height()
154
+ verticalLine = CSSRule.get('[id="' + $(node).attr('id') + '"]::before')
155
+
156
+ if content.is(':hidden')
157
+ content.show 0, -> pseudoElement.updHorizontal(node)
158
+ else
159
+ content.hide 0, -> pseudoElement.updHorizontal(node)
160
+ pseudoElement.updEachVertical(node)
161
+
162
+ # show-hide content table for bunch of nodes
163
+ $('.show-childrens').click ->
164
+ nodeId = $(this).parents('.panel-container').attr('id')
165
+ nodeContent = $(this).parent().next('.panel_contents')
166
+ lastChild = $(".panel-container[data-last-child=#{nodeId}]")
167
+ lastChildId = $(lastChild).attr('id')
168
+
169
+ # NOTE: do not use .toggleClass here
170
+ if nodeContent.is(':hidden') then nodeContent.show() else nodeContent.hide()
171
+
172
+ $('.panel').each ->
173
+ subNode = $(this).parent('.panel-container')
174
+ if subNode.hasClass(nodeId)
175
+ content = $(this).find('.panel_contents')
176
+
177
+ if nodeContent.is(':visible')
178
+ content.show 0, -> pseudoElement.updHorizontal(subNode)
179
+ else
180
+ content.hide 0, -> pseudoElement.updHorizontal(subNode)
181
+ subLastChildId = $(subNode).attr 'data-last-child'
182
+ pseudoElement.updVertical $("##{subLastChildId}") if subLastChildId?
183
+
184
+ pseudoElement.updEachVertical(lastChild)
185
+
186
+ # select user
187
+ $('.panel-header').on 'click', ->
188
+ clearAllColors()
189
+ $(this).addClass('selectable')
190
+ parentId = $(this).parents('.panel-container').attr('id')
191
+
192
+ $('.panel-header').each ->
193
+ if ($(this)).parents('.panel-container').hasClass(parentId)
194
+ $(this).addClass('selectable')
195
+
196
+ # add vertical line to each parent node
197
+ $('.panel-parent').each ->
198
+ nodeId = $(this).attr('id')
199
+ lastChild = $(this).parent().find(
200
+ ".panel-container[data-last-child=#{nodeId}]")
201
+
202
+ pseudoElement.addVertical(this, lastChild) if $(lastChild).length
203
+
204
+ # add horizontal line to each node except root
205
+ $('.panel-container').each ->
206
+ pseudoElement.addHorizontal(this) unless $(this).hasClass('panel-root')
@@ -0,0 +1,41 @@
1
+ $panel-header-color: #5E6469;
2
+ $selectable-color: rgba(122, 158, 255, 0.7);
3
+
4
+ @mixin true_transition {
5
+ transition: 0.1s ease;
6
+ }
7
+
8
+ div[class*='panel-'] {
9
+ @include true_transition
10
+ }
11
+
12
+ .panel_contents table {
13
+ margin-bottom: 0.1em !important;
14
+ }
15
+
16
+ .selectable {
17
+ background-color: $selectable-color !important;
18
+ }
19
+
20
+ .hided, #collection_selection_toggle_panel {
21
+ display: none;
22
+ }
23
+
24
+ .show-content, .to-structure, .show-childrens {
25
+ cursor: pointer;
26
+ float: right;
27
+ }
28
+
29
+ .panel-header span {
30
+ color: $panel-header-color;
31
+ font-weight: bold;
32
+ font-size: 1.1em !important;
33
+ }
34
+
35
+ .panel-container {
36
+ padding-bottom: 0.4em !important;
37
+ }
38
+
39
+ .panel-margin-bottom {
40
+ margin-bottom: 0em !important;
41
+ }
@@ -0,0 +1,68 @@
1
+ module ActiveAdmin
2
+ module ActiveadminAncestryView
3
+ module NodesHelper
4
+ CLASSES = {
5
+ child: 'panel-childless',
6
+ parent: 'panel-parent',
7
+ root: 'panel-root'
8
+ }
9
+
10
+ PRETTY_COLORS = {
11
+ red: [255, 102, 102], yellow: [255, 178, 102],
12
+ green: [102, 255, 102], blue: [102, 178, 255],
13
+ violet: [178, 102, 255], gray: [192, 192, 192]
14
+ }
15
+
16
+ def generate_panel_classes(resource)
17
+ attributes = []
18
+ attributes << resource.path_ids if resource.ancestry
19
+ attributes << child_class(resource)
20
+ attributes << CLASSES[:root] if resource.root?
21
+ attributes.flatten.join(' ')
22
+ end
23
+
24
+ # for 'data-last-child' attribute
25
+ def last_child(resource)
26
+ "#{resource.parent.id}" if last_child?(resource)
27
+ end
28
+
29
+ def panel_shift(resource, multiplicator = 4)
30
+ unless resource.depth.zero?
31
+ "margin-left: #{multiplicator * resource.depth}em;"
32
+ end
33
+ end
34
+
35
+ def random_bckgr_color(resource, no_color = false)
36
+ return if no_color
37
+ return if childless_child?(resource)
38
+ color = random_color.join(', ')
39
+ "background-color: rgba(#{color}, 0.7) !important"
40
+ end
41
+
42
+ private
43
+
44
+ def last_child?(resource)
45
+ parent_last_child_id = resource&.parent&.children&.last&.id
46
+ parent_last_child_id == resource.id
47
+ end
48
+
49
+ def childless_child?(resource)
50
+ resource.is_childless? && resource.is_root? == false
51
+ end
52
+
53
+ def child_class(resource)
54
+ childless_child?(resource) ? CLASSES[:child] : CLASSES[:parent]
55
+ end
56
+
57
+ def random_color(range = -50...50)
58
+ sample_color.map do |light|
59
+ light + Random.rand(range)
60
+ end
61
+ end
62
+
63
+ def sample_color
64
+ PRETTY_COLORS.values.sample
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,26 @@
1
+ module Concerns
2
+ module ActiveadminAncestryView::ModelMethods
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # Return ActiveRecord::Relation with same order as passed to method.
7
+ # For expamle, .ordered_collection([2,1,3]) will return
8
+ # relation with ids [2,1,3] against standart [1,2,3] order.
9
+ def self.ordered_collection(ids)
10
+ order_clause = "CASE id "
11
+ ids.each_with_index do |id, index|
12
+ order_clause << sanitize_sql_array(["WHEN ? THEN ? ", id, index])
13
+ end
14
+ order_clause << sanitize_sql_array(["ELSE ? END", ids.length])
15
+
16
+ where(id: ids).order(order_clause)
17
+ end
18
+
19
+ # Like #ancestry, but with self.id
20
+ def full_ancestry
21
+ return id.to_s unless ancestry
22
+ path_ids.join('/')
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ table
2
+ tbody
3
+ tr
4
+ - unless table.blank?
5
+ - table.each do |header, content|
6
+ th
7
+ =header.to_s + ': '
8
+ =resource.public_send(content)
@@ -0,0 +1,7 @@
1
+ div.panel-container class=generate_panel_classes(resource) id=resource.id data-last-child=last_child(resource) data-shift-multiplicator=shift_depth style=panel_shift(resource, shift_depth)
2
+ div.panel.panel-margin-bottom
3
+ div.panel-header style=random_bckgr_color(resource, no_color)
4
+ = render 'activeadmin_ancestry_view/panel_header_links', resource: resource, headers: headers, table_status: table.present?, no_childless_link: no_childless_link
5
+ - if table.present?
6
+ div.panel_contents class='hided'
7
+ = render 'activeadmin_ancestry_view/content_table', resource: resource, table: table
@@ -0,0 +1,17 @@
1
+ / left link
2
+ span
3
+ - title = headers[:title] ? resource.public_send(headers[:title]) : resource.id
4
+ - link_to_resource = link_to(title, resource_path(resource.id))
5
+
6
+ - if no_childless_link
7
+ = resource.is_childless? ? title : link_to_resource
8
+ - else
9
+ = link_to_resource
10
+
11
+ - if table_status
12
+ / links on right side
13
+ a.view_link.member_link.show-content
14
+ = headers[:info] || t('activeadmin_ancestry_view.info')
15
+ - unless resource.is_childless?
16
+ a.view_link.member_link.show-childrens
17
+ = headers[:expand] || t('activeadmin_ancestry_view.expand')
@@ -0,0 +1,6 @@
1
+ en:
2
+ activeadmin_ancestry_view:
3
+ expand: Expand
4
+ info: Info
5
+ errors:
6
+ wrong_action: "Wrong action name. Allowed actions are: %{actions}"
@@ -0,0 +1,20 @@
1
+ require "activeadmin_ancestry_view/engine"
2
+ require "activeadmin_ancestry_view/version"
3
+ require "activeadmin_ancestry_view/exceptions"
4
+ require "activeadmin_ancestry_view/ancestry_view"
5
+
6
+ require "activeadmin_ancestry_view/finder"
7
+ require "activeadmin_ancestry_view/action_generator"
8
+ require "activeadmin_ancestry_view/controller_generator"
9
+
10
+ require "activeadmin_ancestry_view/controller_builder/controller_builder"
11
+ require "activeadmin_ancestry_view/controller_builder/index_controller_builder"
12
+ require "activeadmin_ancestry_view/controller_builder/show_controller_builder"
13
+
14
+ require "activeadmin_ancestry_view/action_builder/action_builder"
15
+ require "activeadmin_ancestry_view/action_builder/index_action_builder"
16
+ require "activeadmin_ancestry_view/action_builder/show_action_builder"
17
+
18
+ module ActiveadminAncestryView
19
+ ALLOWED_ACTIONS = %w(index show)
20
+ end
@@ -0,0 +1,33 @@
1
+ module ActiveadminAncestryView
2
+ class ActionBuilder
3
+ DEFAULT_OPTIONS = {
4
+ headers: '{ title: :id }',
5
+ table: '{}',
6
+ no_color: 'false',
7
+ no_childless_link: 'false',
8
+ shift: '4'
9
+ }
10
+
11
+ def call(opt = {}, &block)
12
+ end
13
+
14
+ private
15
+
16
+ def render_partial(opt)
17
+ %{render partial: '#{template_path}',
18
+ locals: {
19
+ resource: res,
20
+ headers: #{opt[:headers] || DEFAULT_OPTIONS[:headers]},
21
+ table: #{opt[:table] || DEFAULT_OPTIONS[:table] },
22
+ no_color: #{opt[:no_color] || DEFAULT_OPTIONS[:no_color] },
23
+ no_childless_link: #{opt[:no_childless_link] || DEFAULT_OPTIONS[:no_childless_link]},
24
+ shift_depth: #{opt[:shift_depth] || DEFAULT_OPTIONS[:shift] }
25
+ }
26
+ }
27
+ end
28
+
29
+ def template_path
30
+ 'activeadmin_ancestry_view/main'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ module ActiveadminAncestryView
2
+ class IndexActionBuilder < ActionBuilder
3
+ def call(opt = {}, &block)
4
+ %{index as: :block do |res|
5
+ #{block.call if block_given?}
6
+ #{render_partial(opt)}
7
+ end}
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module ActiveadminAncestryView
2
+ class ShowActionBuilder < ActionBuilder
3
+ def call(opt = {}, &block)
4
+ %{show do
5
+ #{block.call if block_given?}
6
+ sorted_subtree = resource.subtree.sort_by(&:full_ancestry)
7
+ sorted_subtree.each do |res|
8
+ #{render_partial(opt)}
9
+ end
10
+ end}
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveadminAncestryView
2
+ class ActionGenerator
3
+ def initialize(action_builder, opt = {}, &block)
4
+ @action_builder = action_builder
5
+ @opt = opt
6
+ @block = block if block_given?
7
+ end
8
+
9
+ def call
10
+ action_builder.call(opt, &block)
11
+ end
12
+
13
+ private
14
+ attr_reader :action_builder, :opt, :block
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module AncestryView
2
+ def ancestry_view(action_name, opt = {}, &block)
3
+ eval active_admin_action(action_name, opt, &block)
4
+ eval active_admin_controller(action_name)
5
+ end
6
+
7
+ private
8
+
9
+ def active_admin_controller(action_name)
10
+ builder = ActiveadminAncestryView::Finder.get_controller_builder(action_name)
11
+ ActiveadminAncestryView::ControllerGenerator.new(builder).call
12
+ end
13
+
14
+ def active_admin_action(action_name, opt = {}, &block)
15
+ builder = ActiveadminAncestryView::Finder.get_action_builder(action_name)
16
+ ActiveadminAncestryView::ActionGenerator.new(builder, opt, &block).call
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ module ActiveadminAncestryView
2
+ class ControllerBuilder
3
+ def call
4
+ %{controller do
5
+ private
6
+ #{build_attr_accessor}
7
+ #{build_before_action}
8
+ #{build_after_action}
9
+ #{build_methods}
10
+ end}
11
+ end
12
+
13
+ private
14
+
15
+ def build_attr_accessor
16
+ end
17
+
18
+ def build_before_action
19
+ end
20
+
21
+ def build_after_action
22
+ end
23
+
24
+ def build_methods
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveadminAncestryView
2
+ class IndexControllerBuilder < ControllerBuilder
3
+ private
4
+
5
+ ORDER_VAR_NAME = 'i_am_storing_sort_order'
6
+ OLD_SCOPED_COL_VAR_NAME = 'i_am_storing_old_scoped_collection'
7
+
8
+ def build_attr_accessor
9
+ %{attr_accessor :#{ORDER_VAR_NAME}}
10
+ end
11
+
12
+ def build_before_action
13
+ %{send(:before_action, only: :index) do
14
+ #{save_and_clean_sort_order}
15
+ #{save_old_scoped_collection}
16
+ #{sort_scoped_collection}
17
+ end}
18
+ end
19
+
20
+ def build_after_action
21
+ %{send(:after_action, only: :index) do
22
+ #{restore_sort_order}
23
+ #{restore_old_scoped_collection}
24
+ end}
25
+ end
26
+
27
+ def save_old_scoped_collection
28
+ "self.class.send :alias_method, :#{OLD_SCOPED_COL_VAR_NAME}, :scoped_collection\n"
29
+ end
30
+
31
+ def sort_scoped_collection
32
+ %{self.class.redefine_method(:scoped_collection) do
33
+ ids = #{OLD_SCOPED_COL_VAR_NAME}.all.sort_by(&:full_ancestry).map(&:id)
34
+ resource_class.ordered_collection(ids)
35
+ end}
36
+ end
37
+
38
+ def restore_old_scoped_collection
39
+ "self.class.send :alias_method, :scoped_collection, :#{OLD_SCOPED_COL_VAR_NAME}\n"
40
+ end
41
+
42
+ def save_and_clean_sort_order
43
+ %{#{ORDER_VAR_NAME} = active_admin_config.sort_order
44
+ active_admin_config.sort_order = ''}
45
+ end
46
+
47
+ def restore_sort_order
48
+ %{if #{ORDER_VAR_NAME}
49
+ active_admin_config.sort_order = #{ORDER_VAR_NAME}
50
+ #{ORDER_VAR_NAME} = nil
51
+ end}
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,8 @@
1
+ module ActiveadminAncestryView
2
+ class ShowControllerBuilder < ControllerBuilder
3
+ # Nothing to do
4
+ def call
5
+ ''
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveadminAncestryView
2
+ class ControllerGenerator
3
+ def initialize(controller_builder)
4
+ @controller_builder = controller_builder
5
+ end
6
+
7
+ def call
8
+ @controller_builder.call
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module ActiveadminAncestryView
2
+ class Engine < ::Rails::Engine
3
+ config.to_prepare do
4
+ ActiveAdmin::ResourceDSL.send :include, AncestryView
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module ActiveadminAncestryView
2
+ class ActionError < ArgumentError
3
+ end
4
+ end
@@ -0,0 +1,30 @@
1
+ module ActiveadminAncestryView
2
+ class Finder
3
+ class << self
4
+ def get_action_builder(name)
5
+ if_action_valid(name) do
6
+ ActiveadminAncestryView.const_get("#{name.to_s.camelize}ActionBuilder").new
7
+ end
8
+ end
9
+
10
+ def get_controller_builder(name)
11
+ if_action_valid(name) do
12
+ ActiveadminAncestryView.const_get("#{name.to_s.camelize}ControllerBuilder").new
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def if_action_valid(action_name)
19
+ if ALLOWED_ACTIONS.include? action_name.to_s
20
+ yield
21
+ else
22
+ raise ActionError.new(
23
+ I18n.t 'activeadmin_ancestry_view.errors.wrong_action',
24
+ actions: ALLOWED_ACTIONS.join(', ')
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveadminAncestryView
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,47 @@
1
+ module ActiveadminAncestryView
2
+ class Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ def add_javascripts
5
+ target_file_path = 'app/assets/javascripts/active_admin'
6
+ ref = "#= require active_admin/base\n"
7
+ begin
8
+ inject_into_file("#{target_file_path}.coffee", js_to_add, after: ref)
9
+ rescue Errno::ENOENT
10
+ inject_into_file("#{target_file_path}.js.coffee", js_to_add, after: ref)
11
+ end
12
+ end
13
+
14
+ def add_stylesheets
15
+ target_file_path = 'app/assets/stylesheets/active_admin'
16
+ begin
17
+ prepend_file("#{target_file_path}.scss", css_to_add)
18
+ rescue Errno::ENOENT
19
+ prepend_file("#{target_file_path}.css.scss", css_to_add)
20
+ end
21
+ end
22
+
23
+ def add_concerns
24
+ ref = 'has_ancestry'
25
+ Dir['app/models/**/*.rb'].each do |model_file|
26
+ if File.readlines(model_file).grep(/has_ancestry/).any?
27
+ inject_into_file(model_file, concern_to_add, before: ref)
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def concern_to_add
35
+ "include Concerns::ActiveadminAncestryView::ModelMethods\n\t"
36
+ end
37
+
38
+ def js_to_add
39
+ "#= require activeadmin_ancestry_view/base\n"
40
+ end
41
+
42
+ def css_to_add
43
+ "@import \"activeadmin_ancestry_view/base\";\n"
44
+ end
45
+ end
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,167 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activeadmin_ancestry_view
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dimkarodinz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.7.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.7.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: activeadmin
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0.pre4
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0.pre4
41
+ - !ruby/object:Gem::Dependency
42
+ name: jquery-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: slim-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.13'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.13'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ description: Ancestry tree view in ActiveAdmin resource
112
+ email:
113
+ - dimkarodin@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - MIT-LICENSE
119
+ - Rakefile
120
+ - app/assets/javascripts/activeadmin_ancestry_view/base.coffee
121
+ - app/assets/stylesheets/activeadmin_ancestry_view/base.scss
122
+ - app/helpers/active_admin/activeadmin_ancestry_view/nodes_helper.rb
123
+ - app/models/concerns/activeadmin_ancestry_view/model_methods.rb
124
+ - app/views/activeadmin_ancestry_view/_content_table.slim
125
+ - app/views/activeadmin_ancestry_view/_main.slim
126
+ - app/views/activeadmin_ancestry_view/_panel_header_links.slim
127
+ - config/locales/activeadmin_ancestry_view.en.yml
128
+ - lib/activeadmin_ancestry_view.rb
129
+ - lib/activeadmin_ancestry_view/action_builder/action_builder.rb
130
+ - lib/activeadmin_ancestry_view/action_builder/index_action_builder.rb
131
+ - lib/activeadmin_ancestry_view/action_builder/show_action_builder.rb
132
+ - lib/activeadmin_ancestry_view/action_generator.rb
133
+ - lib/activeadmin_ancestry_view/ancestry_view.rb
134
+ - lib/activeadmin_ancestry_view/controller_builder/controller_builder.rb
135
+ - lib/activeadmin_ancestry_view/controller_builder/index_controller_builder.rb
136
+ - lib/activeadmin_ancestry_view/controller_builder/show_controller_builder.rb
137
+ - lib/activeadmin_ancestry_view/controller_generator.rb
138
+ - lib/activeadmin_ancestry_view/engine.rb
139
+ - lib/activeadmin_ancestry_view/exceptions.rb
140
+ - lib/activeadmin_ancestry_view/finder.rb
141
+ - lib/activeadmin_ancestry_view/version.rb
142
+ - lib/generators/activeadmin_ancestry_view/install/install_generator.rb
143
+ homepage: http://127.0.0.1
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.5.1
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: Ancestry tree view in ActiveAdmin resource
167
+ test_files: []