activeadmin_ancestry_view 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []