Skip to content

Commit e89d2b7

Browse files
Merge branch 'feature/Create-a-component-to-display-tree-views' into stage
2 parents 3977206 + 0367c4f commit e89d2b7

24 files changed

+381
-392
lines changed

app/assets/stylesheets/bioportal.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@ div.tree_error {
651651

652652
#bd ul.simpleTree li{
653653
margin-left:-10px;
654+
padding: 5px 0 0 10px;
654655
}
655656

656657
#bd ul.simpleTree{
@@ -668,6 +669,22 @@ div.tree_error {
668669
overflow:auto;
669670
border: 1px solid #444444;
670671
*/
672+
a.tree-link {
673+
display: inline-block;
674+
padding: 5px;
675+
}
676+
677+
a.tree-link.active {
678+
cursor: default;
679+
background-color: var(--light-color);
680+
font-weight: bold;
681+
border-radius: 2px;
682+
}
683+
684+
.tree-border-left{
685+
border-left: 2px dotted #eee;
686+
margin-left: 6px;
687+
}
671688
}
672689
.simpleTree li {
673690
list-style: none;

app/components/tree_infinite_scroll_component/tree_infinite_scroll_component.html.haml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
current_page: @current_page, next_page: @next_page) do |c|
55

66
%div
7-
%ul.simpleTree{data:{controller: 'simple-tree','simple-tree': { 'auto-click-value': auto_click? }, action: 'clicked->history#updateURL'}}
8-
%li.root
9-
%ul
10-
= content
7+
= render TreeViewComponent.new(id: nil, auto_click: auto_click?) do
8+
= content
119

1210
- c.error do
1311
%div.text-wrap

app/components/tree_link_component.rb

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# frozen_string_literal: true
2+
3+
class TreeLinkComponent < ViewComponent::Base
4+
include MultiLanguagesHelper
5+
include ComponentsHelper
6+
7+
def initialize(child:, href:, children_href: , selected_child: , data: {}, muted: false, target_frame: nil)
8+
@child = child
9+
@selected_child = selected_child
10+
@active_style = child.id.eql?(selected_child&.id) && 'active'
11+
#@icons = child.relation_icon(node)
12+
@muted_style = muted ? 'text-muted' : ''
13+
@href = href
14+
@children_link = children_href
15+
if @child.prefLabel.nil?
16+
@pref_label_html = child.id.split('/').last
17+
else
18+
pref_label_lang, @pref_label_html = select_language_label(@child.prefLabel)
19+
pref_label_lang = pref_label_lang.to_s.upcase
20+
@tooltip = pref_label_lang.eql?("@NONE") ? "" : pref_label_lang
21+
end
22+
@data ||= { controller: 'tooltip', 'tooltip-position-value': 'right', turbo: true, 'turbo-frame': target_frame, action: 'click->simple-tree#select'}
23+
24+
@data.merge!(data) do |_, old, new|
25+
"#{old} #{new}"
26+
end
27+
end
28+
29+
30+
# This gives a very hacky short code to use to uniquely represent a class
31+
# based on its parent in a tree. Used for unique ids in HTML for the tree view
32+
def short_uuid
33+
rand(36 ** 8).to_s(36)
34+
end
35+
36+
# TDOD check where used
37+
def child_id
38+
@child.id.to_s.split('/').last
39+
end
40+
41+
def open?
42+
@child.expanded? ? 'open' : ''
43+
end
44+
45+
def border_left
46+
!@child.hasChildren && 'pl-3 tree-border-left'
47+
end
48+
49+
def li_id
50+
@child.id.eql?('bp_fake_root') ? 'bp_fake_root' : short_uuid
51+
end
52+
53+
54+
def open_children_link
55+
return unless @child.hasChildren
56+
if @child.expanded?
57+
tree_close_icon
58+
else
59+
content_tag('turbo_frame', id: "#{child_id}_open_link") do
60+
link_to @children_link,
61+
data: { turbo: true, turbo_frame: "#{child_id + '_childs'}" } do
62+
content_tag(:i, nil, class: "fas fa-chevron-right")
63+
end
64+
end
65+
end
66+
67+
end
68+
69+
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
%li{id:li_id , class: open?}
2+
= open_children_link
3+
%a{id: @child.id, data: @data, title: @tooltip,
4+
href: @href, class: "tree-link #{@muted_style} #{@active_style} #{border_left} #{open?}"}
5+
= @pref_label_html
6+
7+
- if @child.hasChildren && [email protected]?
8+
= render TurboFrameComponent.new(id: "#{child_id}_childs")
9+
- elsif @child.expanded?
10+
= content

app/components/tree_view_component.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# frozen_string_literal: true
2+
3+
class TreeViewComponent < ViewComponent::Base
4+
include Turbo::FramesHelper
5+
include ComponentsHelper
6+
7+
renders_many :children, TreeLinkComponent
8+
9+
def initialize(id:, auto_click: false, sub_tree: false, **html_options)
10+
@id = id
11+
@auto_click = auto_click
12+
@html_options = html_options
13+
@sub_tree = sub_tree
14+
end
15+
16+
private
17+
18+
def sub_tree?
19+
@sub_tree
20+
end
21+
22+
def tree_container(&block)
23+
if sub_tree?
24+
content_tag(:ul, capture(&block), class: 'pl-2 tree-border-left')
25+
else
26+
content_tag(:div, class: 'tree_wrapper hide-if-loading') do
27+
content_tag(:ul, capture(&block), class: 'simpleTree root', data: { controller: 'simple-tree',
28+
'simple-tree-auto-click-value': "#{auto_click?}",
29+
action: 'clicked->history#updateURL' })
30+
end
31+
end
32+
end
33+
34+
def auto_click?
35+
@auto_click.to_s
36+
end
37+
38+
# TDOD check where used
39+
def child_id(child)
40+
child.id.to_s.split('/').last
41+
end
42+
43+
end
44+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
%turbo-frame{id: "#{@id}", **@html_options}
2+
= tree_container do
3+
- children.each do |child|
4+
= child
5+
= content
6+
7+
8+
9+

app/controllers/application_controller.rb

Lines changed: 9 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,6 @@ def to_param(name) # Paramaterizes URLs without encoding
157157
end
158158
end
159159

160-
def undo_param(name) #Undo Paramaterization
161-
unless name.nil?
162-
name.to_s.gsub('_'," ")
163-
end
164-
end
165-
166160
def bp_config_json
167161
# For config settings, see
168162
# config/bioportal_config.rb
@@ -188,22 +182,6 @@ def bp_config_json
188182
config.to_json
189183
end
190184

191-
def remote_file_exists?(url)
192-
begin
193-
url = URI.parse(url)
194-
195-
if url.kind_of?(URI::FTP)
196-
check = check_ftp_file(url)
197-
else
198-
check = check_http_file(url)
199-
end
200-
201-
rescue
202-
return false
203-
end
204-
205-
check
206-
end
207185

208186
def rest_url
209187
# Split the URL into protocol and path parts
@@ -308,15 +286,6 @@ def redirect_to_home # Redirect to Home Page
308286
redirect_to "/"
309287
end
310288

311-
def redirect_to_history # Redirects to the correct tab through the history system
312-
if session[:redirect].nil?
313-
redirect_to_home
314-
else
315-
tab = find_tab(session[:redirect][:ontology])
316-
session[:redirect]=nil
317-
redirect_to uri_url(:ontology=>tab.ontology_id,:conceptid=>tab.concept)
318-
end
319-
end
320289

321290
def redirect_new_api(class_view = false)
322291
# Hack to make ontologyid and conceptid work in addition to id and ontology params
@@ -373,24 +342,6 @@ def authorize_and_redirect
373342
end
374343
end
375344

376-
# Verifies that a user owns an object
377-
def authorize_owner(id=nil)
378-
if id.nil?
379-
id = params[:id].to_i
380-
end
381-
382-
id.map! {|i| i.to_i} if id.kind_of?(Array)
383-
384-
if session[:user].nil?
385-
redirect_to_home
386-
else
387-
if id.kind_of?(Array)
388-
redirect_to_home if !session[:user].admin? && !id.include?(session[:user].id.to_i)
389-
else
390-
redirect_to_home if !session[:user].admin? && !session[:user].id.to_i.eql?(id)
391-
end
392-
end
393-
end
394345

395346
def authorize_admin
396347
admin = session[:user] && session[:user].admin?
@@ -405,41 +356,7 @@ def ontology_restricted?(acronym)
405356
restrict_downloads = $NOT_DOWNLOADABLE
406357
restrict_downloads.include? acronym
407358
end
408-
# updates the 'history' tab with the current selected concept
409-
def update_tab(ontology, concept)
410-
array = session[:ontologies] || []
411-
found = false
412-
for item in array
413-
if item.ontology_id.eql?(ontology.id)
414-
item.concept=concept
415-
found=true
416-
end
417-
end
418-
419-
unless found
420-
array << History.new(ontology.id, ontology.name, ontology.acronym, concept)
421-
end
422-
423-
session[:ontologies]=array
424-
end
425-
426-
# Removes a 'history' tab
427-
def remove_tab(ontology_id)
428-
array = session[:ontologies]
429-
array.delete(find_tab(ontology_id))
430-
session[:ontologies]=array
431-
end
432359

433-
# Returns a specific 'history' tab
434-
def find_tab(ontology_id)
435-
array = session[:ontologies]
436-
for item in array
437-
if item.ontology_id.eql?(ontology_id)
438-
return item
439-
end
440-
end
441-
return nil
442-
end
443360

444361
def check_delete_mapping_permission(mappings)
445362
# ensure mappings is an Array of mappings (some calls may provide only a single mapping instance)
@@ -463,13 +380,13 @@ def using_captcha?
463380
def get_class(params)
464381

465382
lang = request_lang
466-
383+
467384
if @ontology.flat?
468385

469386
ignore_concept_param = params[:conceptid].nil? ||
470-
params[:conceptid].empty? ||
471-
params[:conceptid].eql?("root") ||
472-
params[:conceptid].eql?("bp_fake_root")
387+
params[:conceptid].empty? ||
388+
params[:conceptid].eql?("root") ||
389+
params[:conceptid].eql?("bp_fake_root")
473390
if ignore_concept_param
474391
# Don't display any classes in the tree
475392
@concept = LinkedData::Client::Models::Class.new
@@ -491,19 +408,19 @@ def get_class(params)
491408
# not ignoring 'bp_fake_root' here
492409
include = 'prefLabel,hasChildren,obsolete'
493410
ignore_concept_param = params[:conceptid].nil? ||
494-
params[:conceptid].empty? ||
495-
params[:conceptid].eql?("root")
411+
params[:conceptid].empty? ||
412+
params[:conceptid].eql?("root")
496413
if ignore_concept_param
497414
# get the top level nodes for the root
498415
# TODO_REV: Support views? Replace old view call: @ontology.top_level_classes(view)
499-
@roots = @ontology.explore.roots(concept_schemes: params[:concept_schemes])
416+
@roots = @ontology.explore.roots(concept_schemes: params[:concept_schemes])
500417
if @roots.nil? || @roots.empty?
501418
LOG.add :debug, "Missing @roots for #{@ontology.acronym}"
502419
classes = @ontology.explore.classes.collection
503420
@concept = classes.first.explore.self(full: true) if classes.first
504421
return
505422
end
506-
423+
507424
@root = LinkedData::Client::Models::Class.new(read_only: true)
508425
@root.children = @roots.sort{|x,y| (x.prefLabel || "").downcase <=> (y.prefLabel || "").downcase}
509426

@@ -569,17 +486,7 @@ def get_simplified_ontologies_hash()
569486
return simple_ontologies
570487
end
571488

572-
def get_ontology_details(ont_uri)
573-
# Note the simplify_ontology_model will cache individual ontology data.
574-
begin
575-
ont_model = LinkedData::Client::Models::Ontology.find(ont_uri)
576-
ont = simplify_ontology_model(ont_model)
577-
rescue Exception => e
578-
LOG.add :error, e.message
579-
return nil
580-
end
581-
return ont
582-
end
489+
583490

584491
def simplify_classes(classes)
585492
# Simplify the classes batch service data for the UI

0 commit comments

Comments
 (0)