File Coverage

blib/lib/RapidApp/Module/Explorer.pm
Criterion Covered Total %
statement 29 63 46.0
branch 6 28 21.4
condition 1 2 50.0
subroutine 7 12 58.3
pod 0 4 0.0
total 43 109 39.4


line stmt bran cond sub pod time code
1             package RapidApp::Module::Explorer;
2              
3 4     4   2677 use strict;
  4         13  
  4         136  
4 4     4   26 use warnings;
  4         15  
  4         137  
5              
6             # ABSTRACT: General-purpose 'Explorer' - nav tree with tab content
7              
8 4     4   20 use Moose;
  4         9  
  4         29  
9             extends 'RapidApp::Module::ExtComponent';
10              
11 4     4   24328 use RapidApp::Util qw(:all);
  4         10  
  4         6549  
12              
13             require Module::Runtime;
14              
15             has 'title', is => 'ro', default => 'AppExplorer';
16             has 'right_footer', is => 'ro', lazy => 1, default => sub {(shift)->title};
17             has 'iconCls', is => 'ro', default => 'ra-icon-server-database';
18             has 'init_width', is => 'ro', default => 240;
19              
20             has 'navtree_class', is => 'ro', isa => 'Maybe[Str]', default => sub{undef};
21             has 'navtree_params', is => 'ro', isa => 'HashRef', lazy => 1, default => sub{{}};
22             has 'navtree_load_collapsed', is => 'ro', isa => 'Bool', default => 0;
23             has 'navtree_disabled', is => 'ro', isa => 'Bool', default => 0;
24              
25             has 'navtrees', is => 'ro', isa => 'ArrayRef', lazy => 1, default => sub {
26             my $self = shift;
27             die "either navtrees or navtree_class is required" unless ($self->navtree_class);
28             return [{
29             module => 'navtree',
30             class => $self->navtree_class,
31             params => $self->navtree_params
32             }];
33             };
34              
35             has 'dashboard_class', is => 'ro', isa => 'Maybe[Str]', default => sub {undef};
36             has 'dashboard_params', is => 'ro', isa => 'HashRef', lazy => 1, default => sub{{}};
37              
38             # NEW
39             has 'dashboard_url', is => 'ro', isa => 'Maybe[Str]', default => sub {undef};
40              
41             # New:
42             has 'navtree_footer_template', is => 'ro', isa => 'Maybe[Str]', default => sub {undef};
43              
44             # Totally new:
45             has 'tab_title_max_width', is => 'ro', isa => 'Str', default => '300px';
46              
47             # Extra optional class for rendering any tt files or other files
48             # Feature added with RapidApp::AppPageViewer in mind, but it doesn't
49             # actually care. This module will be loaded as 'page' and nothing else
50             # will be done (i.e. expects direct links from markup to access content)
51             has 'page_viewer_class', is => 'ro', isa => 'Maybe[Str]', default => sub {undef};
52             has 'page_viewer_params', is => 'ro', isa => 'HashRef', lazy => 1, default => sub{{}};
53              
54              
55             sub BUILD {
56 4     4 0 12 my $self = shift;
57            
58 4         9 my %seen = ();
59 4         10 for my $cnf (@{$self->navtrees}) {
  4         106  
60 4 50       24 my $name = $cnf->{module} or next;
61 4 50   4   31 next if try{ $self->get_Module($name) };
  4         119  
62 4 50       4386 my $class = $cnf->{class} or die "Missing class name";
63 4   50     27 my $params = $cnf->{params} || {};
64 4 50       32 die "Duplicate module '$name'" if ($seen{$name}++);
65            
66 4         21 Module::Runtime::require_module($class);
67 4         70 $self->apply_init_modules( $name => { class => $class, params => $params } );
68             }
69            
70 4 50       114 if ($self->dashboard_class) {
71 0         0 Module::Runtime::require_module($self->dashboard_class);
72 0         0 $self->apply_init_modules(
73             dashboard => {
74             class => $self->dashboard_class,
75             params => $self->dashboard_params
76             }
77             );
78             }
79            
80 4 50       106 if ($self->page_viewer_class) {
81 0           Module::Runtime::require_module($self->page_viewer_class);
82 0           $self->apply_init_modules(
83             page => {
84             class => $self->page_viewer_class,
85             params => $self->page_viewer_params
86             }
87             );
88             }
89             }
90              
91              
92             around 'content' => sub {
93             my $orig = shift;
94             my $self = shift;
95            
96             my $cnf = $self->$orig(@_);
97            
98             return { %$cnf,
99             id => 'explorer-id',
100             xtype => 'panel',
101             layout => 'border',
102             items => [
103             $self->content_area,
104             $self->navtree_area
105             ],
106             footer => \1,
107             footerCfg => {
108             tag => 'div',
109             # FIXME: convert to template
110             html => q{
111             <div class="ra-footer no-text-select"><div class="wrap">
112             <table width="100%"><tr>
113             <td width="25%">
114             <a class="left" target="_blank" href="http://www.rapidapp.info"></a>
115             <a class="ra-icon-refresh-tiny ra-autopanel-reloader" title="Reload Interface">
116             <span class="ra-autopanel-reloader">Reload Interface</span>
117             </a>
118             </td>
119             <td width="50%" class="center">
120             <div id="infostatus"></div>
121             </td>
122             <td width="25%" class="right">
123             } . $self->right_footer . q{
124             </td>
125             </tr></table>
126             </div></div>
127             }
128             },
129             };
130             };
131              
132             sub navtree_area {
133 0     0 0   my $self = shift;
134            
135 0 0         return () if ($self->navtree_disabled);
136              
137 0           my $west = {
138             region => 'west',
139             title => $self->title,
140             iconCls => $self->iconCls,
141             collapsible => \1,
142             split => \1,
143             minSize => 150,
144             width => $self->init_width,
145             margins => '3 3 3 3',
146             layout => 'fit',
147             tools => [{
148             id => 'refresh',
149             qtip => 'Refresh Nav Tree',
150             handler => jsfunc 'Ext.ux.RapidApp.NavCore.reloadMainNavTrees'
151             }],
152             collapseFirst => \0,
153             autoScroll => \0,
154             items => {
155             # We need to nest within an additional panel layer to ensure
156             # proper scrolling. Note that autoScroll is set in this panel,
157             # and *not* in the parent panel above (region: west)
158             id => 'main-navtrees-container',
159             xtype => 'panel',
160             autoScroll => \1,
161             border => \0, bodyBorder => \0,
162             items => $self->west_area_items
163             }
164             };
165            
166 0 0         $west->{collapsed} = \1 if ($self->navtree_load_collapsed);
167            
168             # Render a custom footer at the bottom of the navtree
169 0 0         if($self->navtree_footer_template) {
170 0           my $html;
171             try{
172 0     0     $html = $self->c->template_render(
173             $self->navtree_footer_template
174             );
175             }
176             catch {
177 0     0     my $err = shift;
178 0           $html = "$err";
179 0           };
180            
181 0           $west = { %$west,
182             bodyStyle => 'border-bottom: 0px;',
183             footer => \1,
184             footerCfg => {
185             tag => 'div',
186             cls => 'x-panel-body',
187             html => $html
188             }
189             };
190             }
191            
192 0           return $west;
193             }
194              
195             sub west_area_items {
196 0     0 0   my $self = shift;
197            
198             # Dynamic "typing" (of sorts). Allow raw ExtJS configs to
199             # be interspersed among module cnfs
200             my @items = map {
201 0 0         $_->{module} ? $self->get_Module($_->{module})->allowed_content : $_
202             } grep {
203             # New: exclude items where 'menu_require_role' is set but the
204             # current user does not have the role
205             ! $_->{menu_require_role} || $self->role_checker->($self->c,$_->{menu_require_role})
206 0 0         } @{$self->navtrees};
  0            
  0            
207            
208 0           return \@items;
209             }
210              
211              
212             sub content_area {
213 0     0 0   my $self = shift;
214            
215 0           my $cnf = {
216             # main-load-target is looked for by RapidApp js functions:
217             id => 'main-load-target',
218             region => 'center',
219             margins => '3 3 3 0',
220             bodyCssClass => 'sbl-panel-body-noborder',
221             };
222            
223 0 0         $cnf->{margins} = '3 3 3 3' if ($self->navtree_disabled);
224            
225 0           my $initTab = {
226             title => '&nbsp;',
227             iconCls => 'ra-tab-icon-only-16px ra-icon-home',
228             closable => \0,
229             autoLoad => {
230             params => {}
231             }
232             };
233              
234 0 0         if ($self->dashboard_class) {
    0          
235 0           $initTab->{autoLoad}{url} = $self->Module('dashboard')->base_url;
236 0           $cnf->{initLoadTabs} = [$initTab];
237             }
238             elsif ($self->dashboard_url) {
239 0           $initTab->{autopanel_ignore_tabtitle} = \1;
240 0           $initTab->{autoLoad}{url} = $self->dashboard_url;
241 0           $cnf->{initLoadTabs} = [$initTab];
242             }
243            
244 0           $cnf->{tab_title_max_width} = $self->tab_title_max_width;
245              
246 0           return RapidApp::JSONFunc->new(
247             func => 'new Ext.ux.RapidApp.AppTab.TabPanel',
248             parm => $cnf
249             );
250             }
251              
252              
253 4     4   35 no Moose;
  4         13  
  4         33  
254             __PACKAGE__->meta->make_immutable;
255             1;