Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision b251cc22

Von Sven Schöling vor mehr als 9 Jahren hinzugefügt

  • ID b251cc22f355941217493073e124ba3878d5530f
  • Vorgänger 15b1558e
  • Nachfolger cd306e61

Menüstruktur auf YAML geändert

Unterschiede anzeigen:

SL/Layout/Admin.pm
11 11
sub init_sub_layouts {
12 12
  [
13 13
    SL::Layout::None->new,
14
    SL::Layout::CssMenu->new(menu => Menu->new('menus/admin.ini')),
14
    SL::Layout::CssMenu->new(menu => SL::Menu->new('admin')),
15 15
  ]
16 16
}
17 17

  
SL/Layout/Base.pm
29 29
}
30 30

  
31 31
sub init_menu {
32
  my @menu_files = qw(menus/erp.ini);
33
  unshift @menu_files, 'menus/crm.ini' if $::instance_conf->crm_installed;
34
  Menu->new(@menu_files);
32
  SL::Menu->new('user');
35 33
}
36 34

  
37 35
sub init_auto_reload_resources_param {
SL/Layout/CssMenu.pm
3 3
use strict;
4 4
use parent qw(SL::Layout::Base);
5 5

  
6
use URI;
7

  
8
sub print_menu {
9
  my ($self, $parent, $depth) = @_;
10

  
11
  my $html;
12

  
13
  die if ($depth * 1 > 5);
14

  
15
  my @menuorder;
16
  my $menu = $self->menu;
17

  
18
  @menuorder = $menu->access_control(\%::myconfig, $parent);
19

  
20
  $parent .= "--" if ($parent);
21

  
22
  foreach my $item (@menuorder) {
23
    substr($item, 0, length($parent)) = "";
24
    next if (($item eq "") || ($item =~ /--/));
25

  
26
    my $menu_item = $menu->{"${parent}${item}"};
27
    my $menu_title = $::locale->text($item);
28
    my $menu_text = $menu_title;
29

  
30
    if ($menu_item->{"submenu"} || !defined($menu_item->{"module"}) && !defined($menu_item->{href})) {
31

  
32
      my $h = $self->print_menu("${parent}${item}", $depth * 1 + 1)."\n";
33
      if (!$parent) {
34
        $html .= qq|<ul><li><h2>${menu_text}</h2><ul>${h}</ul></li></ul>\n|;
35
      } else {
36
        $html .= qq|<li><div class="x">${menu_text}</div><ul>${h}</ul></li>\n|;
37
      }
38
    } else {
39
      if ($self->{sub_class} && $depth > 1) {
40
        $html .= qq|<li class='sub'>|;
41
      } else {
42
        $html .= qq|<li>|;
43
      }
44
      $html .= $self->menuitem_v3("${parent}$item", { "title" => $menu_title });
45
      $html .= qq|${menu_text}</a></li>\n|;
46
    }
47
  }
48

  
49
  return $html;
50
}
51

  
52
sub menuitem_v3 {
53
  $main::lxdebug->enter_sub();
54

  
55
  my ($self, $item, $other) = @_;
56
  my $menuitem = $self->menu->{$item};
57

  
58
  my $action = "section_menu";
59
  my $module;
60

  
61
  if ($menuitem->{module}) {
62
    $module = $menuitem->{module};
63
  }
64
  if ($menuitem->{action}) {
65
    $action = $menuitem->{action};
66
  }
67

  
68
  my $level  = $::form->escape($item);
69

  
70
  my @vars;
71
  my $target = $menuitem->{target} ? qq| target="| . $::form->escape($menuitem->{target}) . '"' : '';
72
  my $str    = qq|<a${target} href="|;
73

  
74
  if ($menuitem->{href}) {
75
    $main::lxdebug->leave_sub();
76
    return $str . $menuitem->{href} . '">';
77
  }
78

  
79
  $str .= qq|$module?action=| . $::form->escape($action);
80

  
81
  map { delete $menuitem->{$_} } qw(module action target href);
82

  
83
  # add other params
84
  foreach my $key (keys %{ $menuitem }) {
85
    $str .= "&amp;" . $::form->escape($key, 1) . "=";
86
    my ($value, $conf) = split(/=/, $menuitem->{$key}, 2);
87
    $value = $::myconfig{$value} . "/$conf" if ($conf);
88
    $str .= $::form->escape($value, 1);
89
  }
90

  
91
  $str .= '"';
92

  
93
  if ($other) {
94
    foreach my $key (keys(%{$other})) {
95
      $str .= qq| ${key}="| . $::form->quote($other->{$key}) . qq|"|;
96
    }
97
  }
98

  
99
  $str .= ">";
100

  
101
  $main::lxdebug->leave_sub();
102

  
103
  return $str;
104
}
105

  
106 6
sub use_stylesheet {
107 7
  qw(icons16.css frame_header/header.css),
108 8
}
109 9

  
110 10
sub pre_content {
111
  $_[0]->presenter->render('menu/menuv3',
112
    menu           => $_[0]->print_menu,
113
  );
11
  $_[0]->presenter->render('menu/menuv3', menu => $_[0]->menu);
114 12
}
115 13

  
116 14
1;
SL/Layout/Javascript.pm
21 21
  $self->SUPER::use_javascript(@_);
22 22
}
23 23

  
24
sub javascripts_inline {
25
  $_[0]->SUPER::javascripts_inline,
26
<<'EOJS'
27
  DHTMLSuite.createStandardObjects();
28
  DHTMLSuite.configObj.setImagePath('image/dhtmlsuite/');
29
  var menu_model = new DHTMLSuite.menuModel();
30
  menu_model.addItemsFromMarkup('main_menu_model');
31
  menu_model.init();
32
  var menu_bar = new DHTMLSuite.menuBar();
33
  menu_bar.addMenuItems(menu_model);
34
  menu_bar.setTarget('main_menu_div');
35
  menu_bar.init();
36
EOJS
37
}
38

  
24 39
sub pre_content {
25 40
  $_[0]->SUPER::pre_content .
26
  &display
41
  $_[0]->presenter->render("menu/menunew",
42
    force_ul_width  => 1,
43
    menu            => $_[0]->menu,
44
    icon_path       => sub { my $img = "image/icons/16x16/$_[0].png"; -f $img ? $img : () },
45
    max_width       => sub { 10 * max map { length $::locale->text($_->{name}) } @{ $_[0]{children} || [] } },
46
  );
27 47
}
28 48

  
29 49
sub start_content {
......
45 65
  $_[0]->SUPER::stylesheets;
46 66
}
47 67

  
48
sub display {
49
  my ($self) = @_;
50

  
51
  $self->presenter->render("menu/menunew",
52
    force_ul_width  => 1,
53
    menu_items      => $self->acc_menu,
54
  );
55
}
56

  
57
sub acc_menu {
58
  my ($self) = @_;
59

  
60
  my $menu      = $self->menu;
61

  
62
  my $all_items = [];
63
  $self->create_menu($menu, $all_items);
64

  
65
  my $item = { 'subitems' => $all_items };
66
  calculate_width($item);
67

  
68
  return $all_items;
69
}
70

  
71
sub calculate_width {
72
  my $item           = shift;
73

  
74
  $item->{max_width} = max map { length $_->{title} } @{ $item->{subitems} };
75

  
76
  foreach my $subitem (@{ $item->{subitems} }) {
77
    calculate_width($subitem) if ($subitem->{subitems});
78
  }
79
}
80

  
81
sub create_menu {
82
  my ($self, $menu, $all_items, $parent, $depth) = @_;
83
  my $html;
84

  
85
  my $form     = $main::form;
86
  my %myconfig = %main::myconfig;
87

  
88
  $depth ||= 0;
89

  
90
  die if ($depth * 1 > 5);
91

  
92
  my @menuorder  = $menu->access_control(\%myconfig, $parent);
93
  $parent       .= "--" if ($parent);
94
  $parent      ||= '';
95

  
96
  foreach my $name (@menuorder) {
97
    substr($name, 0, length($parent), "");
98
    next if (($name eq "") || ($name =~ /--/));
99

  
100
    my $menu_item = $menu->{"${parent}${name}"};
101
    my $item      = { 'title' => $::locale->text($name) };
102
    push @{ $all_items }, $item;
103

  
104
    if ($menu_item->{submenu} || (!defined($menu_item->{module}) && !defined($menu_item->{href}))) {
105
      $item->{subitems} = [];
106
      $item->{image} = _icon_path($menu_item->{ICON});
107
      $self->create_menu($menu, $item->{subitems}, "${parent}${name}", $depth * 1 + 1);
108

  
109
    } else {
110
      $item->{image} = _icon_path("${parent}${name}.png");
111
      $menu->menuitem_new("${parent}${name}", $item);
112
    }
113
  }
114
}
115

  
116
sub _icon_path {
117
  my ($label, $size) = @_;
118

  
119
  $size ||= 16;
120

  
121
  my $img = "image/icons/${size}x${size}/$label.png";
122

  
123
  return unless -f $img;
124
  return $img;
125
}
126

  
127 68
1;
SL/Layout/MenuLeft.pm
40 40

  
41 41
sub section_menu {
42 42
  my ($menu) = @_;
43
  my @menuorder = @{ $menu->{ORDER} };
44 43
  my @items;
45 44
  my @id_stack = (-1);
46 45

  
47
  for my $item (@menuorder) {
48
    my $menuitem   = $menu->{$item};
49
    my $olabel     = apply { s/.*--// } $item;
50
    my $ml         = apply { s/--.*// } $item;
51
    my $icon_class = apply { $_ = lc $_; s/[^a-z0-9_-]/-/g } $menuitem->{ICON};
52
    my $level      = (0 + $item =~ s/--/--/g);
53
    my $spacer     = "s" . $level;
46
  for my $node ($menu->tree_walk) {
47
    my $level      = $node->{level};
54 48

  
55 49
    # do id stack
56 50
    push @id_stack, -1 if    $level > $#id_stack;
57 51
    pop @id_stack      while $level < $#id_stack;
58 52
    $id_stack[-1]++;
59 53

  
60
    my $label         = $::locale->text($olabel);
54
    my $label = $::locale->text($node->{name});
55
    my $href  = $menu->href_for_node($node);
61 56

  
62
    $menuitem->{module} ||= $::form->{script};
63
    $menuitem->{action} ||= "section_menu";
64
    $menuitem->{href}   ||= "$menuitem->{module}?action=$menuitem->{action}";
57
    my @common_args  = ($label, "s" . $level, join '_', @id_stack);
65 58

  
66
    # add other params
67
    foreach my $key (keys %$menuitem) {
68
      next if $key =~ /target|module|action|href|ICON/;
69
      $menuitem->{href} .= "&" . $::form->escape($key, 1) . "=";
70
      my ($value, $conf) = split(/=/, $menuitem->{$key}, 2);
71
      $value = $::myconfig{$value} . "/$conf" if ($conf);
72
      $menuitem->{href} .= $::form->escape($value, 1);
73
    }
74

  
75
    my @common_args  = ($label, $spacer, join '_', @id_stack);
76

  
77
    if ($spacer eq 's0') { # toplevel
78
      push @items, [ @common_args, "icon24 $icon_class", 'm' ];
79
    } elsif ($menuitem->{submenu}) {
59
    if (!$node->{parent}) { # toplevel
60
      push @items, [ @common_args, "icon24 $node->{icon}", 'm' ];
61
    } elsif ($node->{children}) {
80 62
      push @items, [ @common_args, "icon16 submenu", 'sm' ];
81
    } elsif ($menuitem->{module}) {
82
      push @items, [ @common_args, "icon16 $icon_class", 'i', $menuitem->{href}, $menuitem->{target} ];
63
    } else {
64
      push @items, [ @common_args, "icon16 $node->{icon}", 'i', $href, $node->{target} ];
83 65
    }
84 66
  }
85 67

  
SL/Menu.pm
1
#=====================================================================
2
# LX-Office ERP
3
# Copyright (C) 2004
4
# Based on SQL-Ledger Version 2.1.9
5
# Web http://www.lx-office.org
6
#
7
#=====================================================================
8
# SQL-Ledger Accounting
9
# Copyright (C) 2001
10
#
11
#  Author: Dieter Simader
12
#   Email: dsimader@sql-ledger.org
13
#     Web: http://www.sql-ledger.org
14
#
15
#  Contributors:
16
#
17
# This program is free software; you can redistribute it and/or modify
18
# it under the terms of the GNU General Public License as published by
19
# the Free Software Foundation; either version 2 of the License, or
20
# (at your option) any later version.
21
#
22
# This program is distributed in the hope that it will be useful,
23
# but WITHOUT ANY WARRANTY; without even the implied warranty of
24
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
# GNU General Public License for more details.
26
# You should have received a copy of the GNU General Public License
27
# along with this program; if not, write to the Free Software
28
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29
#=====================================================================
30
#
31
# routines for menu items
32
#
33
#=====================================================================
34

  
35
package Menu;
1
package SL::Menu;
36 2

  
37 3
use strict;
38 4

  
39 5
use SL::Auth;
40
use SL::Inifile;
41

  
42
our @ISA = qw(Inifile);
43

  
6
use YAML::XS ();
7
use File::Spec;
8
use SL::MoreCommon qw(uri_encode);
44 9

  
45 10
sub new {
46
  $main::lxdebug->enter_sub();
11
  my ($package, $domain) = @_;
47 12

  
48
  my ($package, @menufiles) = @_;
13
  my $path = File::Spec->catdir('menus', $domain);
49 14

  
50
  my $self = $package->SUPER::new($menufiles[0]);
15
  opendir my $dir, $path or die "can't open $path: $!";
16
  my @files = sort grep -f "$path/$_", readdir $dir;
17
  close $dir;
51 18

  
52
  for (@menufiles[1..$#menufiles]) {
53
    my $inifile = Inifile->new($_);
54
    push @{ $self->{ORDER} }, @{ delete $inifile->{ORDER} };
55
    $self->{$_} = $inifile->{$_} for keys %$inifile;
19
  my $nodes = [];
20
  my $nodes_by_id = {};
21
  for my $file (@files) {
22
    my $data = YAML::XS::LoadFile(File::Spec->catfile($path, $file));
23
    _merge($nodes, $nodes_by_id, $data);
56 24
  }
57 25

  
58
  $self->set_access;
59 26

  
60
  $main::lxdebug->leave_sub();
27
  my $self = bless {
28
    nodes => $nodes,
29
    by_id => $nodes_by_id,
30
  }, $package;
31

  
32
  $self->build_tree;
33
  $self->set_access;
61 34

  
62 35
  return $self;
63 36
}
64 37

  
65
sub menuitem_new {
66
  $main::lxdebug->enter_sub(LXDebug::DEBUG2());
38
sub _merge {
39
  my ($nodes, $by_id, $data) = @_;
67 40

  
68
  my ($self, $name, $item) = @_;
41
  die 'not an array ref' unless $data && 'ARRAY' eq ref $data; # TODO check this sooner, to get better diag to user
69 42

  
70
  my $module      = $self->{$name}->{module} || $::form->{script};
71
  my $action      = $self->{$name}->{action};
43
  for my $node (@$data) {
44
    my $id = $node->{id};
72 45

  
73
  $item->{target} = $self->{$name}->{target} || "main_window";
74
  $item->{href}   = $self->{$name}->{href}   || "${module}?action=" . $::form->escape($action);
46
    my $merge_to = $by_id->{$id};
75 47

  
76
  my @vars = qw(module target href);
77
  push @vars, 'action' unless ($self->{$name}->{href});
48
    if (!$merge_to) {
49
      push @$nodes, $node;
50
      $by_id->{$id} = $node;
51
      next;
52
    }
78 53

  
79
  map { delete $self->{$name}{$_} } @vars;
54
    # TODO make this a real recursive merge
55
    # TODO add support for arrays
56

  
57
    # merge keys except params
58
    for my $key (keys %$node) {
59
      if (ref $node->{$key}) {
60
        if ('HASH' eq ref $node->{$key}) {
61
          $merge_to->{$key} = {} if !exists $merge_to->{$key} || 'HASH' ne ref $merge_to->{$key};
62
          for (keys %{ $node->{params} }) {
63
            $merge_to->{$key}{$_} = $node->{params}{$_};
64
          }
65
        } else {
66
          die "unsupported structure @{[ ref $node->{$key} ]}";
67
        }
68
      } else {
69
        $merge_to->{$key} = $node->{$key};
70
      }
71
    }
72
  }
73
}
80 74

  
81
  # add other params
82
  foreach my $key (keys %{ $self->{$name} }) {
83
    my ($value, $conf)  = split(m/=/, $self->{$name}->{$key}, 2);
84
    $value              = $::myconfig->{$value} . "/$conf" if ($conf);
85
    $item->{href}      .= "&" . $::form->escape($key) . "=" . $::form->escape($value);
75
sub build_tree {
76
  my ($self) = @_;
77

  
78
  # first, some sanity check. are all parents valid ids or empty?
79
  for my $node ($self->nodes) {
80
    next if !exists $node->{parent} || !$node->{parent} || $self->{by_id}->{$node->{id}};
81
    die "menu: node $node->{id} has non-existant parent $node->{parent}";
86 82
  }
87 83

  
88
  $main::lxdebug->leave_sub(LXDebug::DEBUG2());
89
}
84
  my %by_parent;
85
  # order them by parent
86
  for my $node ($self->nodes) {
87
    push @{ $by_parent{ $node->{parent} } //= [] }, $node;
88
  }
90 89

  
91
sub access_control {
92
  $main::lxdebug->enter_sub(2);
90
  my $tree = { };
91
  $self->{by_id}{''} = $tree;
93 92

  
94
  my ($self, $myconfig, $menulevel) = @_;
95 93

  
96
  my @menu = ();
94
  for (keys %by_parent) {
95
    my $parent = $self->{by_id}{$_};
96
    $parent->{children} =  [ sort { $a->{order} <=> $b->{order} } @{ $by_parent{$_} } ];
97
  }
98

  
99
  _set_level_rec($tree->{children}, 0);
100

  
101
  $self->{tree} = $tree->{children};
102
}
103

  
104
sub _set_level_rec {
105
  my ($ary_ref, $level) = @_;
97 106

  
98
  if (!$menulevel) {
99
    @menu = grep { !/--/ } @{ $self->{ORDER} };
100
  } else {
101
    @menu = grep { /^${menulevel}--/ } @{ $self->{ORDER} };
107
  for (@$ary_ref) {
108
    $_->{level} = $level;
109
    _set_level_rec($_->{children}, $level + 1) if $_->{children};
102 110
  }
111
}
103 112

  
104
  $main::lxdebug->leave_sub(2);
113
sub nodes {
114
  @{ $_[0]{nodes} }
115
}
116

  
117
sub tree_walk {
118
  my ($self, $all) = @_;
105 119

  
106
  return @menu;
120
  _tree_walk_rec($self->{tree}, $all);
107 121
}
108 122

  
109
sub parse_access_string {
110
  my $self   = shift;
111
  my $key    = shift;
112
  my $access = shift;
123
sub _tree_walk_rec {
124
  my ($ary_ref, $all) = @_;
125
  map { $_->{children} ? ($_, _tree_walk_rec($_->{children}, $all)) : ($_) } grep { $all || $_->{visible} } @$ary_ref;
126
}
113 127

  
114
  my $form        =  $main::form;
115
  my $auth        =  $main::auth;
116
  my $myconfig    = \%main::myconfig;
128
sub parse_access_string {
129
  my ($self, $node) = @_;
117 130

  
118 131
  my @stack;
119 132
  my $cur_ary = [];
120 133

  
121 134
  push @stack, $cur_ary;
122 135

  
123
  while ($access =~ m/^([a-z_]+|\||\&|\(|\)|\s+)/) {
136
  my $access = $node->{access};
137

  
138
  while ($access =~ m/^([a-z_\/]+|\||\&|\(|\)|\s+)/) {
124 139
    my $token = $1;
125 140
    substr($access, 0, length($1)) = "";
126 141

  
......
135 150
    } elsif ($token eq ")") {
136 151
      pop @stack;
137 152
      if (!@stack) {
138
        $form->error("Error in menu.ini for entry ${key}: missing '('");
153
        die "Error in menu.ini for entry $node->{id}: missing '('";
139 154
      }
140 155
      $cur_ary = $stack[-1];
141 156

  
......
143 158
      push @{$cur_ary}, $token;
144 159

  
145 160
    } else {
146
      push @{$cur_ary}, $auth->check_right($::myconfig{login}, $token, 1);
161
      if ($token =~ m{^ client / (.*) }x) {
162
        push @{$cur_ary}, $self->parse_instance_conf_string($1);
163
      } else {
164
        push @{$cur_ary}, $::auth->check_right($::myconfig{login}, $token, 1);
165
      }
147 166
    }
148 167
  }
149 168

  
150 169
  if ($access) {
151
    $form->error("Error in menu.ini for entry ${key}: unrecognized token at the start of '$access'\n");
170
    die "Error in menu.ini for entry $node->{id}: unrecognized token at the start of '$access'\n";
152 171
  }
153 172

  
154 173
  if (1 < scalar @stack) {
155
    $main::form->error("Error in menu.ini for entry ${key}: Missing ')'\n");
174
    die "Error in menu.ini for entry $node->{id}: Missing ')'\n";
156 175
  }
157 176

  
158 177
  return SL::Auth::evaluate_rights_ary($stack[0]);
159 178
}
160 179

  
161
sub parse_instance_conf_string {
162
  my ($self, $setting) = @_;
163
  return $::instance_conf->data->{$setting};
164
}
165

  
166
sub set_access {
167
  my $self = shift;
168

  
169
  my $key;
170

  
171
  foreach $key (@{ $self->{ORDER} }) {
172
    my $entry = $self->{$key};
173

  
174
    $entry->{GRANTED}              = $entry->{ACCESS} ? $self->parse_access_string($key, $entry->{ACCESS}) : 1;
175
    $entry->{GRANTED}            &&= $self->parse_instance_conf_string($entry->{INSTANCE_CONF}) if $entry->{INSTANCE_CONF};
176
    $entry->{IS_MENU}              = $entry->{submenu} || ($key !~ m/--/);
177
    $entry->{NUM_VISIBLE_CHILDREN} = 0;
178

  
179
    if ($key =~ m/--/) {
180
      my $parent = $key;
181
      substr($parent, rindex($parent, '--')) = '';
182
      $entry->{GRANTED} &&= $self->{$parent}->{GRANTED};
183
    }
184

  
185
    $entry->{VISIBLE} = $entry->{GRANTED};
186
  }
187

  
188
  foreach $key (reverse @{ $self->{ORDER} }) {
189
    my $entry = $self->{$key};
180
sub href_for_node {
181
  my ($self, $node) = @_;
190 182

  
191
    if ($entry->{IS_MENU}) {
192
      $entry->{VISIBLE} &&= $entry->{NUM_VISIBLE_CHILDREN} > 0;
193
    }
183
  return undef if !$node->{href} && !$node->{module} && !$node->{params};
194 184

  
195
    next if (($key !~ m/--/) || !$entry->{VISIBLE});
185
  my $href = $node->{href} || $node->{module} || 'controller.pl';
186
  my @tokens;
196 187

  
197
    my $parent = $key;
198
    substr($parent, rindex($parent, '--')) = '';
199
    $self->{$parent}->{NUM_VISIBLE_CHILDREN}++;
188
  while (my ($key, $value) = each %{ $node->{params} }) {
189
    push @tokens, uri_encode($key, 1) . "=" . uri_encode($value, 1);
200 190
  }
201 191

  
202
#   $self->dump_visible();
192
  return join '?', $href, grep $_, join '&', @tokens;
193
}
203 194

  
204
  $self->{ORDER} = [ grep { $self->{$_}->{VISIBLE} } @{ $self->{ORDER} } ];
195
sub name_for_node {
196
  $::locale->text($_[1]{name})
197
}
205 198

  
206
  { no strict 'refs';
207
  # ToDO: fix this. nuke and pave algorithm without type checking screams for problems.
208
  map { delete @{$self->{$_}}{qw(GRANTED IS_MENU NUM_VISIBLE_CHILDREN VISIBLE ACCESS)} if ($_ ne 'ORDER') } keys %{ $self };
209
  }
199
sub parse_instance_conf_string {
200
  my ($self, $setting) = @_;
201
  return $::instance_conf->data->{$setting};
210 202
}
211 203

  
212
sub dump_visible {
213
  my $self = shift;
214
  foreach my $key (@{ $self->{ORDER} }) {
215
    my $entry = $self->{$key};
216
    $main::lxdebug->message(0, "$entry->{GRANTED} $entry->{VISIBLE} $entry->{NUM_VISIBLE_CHILDREN} $key");
204
sub set_access {
205
  my ($self) = @_;
206
  # 1. evaluate access for all
207
  # 2. if a menu has no visible children, its not visible either
208

  
209
  for my $node (reverse $self->tree_walk("all")) {
210
    $node->{visible} = $node->{access}           ? $self->parse_access_string($node)
211
                     : !$node->{children}        ? 1
212
                     : $node->{visible_children} ? 1
213
                     :                             0;
214
    if ($node->{visible} && $node->{parent}) {
215
      $self->{by_id}{ $node->{parent} }{visible_children} = 1;
216
    }
217 217
  }
218 218
}
219 219

  
menus/admin/00-admin.yaml
1
---
2
- id: users_clients_and_user_groups
3
  name: Users, Clients and User Groups
4
  order: 100
5
- parent: users_clients_and_user_groups
6
  id: users_clients_and_user_groups_list_users_clients_and_user_groups
7
  name: List Users, Clients and User Groups
8
  order: 100
9
  params: 
10
    action: Admin/show
11
- parent: users_clients_and_user_groups
12
  id: users_clients_and_user_groups_add_user
13
  name: Add User
14
  order: 200
15
  params: 
16
    action: Admin/new_user
17
- parent: users_clients_and_user_groups
18
  id: users_clients_and_user_groups_add_client
19
  name: Add Client
20
  order: 300
21
  params: 
22
    action: Admin/new_client
23
- parent: users_clients_and_user_groups
24
  id: users_clients_and_user_groups_add_user_group
25
  name: Add User Group
26
  order: 400
27
  params: 
28
    action: Admin/new_group
29
- id: database_management
30
  name: Database Management
31
  order: 200
32
- parent: database_management
33
  id: database_management_create_dataset
34
  name: Create Dataset
35
  order: 100
36
  params: 
37
    action: Admin/create_dataset_login
38
- parent: database_management
39
  id: database_management_delete_dataset
40
  name: Delete Dataset
41
  order: 200
42
  params: 
43
    action: Admin/delete_dataset_login
44
- id: printer_management
45
  name: Printer Management
46
  order: 300
47
- parent: printer_management
48
  id: printer_management_list_printers
49
  name: List Printers
50
  order: 100
51
  params: 
52
    action: Admin/list_printers
53
- parent: printer_management
54
  id: printer_management_add_printer
55
  name: Add Printer
56
  order: 200
57
  params: 
58
    action: Admin/new_printer
59
- id: system
60
  name: System
61
  icon: system
62
  order: 400
63
- parent: system
64
  id: system_lock_and_unlock_installation
65
  name: Lock and unlock installation
66
  order: 100
67
  params: 
68
    action: Admin/show_lock
69
- parent: system
70
  id: system_documentation_in_german_
71
  name: Documentation (in German)
72
  order: 200
73
  href: doc/kivitendo-Dokumentation.pdf
74
  target: _blank
75
- parent: system
76
  id: system_kivitendo_website_external_
77
  name: kivitendo website (external)
78
  order: 300
79
  href: http://www.kivitendo.de/
80
  target: _blank
81
- parent: system
82
  id: system_to_user_login
83
  name: To user login
84
  order: 400
85
  params: 
86
    action: LoginScreen/user_login
87
- parent: system
88
  id: system_logout
89
  name: Logout
90
  order: 500
91
  params: 
92
    action: Admin/logout
menus/user/00-erp.yaml
1
---
2
- id: master_data
3
  name: Master Data
4
  icon: master_data
5
  order: 100
6
- parent: master_data
7
  id: master_data_add_customer
8
  name: Add Customer
9
  icon: customer_add
10
  order: 100
11
  access: customer_vendor_edit
12
  params: 
13
    action: CustomerVendor/add
14
    db: customer
15
- parent: master_data
16
  id: master_data_add_vendor
17
  name: Add Vendor
18
  icon: vendor_add
19
  order: 200
20
  access: customer_vendor_edit
21
  params: 
22
    action: CustomerVendor/add
23
    db: vendor
24
- parent: master_data
25
  id: master_data_add_part
26
  name: Add Part
27
  icon: part_add
28
  order: 300
29
  access: part_service_assembly_edit
30
  module: ic.pl
31
  params: 
32
    action: add
33
    item: part
34
- parent: master_data
35
  id: master_data_add_service
36
  name: Add Service
37
  icon: service_add
38
  order: 400
39
  access: part_service_assembly_edit
40
  module: ic.pl
41
  params: 
42
    action: add
43
    item: service
44
- parent: master_data
45
  id: master_data_add_assembly
46
  name: Add Assembly
47
  icon: assembly_add
48
  order: 500
49
  access: part_service_assembly_edit
50
  module: ic.pl
51
  params: 
52
    action: add
53
    item: assembly
54
- parent: master_data
55
  id: master_data_add_project
56
  name: Add Project
57
  icon: project_add
58
  order: 600
59
  access: project_edit
60
  params: 
61
    action: Project/new
62
- parent: master_data
63
  id: master_data_add_requirement_spec_template
64
  name: Add Requirement Spec Template
65
  order: 700
66
  access: requirement_spec_edit
67
  params: 
68
    action: RequirementSpec/new
69
    is_template: 1
70
- parent: master_data
71
  id: master_data_update_prices
72
  name: Update Prices
73
  icon: prices_update
74
  order: 800
75
  access: part_service_assembly_edit
76
  module: ic.pl
77
  params: 
78
    action: search_update_prices
79
- parent: master_data
80
  id: master_data_price_rules
81
  name: Price Rules
82
  order: 900
83
  access: part_service_assembly_edit
84
  params: 
85
    action: PriceRule/list
86
    filter.obsolete: 0
87
- parent: master_data
88
  id: master_data_reports
89
  name: Reports
90
  icon: master_data_report
91
  order: 1000
92
  module: menu.pl
93
  params: 
94
    action: acc_menu
95
- parent: master_data_reports
96
  id: master_data_reports_customers
97
  name: Customers
98
  icon: customer_report
99
  order: 100
100
  access: customer_vendor_edit
101
  params: 
102
    action: CustomerVendor/search
103
    db: customer
104
- parent: master_data_reports
105
  id: master_data_reports_vendors
106
  name: Vendors
107
  icon: vendor_report
108
  order: 200
109
  access: customer_vendor_edit
110
  params: 
111
    action: CustomerVendor/search
112
    db: vendor
113
- parent: master_data_reports
114
  id: master_data_reports_contacts
115
  name: Contacts
116
  order: 300
117
  access: customer_vendor_edit
118
  params: 
119
    action: CustomerVendor/search_contact
120
    db: customer
121
- parent: master_data_reports
122
  id: master_data_reports_parts
123
  name: Parts
124
  icon: part_report
125
  order: 400
126
  access: part_service_assembly_details
127
  module: ic.pl
128
  params: 
129
    action: search
130
    searchitems: part
131
- parent: master_data_reports
132
  id: master_data_reports_services
133
  name: Services
134
  icon: service_report
135
  order: 500
136
  access: part_service_assembly_details
137
  module: ic.pl
138
  params: 
139
    action: search
140
    searchitems: service
141
- parent: master_data_reports
142
  id: master_data_reports_assemblies
143
  name: Assemblies
144
  icon: assembly_report
145
  order: 600
146
  access: part_service_assembly_details
147
  module: ic.pl
148
  params: 
149
    action: search
150
    searchitems: assembly
151
- parent: master_data_reports
152
  id: master_data_reports_projects
153
  name: Projects
154
  icon: project_report
155
  order: 700
156
  access: project_edit
157
  params: 
158
    action: Project/list
159
    filter.active: active
160
    filter.valid: valid
161
- parent: master_data_reports
162
  id: master_data_reports_requirement_spec_templates
163
  name: Requirement Spec Templates
164
  order: 800
165
  access: requirement_spec_edit
166
  params: 
167
    action: RequirementSpec/list
168
    is_template: 1
169
- id: ar
170
  name: AR
171
  icon: ar
172
  order: 200
173
- parent: ar
174
  id: ar_add_requirement_spec
175
  name: Add Requirement Spec
176
  order: 100
177
  access: requirement_spec_edit
178
  params: 
179
    action: RequirementSpec/new
180
- parent: ar
181
  id: ar_add_quotation
182
  name: Add Quotation
183
  icon: quotation_add
184
  order: 200
185
  access: sales_quotation_edit
186
  module: oe.pl
187
  params: 
188
    action: add
189
    type: sales_quotation
190
- parent: ar
191
  id: ar_add_sales_order
192
  name: Add Sales Order
193
  icon: sales_order_add
194
  order: 300
195
  access: sales_order_edit
196
  module: oe.pl
197
  params: 
198
    action: add
199
    type: sales_order
200
- parent: ar
201
  id: ar_add_delivery_order
202
  name: Add Delivery Order
203
  icon: delivery_order_add
204
  order: 400
205
  access: sales_delivery_order_edit
206
  module: do.pl
207
  params: 
208
    action: add
209
    type: sales_delivery_order
210
- parent: ar
211
  id: ar_add_sales_invoice
212
  name: Add Sales Invoice
213
  icon: sales_invoice_add
214
  order: 500
215
  access: invoice_edit
216
  module: is.pl
217
  params: 
218
    action: add
219
    type: invoice
220
- parent: ar
221
  id: ar_add_credit_note
222
  name: Add Credit Note
223
  icon: credit_note_add
224
  order: 600
225
  access: invoice_edit
226
  module: is.pl
227
  params: 
228
    action: add
229
    type: credit_note
230
- parent: ar
231
  id: ar_add_dunning
232
  name: Add Dunning
233
  icon: dunning_add
234
  order: 700
235
  access: dunning_edit
236
  module: dn.pl
237
  params: 
238
    action: add
239
- parent: ar
240
  id: ar_add_letter
241
  name: Add Letter
242
  order: 800
243
  access: sales_letter_edit
244
  module: letter.pl
245
  params: 
246
    action: add
247
- parent: ar
248
  id: ar_reports
249
  name: Reports
250
  icon: ar_report
251
  order: 900
252
  module: menu.pl
253
  params: 
254
    action: acc_menu
255
- parent: ar_reports
256
  id: ar_reports_requirement_specs
257
  name: Requirement Specs
258
  order: 100
259
  access: requirement_spec_edit
260
  params: 
261
    action: RequirementSpec/list
262
- parent: ar_reports
263
  id: ar_reports_quotations
264
  name: Quotations
265
  icon: report_quotations
266
  order: 200
267
  access: sales_quotation_edit
268
  module: oe.pl
269
  params: 
270
    action: search
271
    type: sales_quotation
272
- parent: ar_reports
273
  id: ar_reports_sales_orders
274
  name: Sales Orders
275
  icon: report_sales_orders
276
  order: 300
277
  access: sales_order_edit
278
  module: oe.pl
279
  params: 
280
    action: search
281
    type: sales_order
282
- parent: ar_reports
283
  id: ar_reports_delivery_orders
284
  name: Delivery Orders
285
  icon: delivery_order_report
286
  order: 400
287
  access: sales_delivery_order_edit
288
  module: do.pl
289
  params: 
290
    action: search
291
    type: sales_delivery_order
292
- parent: ar_reports
293
  id: ar_reports_invoices_credit_notes_ar_transactions
294
  name: Invoices, Credit Notes & AR Transactions
295
  icon: invoices_report
296
  order: 500
297
  access: invoice_edit
298
  module: ar.pl
299
  params: 
300
    action: search
301
    nextsub: ar_transactions
302
- parent: ar_reports
303
  id: ar_reports_sales_report
304
  name: Sales Report
305
  order: 600
306
  access: invoice_edit
307
  module: vk.pl
308
  params: 
309
    action: search_invoice
310
    nextsub: invoice_transactions
311
- parent: ar_reports
312
  id: ar_reports_dunnings
313
  name: Dunnings
314
  icon: dunnings_report
315
  order: 700
316
  access: dunning_edit
317
  module: dn.pl
318
  params: 
319
    action: search
320
- parent: ar_reports
321
  id: ar_reports_delivery_plan
322
  name: Delivery Plan
323
  order: 800
324
  access: delivery_plan
325
  params: 
326
    action: DeliveryPlan/list
327
    vc: customer
328
    mode: delivery_plan
329
- parent: ar_reports
330
  id: ar_reports_delivery_value_report
331
  name: Delivery Value Report
332
  order: 900
333
  access: delivery_value_report
334
  params: 
335
    action: DeliveryPlan/list
336
    mode: delivery_value_report
337
    vc: customer
338
- parent: ar_reports
339
  id: ar_reports_financial_controlling
340
  name: Financial Controlling
341
  order: 1000
342
  access: sales_order_edit
343
  params: 
344
    action: FinancialControllingReport/list
345
- parent: ar_reports
346
  id: ar_reports_letters
347
  name: Letters
348
  order: 1100
349
  access: sales_letter_report
350
  module: letter.pl
351
  params: 
352
    action: search
353
- id: ap
354
  name: AP
355
  icon: ap
356
  order: 300
357
- parent: ap
358
  id: ap_add_rfq
359
  name: Add RFQ
360
  icon: rfq_add
361
  order: 100
362
  access: request_quotation_edit
363
  module: oe.pl
364
  params: 
365
    action: add
366
    type: request_quotation
367
- parent: ap
368
  id: ap_add_purchase_order
369
  name: Add Purchase Order
370
  icon: purchase_order_add
371
  order: 200
372
  access: purchase_order_edit
373
  module: oe.pl
374
  params: 
375
    action: add
376
    type: purchase_order
377
- parent: ap
378
  id: ap_add_delivery_note
379
  name: Add Delivery Note
380
  order: 300
381
  access: client/allow_new_purchase_delivery_order & purchase_delivery_order_edit
382
  module: do.pl
383
  params: 
384
    action: add
385
    type: purchase_delivery_order
386
- parent: ap
387
  id: ap_add_vendor_invoice
388
  name: Add Vendor Invoice
389
  order: 400
390
  access: client/allow_new_purchase_invoice & vendor_invoice_edit
391
  module: ir.pl
392
  params: 
393
    action: add
394
    type: invoice
395
- parent: ap
396
  id: ap_reports
397
  name: Reports
398
  icon: ap_report
399
  order: 500
400
  module: menu.pl
401
  params: 
402
    action: acc_menu
403
- parent: ap_reports
404
  id: ap_reports_rfqs
405
  name: RFQs
406
  icon: rfq_report
407
  order: 100
408
  access: request_quotation_edit
409
  module: oe.pl
410
  params: 
411
    action: search
412
    type: request_quotation
413
- parent: ap_reports
414
  id: ap_reports_purchase_orders
415
  name: Purchase Orders
416
  icon: purchase_order_report
417
  order: 200
418
  access: purchase_order_edit
419
  module: oe.pl
420
  params: 
421
    action: search
422
    type: purchase_order
423
- parent: ap_reports
424
  id: ap_reports_delivery_orders
425
  name: Delivery Orders
426
  order: 300
427
  access: purchase_delivery_order_edit
428
  module: do.pl
429
  params: 
430
    action: search
431
    type: purchase_delivery_order
432
- parent: ap_reports
433
  id: ap_reports_vendor_invoices_ap_transactions
434
  name: Vendor Invoices & AP Transactions
435
  order: 400
436
  access: vendor_invoice_edit
437
  module: ap.pl
438
  params: 
439
    action: search
440
    nextsub: ap_transactions
441
- parent: ap_reports
442
  id: ap_reports_delivery_plan
443
  name: Delivery Plan
444
  order: 500
445
  access: delivery_plan
446
  params: 
447
    action: DeliveryPlan/list
448
    mode: delivery_plan
449
    vc: vendor
450
- parent: ap_reports
451
  id: ap_reports_delivery_value_report
452
  name: Delivery Value Report
453
  order: 600
454
  access: delivery_value_report
455
  params: 
456
    action: DeliveryPlan/list
457
    vc: vendor
458
    mode: delivery_value_report
459
- id: warehouse
460
  name: Warehouse
461
  icon: warehouse
462
  order: 400
463
- parent: warehouse
464
  id: warehouse_stock
465
  name: Stock
466
  order: 100
467
  access: warehouse_management
468
  params: 
469
    action: Inventory/stock_in
470
- parent: warehouse
471
  id: warehouse_produce_assembly
472
  name: Produce Assembly
473
  icon: assembly_produce
474
  order: 200
475
  access: warehouse_management
476
  module: wh.pl
477
  params: 
478
    action: transfer_warehouse_selection
479
    trans_type: assembly
480
- parent: warehouse
481
  id: warehouse_transfer
482
  name: Transfer
483
  order: 300
484
  access: warehouse_management
485
  module: wh.pl
486
  params: 
487
    action: transfer_warehouse_selection
488
    trans_type: transfer
489
- parent: warehouse
490
  id: warehouse_removal
491
  name: Removal
492
  order: 400
493
  access: warehouse_management
494
  module: wh.pl
495
  params: 
496
    action: transfer_warehouse_selection
497
    trans_type: removal
498
- parent: warehouse
499
  id: warehouse_reports
500
  name: Reports
501
  order: 500
502
  module: menu.pl
503
  params: 
504
    action: acc_menu
505
- parent: warehouse_reports
506
  id: warehouse_reports_warehouse_content
507
  name: Warehouse content
508
  order: 100
509
  access: warehouse_contents | warehouse_management
510
  module: wh.pl
511
  params: 
512
    action: report
513
- parent: warehouse_reports
514
  id: warehouse_reports_whjournal
515
  name: WHJournal
516
  order: 200
517
  access: warehouse_management
518
  module: wh.pl
519
  params: 
520
    action: journal
521
- id: general_ledger
522
  name: General Ledger
523
  icon: gl
524
  order: 500
525
- parent: general_ledger
526
  id: general_ledger_add_transaction
527
  name: Add Transaction
528
  icon: transaction_add
529
  order: 100
530
  access: general_ledger
531
  module: gl.pl
532
  params: 
533
    action: add
534
- parent: general_ledger
535
  id: general_ledger_add_ar_transaction
536
  name: Add AR Transaction
537
  icon: ar_transaction_add
538
  order: 200
539
  access: general_ledger
540
  module: ar.pl
541
  params: 
542
    action: add
543
- parent: general_ledger
544
  id: general_ledger_add_ap_transaction
545
  name: Add AP Transaction
546
  icon: ap_transaction_add
547
  order: 300
548
  access: general_ledger
549
  module: ap.pl
550
  params: 
551
    action: add
552
- parent: general_ledger
553
  id: general_ledger_datev_export_assistent
554
  name: DATEV - Export Assistent
555
  icon: datev
556
  order: 400
557
  access: datev_export
558
  module: datev.pl
559
  params: 
560
    action: export
561
- parent: general_ledger
562
  id: general_ledger_reports
563
  name: Reports
564
  icon: gl_report
565
  order: 500
566
  module: menu.pl
567
  params: 
568
    action: acc_menu
569
- parent: general_ledger_reports
570
  id: general_ledger_reports_ar_aging
571
  name: AR Aging
572
  icon: ar_aging
573
  order: 100
574
  access: general_ledger
575
  module: rp.pl
576
  params: 
577
    action: report
578
    report: ar_aging
579
- parent: general_ledger_reports
580
  id: general_ledger_reports_ap_aging
581
  name: AP Aging
582
  icon: ap_aging
583
  order: 200
584
  access: general_ledger
585
  module: rp.pl
586
  params: 
587
    action: report
588
    report: ap_aging
589
- parent: general_ledger_reports
590
  id: general_ledger_reports_journal
591
  name: Journal
592
  icon: journal
593
  order: 300
594
  access: general_ledger
595
  module: gl.pl
596
  params: 
597
    action: search
598
- id: cash
599
  name: Cash
600
  icon: cash
601
  order: 600
602
- parent: cash
603
  id: cash_receipt
604
  name: Receipt
605
  icon: receipt
606
  order: 100
607
  access: cash
608
  module: cp.pl
609
  params: 
610
    action: payment
611
    vc: customer
612
    type: receipt
613
- parent: cash
614
  id: cash_payment
615
  name: Payment
616
  icon: payment
617
  order: 200
618
  access: cash
619
  module: cp.pl
620
  params: 
621
    action: payment
622
    vc: vendor
623
    type: check
624
- parent: cash
625
  id: cash_bank_collection_via_sepa
626
  name: Bank collection via SEPA
627
  order: 300
628
  access: cash
629
  module: sepa.pl
630
  params: 
631
    action: bank_transfer_add
632
    vc: customer
633
- parent: cash
634
  id: cash_bank_transfer_via_sepa
635
  name: Bank transfer via SEPA
636
  order: 400
637
  access: cash
638
  module: sepa.pl
639
  params: 
640
    action: bank_transfer_add
641
    vc: vendor
642
- parent: cash
643
  id: cash_bank_import
644
  name: Bank Import
645
  order: 500
646
  module: menu.pl
647
  params: 
648
    action: acc_menu
649
- parent: cash_bank_import
650
  id: cash_bank_import_csv
651
  name: CSV
652
  order: 100
653
  access: bank_transaction
654
  params: 
655
    action: CsvImport/new
656
    profile.type: bank_transactions
657
- parent: cash_bank_import
658
  id: cash_bank_import_mt940
659
  name: MT940
660
  order: 200
661
  access: bank_transaction
662
  params: 
663
    action: BankImport/upload_mt940
664
- parent: cash
665
  id: cash_bank_transactions_mt940
666
  name: Bank transactions MT940
667
  order: 600
668
  access: bank_transaction
669
  params: 
670
    action: BankTransaction/search
671
- parent: cash
672
  id: cash_reconciliation_with_bank
673
  name: Reconciliation with bank
674
  order: 700
675
  access: bank_transaction
676
  params: 
677
    action: Reconciliation/search
678
    next_sub: Reconciliation/reconciliation
679
- parent: cash
680
  id: cash_reconciliation
681
  name: Reconciliation
682
  icon: reconcilliation
683
  order: 800
684
  access: cash
685
  module: rc.pl
686
  params: 
687
    action: reconciliation
688
- parent: cash
689
  id: cash_reports
690
  name: Reports
691
  icon: cash_report
692
  order: 900
693
  module: menu.pl
694
  params: 
695
    action: acc_menu
696
- parent: cash_reports
697
  id: cash_reports_receipts
698
  name: Receipts
699
  icon: receipt_report
700
  order: 100
701
  access: cash
702
  module: rp.pl
703
  params: 
704
    action: report
705
    report: receipts
706
- parent: cash_reports
707
  id: cash_reports_payments
708
  name: Payments
709
  icon: payment_report
710
  order: 200
711
  access: cash
712
  module: rp.pl
... Dieser Diff wurde abgeschnitten, weil er die maximale Anzahl anzuzeigender Zeilen überschreitet.

Auch abrufbar als: Unified diff