From: Sven Schöling Date: Wed, 15 Jul 2015 15:54:07 +0000 (+0200) Subject: Menüstruktur auf YAML geändert X-Git-Tag: release-3.3.0beta~31^2~24 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=b251cc22f355941217493073e124ba3878d5530f;p=kivitendo-erp.git Menüstruktur auf YAML geändert --- diff --git a/SL/Layout/Admin.pm b/SL/Layout/Admin.pm index e10ed0341..03832b555 100644 --- a/SL/Layout/Admin.pm +++ b/SL/Layout/Admin.pm @@ -11,7 +11,7 @@ use SL::Layout::CssMenu; sub init_sub_layouts { [ SL::Layout::None->new, - SL::Layout::CssMenu->new(menu => Menu->new('menus/admin.ini')), + SL::Layout::CssMenu->new(menu => SL::Menu->new('admin')), ] } diff --git a/SL/Layout/Base.pm b/SL/Layout/Base.pm index a8bf139a7..e39502f1f 100644 --- a/SL/Layout/Base.pm +++ b/SL/Layout/Base.pm @@ -29,9 +29,7 @@ sub new { } sub init_menu { - my @menu_files = qw(menus/erp.ini); - unshift @menu_files, 'menus/crm.ini' if $::instance_conf->crm_installed; - Menu->new(@menu_files); + SL::Menu->new('user'); } sub init_auto_reload_resources_param { diff --git a/SL/Layout/CssMenu.pm b/SL/Layout/CssMenu.pm index c26fad7bb..d9399083d 100644 --- a/SL/Layout/CssMenu.pm +++ b/SL/Layout/CssMenu.pm @@ -3,114 +3,12 @@ package SL::Layout::CssMenu; use strict; use parent qw(SL::Layout::Base); -use URI; - -sub print_menu { - my ($self, $parent, $depth) = @_; - - my $html; - - die if ($depth * 1 > 5); - - my @menuorder; - my $menu = $self->menu; - - @menuorder = $menu->access_control(\%::myconfig, $parent); - - $parent .= "--" if ($parent); - - foreach my $item (@menuorder) { - substr($item, 0, length($parent)) = ""; - next if (($item eq "") || ($item =~ /--/)); - - my $menu_item = $menu->{"${parent}${item}"}; - my $menu_title = $::locale->text($item); - my $menu_text = $menu_title; - - if ($menu_item->{"submenu"} || !defined($menu_item->{"module"}) && !defined($menu_item->{href})) { - - my $h = $self->print_menu("${parent}${item}", $depth * 1 + 1)."\n"; - if (!$parent) { - $html .= qq|\n|; - } else { - $html .= qq|
  • ${menu_text}
  • \n|; - } - } else { - if ($self->{sub_class} && $depth > 1) { - $html .= qq|
  • |; - } else { - $html .= qq|
  • |; - } - $html .= $self->menuitem_v3("${parent}$item", { "title" => $menu_title }); - $html .= qq|${menu_text}
  • \n|; - } - } - - return $html; -} - -sub menuitem_v3 { - $main::lxdebug->enter_sub(); - - my ($self, $item, $other) = @_; - my $menuitem = $self->menu->{$item}; - - my $action = "section_menu"; - my $module; - - if ($menuitem->{module}) { - $module = $menuitem->{module}; - } - if ($menuitem->{action}) { - $action = $menuitem->{action}; - } - - my $level = $::form->escape($item); - - my @vars; - my $target = $menuitem->{target} ? qq| target="| . $::form->escape($menuitem->{target}) . '"' : ''; - my $str = qq|'; - } - - $str .= qq|$module?action=| . $::form->escape($action); - - map { delete $menuitem->{$_} } qw(module action target href); - - # add other params - foreach my $key (keys %{ $menuitem }) { - $str .= "&" . $::form->escape($key, 1) . "="; - my ($value, $conf) = split(/=/, $menuitem->{$key}, 2); - $value = $::myconfig{$value} . "/$conf" if ($conf); - $str .= $::form->escape($value, 1); - } - - $str .= '"'; - - if ($other) { - foreach my $key (keys(%{$other})) { - $str .= qq| ${key}="| . $::form->quote($other->{$key}) . qq|"|; - } - } - - $str .= ">"; - - $main::lxdebug->leave_sub(); - - return $str; -} - sub use_stylesheet { qw(icons16.css frame_header/header.css), } sub pre_content { - $_[0]->presenter->render('menu/menuv3', - menu => $_[0]->print_menu, - ); + $_[0]->presenter->render('menu/menuv3', menu => $_[0]->menu); } 1; diff --git a/SL/Layout/Javascript.pm b/SL/Layout/Javascript.pm index 26539de1c..366e0d7c9 100644 --- a/SL/Layout/Javascript.pm +++ b/SL/Layout/Javascript.pm @@ -21,9 +21,29 @@ sub use_javascript { $self->SUPER::use_javascript(@_); } +sub javascripts_inline { + $_[0]->SUPER::javascripts_inline, +<<'EOJS' + DHTMLSuite.createStandardObjects(); + DHTMLSuite.configObj.setImagePath('image/dhtmlsuite/'); + var menu_model = new DHTMLSuite.menuModel(); + menu_model.addItemsFromMarkup('main_menu_model'); + menu_model.init(); + var menu_bar = new DHTMLSuite.menuBar(); + menu_bar.addMenuItems(menu_model); + menu_bar.setTarget('main_menu_div'); + menu_bar.init(); +EOJS +} + sub pre_content { $_[0]->SUPER::pre_content . - &display + $_[0]->presenter->render("menu/menunew", + force_ul_width => 1, + menu => $_[0]->menu, + icon_path => sub { my $img = "image/icons/16x16/$_[0].png"; -f $img ? $img : () }, + max_width => sub { 10 * max map { length $::locale->text($_->{name}) } @{ $_[0]{children} || [] } }, + ); } sub start_content { @@ -45,83 +65,4 @@ sub stylesheets { $_[0]->SUPER::stylesheets; } -sub display { - my ($self) = @_; - - $self->presenter->render("menu/menunew", - force_ul_width => 1, - menu_items => $self->acc_menu, - ); -} - -sub acc_menu { - my ($self) = @_; - - my $menu = $self->menu; - - my $all_items = []; - $self->create_menu($menu, $all_items); - - my $item = { 'subitems' => $all_items }; - calculate_width($item); - - return $all_items; -} - -sub calculate_width { - my $item = shift; - - $item->{max_width} = max map { length $_->{title} } @{ $item->{subitems} }; - - foreach my $subitem (@{ $item->{subitems} }) { - calculate_width($subitem) if ($subitem->{subitems}); - } -} - -sub create_menu { - my ($self, $menu, $all_items, $parent, $depth) = @_; - my $html; - - my $form = $main::form; - my %myconfig = %main::myconfig; - - $depth ||= 0; - - die if ($depth * 1 > 5); - - my @menuorder = $menu->access_control(\%myconfig, $parent); - $parent .= "--" if ($parent); - $parent ||= ''; - - foreach my $name (@menuorder) { - substr($name, 0, length($parent), ""); - next if (($name eq "") || ($name =~ /--/)); - - my $menu_item = $menu->{"${parent}${name}"}; - my $item = { 'title' => $::locale->text($name) }; - push @{ $all_items }, $item; - - if ($menu_item->{submenu} || (!defined($menu_item->{module}) && !defined($menu_item->{href}))) { - $item->{subitems} = []; - $item->{image} = _icon_path($menu_item->{ICON}); - $self->create_menu($menu, $item->{subitems}, "${parent}${name}", $depth * 1 + 1); - - } else { - $item->{image} = _icon_path("${parent}${name}.png"); - $menu->menuitem_new("${parent}${name}", $item); - } - } -} - -sub _icon_path { - my ($label, $size) = @_; - - $size ||= 16; - - my $img = "image/icons/${size}x${size}/$label.png"; - - return unless -f $img; - return $img; -} - 1; diff --git a/SL/Layout/MenuLeft.pm b/SL/Layout/MenuLeft.pm index 4c1901cc8..17ea51a97 100644 --- a/SL/Layout/MenuLeft.pm +++ b/SL/Layout/MenuLeft.pm @@ -40,46 +40,28 @@ sub end_content { sub section_menu { my ($menu) = @_; - my @menuorder = @{ $menu->{ORDER} }; my @items; my @id_stack = (-1); - for my $item (@menuorder) { - my $menuitem = $menu->{$item}; - my $olabel = apply { s/.*--// } $item; - my $ml = apply { s/--.*// } $item; - my $icon_class = apply { $_ = lc $_; s/[^a-z0-9_-]/-/g } $menuitem->{ICON}; - my $level = (0 + $item =~ s/--/--/g); - my $spacer = "s" . $level; + for my $node ($menu->tree_walk) { + my $level = $node->{level}; # do id stack push @id_stack, -1 if $level > $#id_stack; pop @id_stack while $level < $#id_stack; $id_stack[-1]++; - my $label = $::locale->text($olabel); + my $label = $::locale->text($node->{name}); + my $href = $menu->href_for_node($node); - $menuitem->{module} ||= $::form->{script}; - $menuitem->{action} ||= "section_menu"; - $menuitem->{href} ||= "$menuitem->{module}?action=$menuitem->{action}"; + my @common_args = ($label, "s" . $level, join '_', @id_stack); - # add other params - foreach my $key (keys %$menuitem) { - next if $key =~ /target|module|action|href|ICON/; - $menuitem->{href} .= "&" . $::form->escape($key, 1) . "="; - my ($value, $conf) = split(/=/, $menuitem->{$key}, 2); - $value = $::myconfig{$value} . "/$conf" if ($conf); - $menuitem->{href} .= $::form->escape($value, 1); - } - - my @common_args = ($label, $spacer, join '_', @id_stack); - - if ($spacer eq 's0') { # toplevel - push @items, [ @common_args, "icon24 $icon_class", 'm' ]; - } elsif ($menuitem->{submenu}) { + if (!$node->{parent}) { # toplevel + push @items, [ @common_args, "icon24 $node->{icon}", 'm' ]; + } elsif ($node->{children}) { push @items, [ @common_args, "icon16 submenu", 'sm' ]; - } elsif ($menuitem->{module}) { - push @items, [ @common_args, "icon16 $icon_class", 'i', $menuitem->{href}, $menuitem->{target} ]; + } else { + push @items, [ @common_args, "icon16 $node->{icon}", 'i', $href, $node->{target} ]; } } diff --git a/SL/Menu.pm b/SL/Menu.pm index 873701616..534a05e6e 100644 --- a/SL/Menu.pm +++ b/SL/Menu.pm @@ -1,126 +1,141 @@ -#===================================================================== -# LX-Office ERP -# Copyright (C) 2004 -# Based on SQL-Ledger Version 2.1.9 -# Web http://www.lx-office.org -# -#===================================================================== -# SQL-Ledger Accounting -# Copyright (C) 2001 -# -# Author: Dieter Simader -# Email: dsimader@sql-ledger.org -# Web: http://www.sql-ledger.org -# -# Contributors: -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -#===================================================================== -# -# routines for menu items -# -#===================================================================== - -package Menu; +package SL::Menu; use strict; use SL::Auth; -use SL::Inifile; - -our @ISA = qw(Inifile); - +use YAML::XS (); +use File::Spec; +use SL::MoreCommon qw(uri_encode); sub new { - $main::lxdebug->enter_sub(); + my ($package, $domain) = @_; - my ($package, @menufiles) = @_; + my $path = File::Spec->catdir('menus', $domain); - my $self = $package->SUPER::new($menufiles[0]); + opendir my $dir, $path or die "can't open $path: $!"; + my @files = sort grep -f "$path/$_", readdir $dir; + close $dir; - for (@menufiles[1..$#menufiles]) { - my $inifile = Inifile->new($_); - push @{ $self->{ORDER} }, @{ delete $inifile->{ORDER} }; - $self->{$_} = $inifile->{$_} for keys %$inifile; + my $nodes = []; + my $nodes_by_id = {}; + for my $file (@files) { + my $data = YAML::XS::LoadFile(File::Spec->catfile($path, $file)); + _merge($nodes, $nodes_by_id, $data); } - $self->set_access; - $main::lxdebug->leave_sub(); + my $self = bless { + nodes => $nodes, + by_id => $nodes_by_id, + }, $package; + + $self->build_tree; + $self->set_access; return $self; } -sub menuitem_new { - $main::lxdebug->enter_sub(LXDebug::DEBUG2()); +sub _merge { + my ($nodes, $by_id, $data) = @_; - my ($self, $name, $item) = @_; + die 'not an array ref' unless $data && 'ARRAY' eq ref $data; # TODO check this sooner, to get better diag to user - my $module = $self->{$name}->{module} || $::form->{script}; - my $action = $self->{$name}->{action}; + for my $node (@$data) { + my $id = $node->{id}; - $item->{target} = $self->{$name}->{target} || "main_window"; - $item->{href} = $self->{$name}->{href} || "${module}?action=" . $::form->escape($action); + my $merge_to = $by_id->{$id}; - my @vars = qw(module target href); - push @vars, 'action' unless ($self->{$name}->{href}); + if (!$merge_to) { + push @$nodes, $node; + $by_id->{$id} = $node; + next; + } - map { delete $self->{$name}{$_} } @vars; + # TODO make this a real recursive merge + # TODO add support for arrays + + # merge keys except params + for my $key (keys %$node) { + if (ref $node->{$key}) { + if ('HASH' eq ref $node->{$key}) { + $merge_to->{$key} = {} if !exists $merge_to->{$key} || 'HASH' ne ref $merge_to->{$key}; + for (keys %{ $node->{params} }) { + $merge_to->{$key}{$_} = $node->{params}{$_}; + } + } else { + die "unsupported structure @{[ ref $node->{$key} ]}"; + } + } else { + $merge_to->{$key} = $node->{$key}; + } + } + } +} - # add other params - foreach my $key (keys %{ $self->{$name} }) { - my ($value, $conf) = split(m/=/, $self->{$name}->{$key}, 2); - $value = $::myconfig->{$value} . "/$conf" if ($conf); - $item->{href} .= "&" . $::form->escape($key) . "=" . $::form->escape($value); +sub build_tree { + my ($self) = @_; + + # first, some sanity check. are all parents valid ids or empty? + for my $node ($self->nodes) { + next if !exists $node->{parent} || !$node->{parent} || $self->{by_id}->{$node->{id}}; + die "menu: node $node->{id} has non-existant parent $node->{parent}"; } - $main::lxdebug->leave_sub(LXDebug::DEBUG2()); -} + my %by_parent; + # order them by parent + for my $node ($self->nodes) { + push @{ $by_parent{ $node->{parent} } //= [] }, $node; + } -sub access_control { - $main::lxdebug->enter_sub(2); + my $tree = { }; + $self->{by_id}{''} = $tree; - my ($self, $myconfig, $menulevel) = @_; - my @menu = (); + for (keys %by_parent) { + my $parent = $self->{by_id}{$_}; + $parent->{children} = [ sort { $a->{order} <=> $b->{order} } @{ $by_parent{$_} } ]; + } + + _set_level_rec($tree->{children}, 0); + + $self->{tree} = $tree->{children}; +} + +sub _set_level_rec { + my ($ary_ref, $level) = @_; - if (!$menulevel) { - @menu = grep { !/--/ } @{ $self->{ORDER} }; - } else { - @menu = grep { /^${menulevel}--/ } @{ $self->{ORDER} }; + for (@$ary_ref) { + $_->{level} = $level; + _set_level_rec($_->{children}, $level + 1) if $_->{children}; } +} - $main::lxdebug->leave_sub(2); +sub nodes { + @{ $_[0]{nodes} } +} + +sub tree_walk { + my ($self, $all) = @_; - return @menu; + _tree_walk_rec($self->{tree}, $all); } -sub parse_access_string { - my $self = shift; - my $key = shift; - my $access = shift; +sub _tree_walk_rec { + my ($ary_ref, $all) = @_; + map { $_->{children} ? ($_, _tree_walk_rec($_->{children}, $all)) : ($_) } grep { $all || $_->{visible} } @$ary_ref; +} - my $form = $main::form; - my $auth = $main::auth; - my $myconfig = \%main::myconfig; +sub parse_access_string { + my ($self, $node) = @_; my @stack; my $cur_ary = []; push @stack, $cur_ary; - while ($access =~ m/^([a-z_]+|\||\&|\(|\)|\s+)/) { + my $access = $node->{access}; + + while ($access =~ m/^([a-z_\/]+|\||\&|\(|\)|\s+)/) { my $token = $1; substr($access, 0, length($1)) = ""; @@ -135,7 +150,7 @@ sub parse_access_string { } elsif ($token eq ")") { pop @stack; if (!@stack) { - $form->error("Error in menu.ini for entry ${key}: missing '('"); + die "Error in menu.ini for entry $node->{id}: missing '('"; } $cur_ary = $stack[-1]; @@ -143,77 +158,62 @@ sub parse_access_string { push @{$cur_ary}, $token; } else { - push @{$cur_ary}, $auth->check_right($::myconfig{login}, $token, 1); + if ($token =~ m{^ client / (.*) }x) { + push @{$cur_ary}, $self->parse_instance_conf_string($1); + } else { + push @{$cur_ary}, $::auth->check_right($::myconfig{login}, $token, 1); + } } } if ($access) { - $form->error("Error in menu.ini for entry ${key}: unrecognized token at the start of '$access'\n"); + die "Error in menu.ini for entry $node->{id}: unrecognized token at the start of '$access'\n"; } if (1 < scalar @stack) { - $main::form->error("Error in menu.ini for entry ${key}: Missing ')'\n"); + die "Error in menu.ini for entry $node->{id}: Missing ')'\n"; } return SL::Auth::evaluate_rights_ary($stack[0]); } -sub parse_instance_conf_string { - my ($self, $setting) = @_; - return $::instance_conf->data->{$setting}; -} - -sub set_access { - my $self = shift; - - my $key; - - foreach $key (@{ $self->{ORDER} }) { - my $entry = $self->{$key}; - - $entry->{GRANTED} = $entry->{ACCESS} ? $self->parse_access_string($key, $entry->{ACCESS}) : 1; - $entry->{GRANTED} &&= $self->parse_instance_conf_string($entry->{INSTANCE_CONF}) if $entry->{INSTANCE_CONF}; - $entry->{IS_MENU} = $entry->{submenu} || ($key !~ m/--/); - $entry->{NUM_VISIBLE_CHILDREN} = 0; - - if ($key =~ m/--/) { - my $parent = $key; - substr($parent, rindex($parent, '--')) = ''; - $entry->{GRANTED} &&= $self->{$parent}->{GRANTED}; - } - - $entry->{VISIBLE} = $entry->{GRANTED}; - } - - foreach $key (reverse @{ $self->{ORDER} }) { - my $entry = $self->{$key}; +sub href_for_node { + my ($self, $node) = @_; - if ($entry->{IS_MENU}) { - $entry->{VISIBLE} &&= $entry->{NUM_VISIBLE_CHILDREN} > 0; - } + return undef if !$node->{href} && !$node->{module} && !$node->{params}; - next if (($key !~ m/--/) || !$entry->{VISIBLE}); + my $href = $node->{href} || $node->{module} || 'controller.pl'; + my @tokens; - my $parent = $key; - substr($parent, rindex($parent, '--')) = ''; - $self->{$parent}->{NUM_VISIBLE_CHILDREN}++; + while (my ($key, $value) = each %{ $node->{params} }) { + push @tokens, uri_encode($key, 1) . "=" . uri_encode($value, 1); } -# $self->dump_visible(); + return join '?', $href, grep $_, join '&', @tokens; +} - $self->{ORDER} = [ grep { $self->{$_}->{VISIBLE} } @{ $self->{ORDER} } ]; +sub name_for_node { + $::locale->text($_[1]{name}) +} - { no strict 'refs'; - # ToDO: fix this. nuke and pave algorithm without type checking screams for problems. - map { delete @{$self->{$_}}{qw(GRANTED IS_MENU NUM_VISIBLE_CHILDREN VISIBLE ACCESS)} if ($_ ne 'ORDER') } keys %{ $self }; - } +sub parse_instance_conf_string { + my ($self, $setting) = @_; + return $::instance_conf->data->{$setting}; } -sub dump_visible { - my $self = shift; - foreach my $key (@{ $self->{ORDER} }) { - my $entry = $self->{$key}; - $main::lxdebug->message(0, "$entry->{GRANTED} $entry->{VISIBLE} $entry->{NUM_VISIBLE_CHILDREN} $key"); +sub set_access { + my ($self) = @_; + # 1. evaluate access for all + # 2. if a menu has no visible children, its not visible either + + for my $node (reverse $self->tree_walk("all")) { + $node->{visible} = $node->{access} ? $self->parse_access_string($node) + : !$node->{children} ? 1 + : $node->{visible_children} ? 1 + : 0; + if ($node->{visible} && $node->{parent}) { + $self->{by_id}{ $node->{parent} }{visible_children} = 1; + } } } diff --git a/menus/admin/00-admin.yaml b/menus/admin/00-admin.yaml new file mode 100644 index 000000000..86850271c --- /dev/null +++ b/menus/admin/00-admin.yaml @@ -0,0 +1,92 @@ +--- +- id: users_clients_and_user_groups + name: Users, Clients and User Groups + order: 100 +- parent: users_clients_and_user_groups + id: users_clients_and_user_groups_list_users_clients_and_user_groups + name: List Users, Clients and User Groups + order: 100 + params: + action: Admin/show +- parent: users_clients_and_user_groups + id: users_clients_and_user_groups_add_user + name: Add User + order: 200 + params: + action: Admin/new_user +- parent: users_clients_and_user_groups + id: users_clients_and_user_groups_add_client + name: Add Client + order: 300 + params: + action: Admin/new_client +- parent: users_clients_and_user_groups + id: users_clients_and_user_groups_add_user_group + name: Add User Group + order: 400 + params: + action: Admin/new_group +- id: database_management + name: Database Management + order: 200 +- parent: database_management + id: database_management_create_dataset + name: Create Dataset + order: 100 + params: + action: Admin/create_dataset_login +- parent: database_management + id: database_management_delete_dataset + name: Delete Dataset + order: 200 + params: + action: Admin/delete_dataset_login +- id: printer_management + name: Printer Management + order: 300 +- parent: printer_management + id: printer_management_list_printers + name: List Printers + order: 100 + params: + action: Admin/list_printers +- parent: printer_management + id: printer_management_add_printer + name: Add Printer + order: 200 + params: + action: Admin/new_printer +- id: system + name: System + icon: system + order: 400 +- parent: system + id: system_lock_and_unlock_installation + name: Lock and unlock installation + order: 100 + params: + action: Admin/show_lock +- parent: system + id: system_documentation_in_german_ + name: Documentation (in German) + order: 200 + href: doc/kivitendo-Dokumentation.pdf + target: _blank +- parent: system + id: system_kivitendo_website_external_ + name: kivitendo website (external) + order: 300 + href: http://www.kivitendo.de/ + target: _blank +- parent: system + id: system_to_user_login + name: To user login + order: 400 + params: + action: LoginScreen/user_login +- parent: system + id: system_logout + name: Logout + order: 500 + params: + action: Admin/logout diff --git a/menus/user/00-erp.yaml b/menus/user/00-erp.yaml new file mode 100644 index 000000000..1a44d0feb --- /dev/null +++ b/menus/user/00-erp.yaml @@ -0,0 +1,1388 @@ +--- +- id: master_data + name: Master Data + icon: master_data + order: 100 +- parent: master_data + id: master_data_add_customer + name: Add Customer + icon: customer_add + order: 100 + access: customer_vendor_edit + params: + action: CustomerVendor/add + db: customer +- parent: master_data + id: master_data_add_vendor + name: Add Vendor + icon: vendor_add + order: 200 + access: customer_vendor_edit + params: + action: CustomerVendor/add + db: vendor +- parent: master_data + id: master_data_add_part + name: Add Part + icon: part_add + order: 300 + access: part_service_assembly_edit + module: ic.pl + params: + action: add + item: part +- parent: master_data + id: master_data_add_service + name: Add Service + icon: service_add + order: 400 + access: part_service_assembly_edit + module: ic.pl + params: + action: add + item: service +- parent: master_data + id: master_data_add_assembly + name: Add Assembly + icon: assembly_add + order: 500 + access: part_service_assembly_edit + module: ic.pl + params: + action: add + item: assembly +- parent: master_data + id: master_data_add_project + name: Add Project + icon: project_add + order: 600 + access: project_edit + params: + action: Project/new +- parent: master_data + id: master_data_add_requirement_spec_template + name: Add Requirement Spec Template + order: 700 + access: requirement_spec_edit + params: + action: RequirementSpec/new + is_template: 1 +- parent: master_data + id: master_data_update_prices + name: Update Prices + icon: prices_update + order: 800 + access: part_service_assembly_edit + module: ic.pl + params: + action: search_update_prices +- parent: master_data + id: master_data_price_rules + name: Price Rules + order: 900 + access: part_service_assembly_edit + params: + action: PriceRule/list + filter.obsolete: 0 +- parent: master_data + id: master_data_reports + name: Reports + icon: master_data_report + order: 1000 + module: menu.pl + params: + action: acc_menu +- parent: master_data_reports + id: master_data_reports_customers + name: Customers + icon: customer_report + order: 100 + access: customer_vendor_edit + params: + action: CustomerVendor/search + db: customer +- parent: master_data_reports + id: master_data_reports_vendors + name: Vendors + icon: vendor_report + order: 200 + access: customer_vendor_edit + params: + action: CustomerVendor/search + db: vendor +- parent: master_data_reports + id: master_data_reports_contacts + name: Contacts + order: 300 + access: customer_vendor_edit + params: + action: CustomerVendor/search_contact + db: customer +- parent: master_data_reports + id: master_data_reports_parts + name: Parts + icon: part_report + order: 400 + access: part_service_assembly_details + module: ic.pl + params: + action: search + searchitems: part +- parent: master_data_reports + id: master_data_reports_services + name: Services + icon: service_report + order: 500 + access: part_service_assembly_details + module: ic.pl + params: + action: search + searchitems: service +- parent: master_data_reports + id: master_data_reports_assemblies + name: Assemblies + icon: assembly_report + order: 600 + access: part_service_assembly_details + module: ic.pl + params: + action: search + searchitems: assembly +- parent: master_data_reports + id: master_data_reports_projects + name: Projects + icon: project_report + order: 700 + access: project_edit + params: + action: Project/list + filter.active: active + filter.valid: valid +- parent: master_data_reports + id: master_data_reports_requirement_spec_templates + name: Requirement Spec Templates + order: 800 + access: requirement_spec_edit + params: + action: RequirementSpec/list + is_template: 1 +- id: ar + name: AR + icon: ar + order: 200 +- parent: ar + id: ar_add_requirement_spec + name: Add Requirement Spec + order: 100 + access: requirement_spec_edit + params: + action: RequirementSpec/new +- parent: ar + id: ar_add_quotation + name: Add Quotation + icon: quotation_add + order: 200 + access: sales_quotation_edit + module: oe.pl + params: + action: add + type: sales_quotation +- parent: ar + id: ar_add_sales_order + name: Add Sales Order + icon: sales_order_add + order: 300 + access: sales_order_edit + module: oe.pl + params: + action: add + type: sales_order +- parent: ar + id: ar_add_delivery_order + name: Add Delivery Order + icon: delivery_order_add + order: 400 + access: sales_delivery_order_edit + module: do.pl + params: + action: add + type: sales_delivery_order +- parent: ar + id: ar_add_sales_invoice + name: Add Sales Invoice + icon: sales_invoice_add + order: 500 + access: invoice_edit + module: is.pl + params: + action: add + type: invoice +- parent: ar + id: ar_add_credit_note + name: Add Credit Note + icon: credit_note_add + order: 600 + access: invoice_edit + module: is.pl + params: + action: add + type: credit_note +- parent: ar + id: ar_add_dunning + name: Add Dunning + icon: dunning_add + order: 700 + access: dunning_edit + module: dn.pl + params: + action: add +- parent: ar + id: ar_add_letter + name: Add Letter + order: 800 + access: sales_letter_edit + module: letter.pl + params: + action: add +- parent: ar + id: ar_reports + name: Reports + icon: ar_report + order: 900 + module: menu.pl + params: + action: acc_menu +- parent: ar_reports + id: ar_reports_requirement_specs + name: Requirement Specs + order: 100 + access: requirement_spec_edit + params: + action: RequirementSpec/list +- parent: ar_reports + id: ar_reports_quotations + name: Quotations + icon: report_quotations + order: 200 + access: sales_quotation_edit + module: oe.pl + params: + action: search + type: sales_quotation +- parent: ar_reports + id: ar_reports_sales_orders + name: Sales Orders + icon: report_sales_orders + order: 300 + access: sales_order_edit + module: oe.pl + params: + action: search + type: sales_order +- parent: ar_reports + id: ar_reports_delivery_orders + name: Delivery Orders + icon: delivery_order_report + order: 400 + access: sales_delivery_order_edit + module: do.pl + params: + action: search + type: sales_delivery_order +- parent: ar_reports + id: ar_reports_invoices_credit_notes_ar_transactions + name: Invoices, Credit Notes & AR Transactions + icon: invoices_report + order: 500 + access: invoice_edit + module: ar.pl + params: + action: search + nextsub: ar_transactions +- parent: ar_reports + id: ar_reports_sales_report + name: Sales Report + order: 600 + access: invoice_edit + module: vk.pl + params: + action: search_invoice + nextsub: invoice_transactions +- parent: ar_reports + id: ar_reports_dunnings + name: Dunnings + icon: dunnings_report + order: 700 + access: dunning_edit + module: dn.pl + params: + action: search +- parent: ar_reports + id: ar_reports_delivery_plan + name: Delivery Plan + order: 800 + access: delivery_plan + params: + action: DeliveryPlan/list + vc: customer + mode: delivery_plan +- parent: ar_reports + id: ar_reports_delivery_value_report + name: Delivery Value Report + order: 900 + access: delivery_value_report + params: + action: DeliveryPlan/list + mode: delivery_value_report + vc: customer +- parent: ar_reports + id: ar_reports_financial_controlling + name: Financial Controlling + order: 1000 + access: sales_order_edit + params: + action: FinancialControllingReport/list +- parent: ar_reports + id: ar_reports_letters + name: Letters + order: 1100 + access: sales_letter_report + module: letter.pl + params: + action: search +- id: ap + name: AP + icon: ap + order: 300 +- parent: ap + id: ap_add_rfq + name: Add RFQ + icon: rfq_add + order: 100 + access: request_quotation_edit + module: oe.pl + params: + action: add + type: request_quotation +- parent: ap + id: ap_add_purchase_order + name: Add Purchase Order + icon: purchase_order_add + order: 200 + access: purchase_order_edit + module: oe.pl + params: + action: add + type: purchase_order +- parent: ap + id: ap_add_delivery_note + name: Add Delivery Note + order: 300 + access: client/allow_new_purchase_delivery_order & purchase_delivery_order_edit + module: do.pl + params: + action: add + type: purchase_delivery_order +- parent: ap + id: ap_add_vendor_invoice + name: Add Vendor Invoice + order: 400 + access: client/allow_new_purchase_invoice & vendor_invoice_edit + module: ir.pl + params: + action: add + type: invoice +- parent: ap + id: ap_reports + name: Reports + icon: ap_report + order: 500 + module: menu.pl + params: + action: acc_menu +- parent: ap_reports + id: ap_reports_rfqs + name: RFQs + icon: rfq_report + order: 100 + access: request_quotation_edit + module: oe.pl + params: + action: search + type: request_quotation +- parent: ap_reports + id: ap_reports_purchase_orders + name: Purchase Orders + icon: purchase_order_report + order: 200 + access: purchase_order_edit + module: oe.pl + params: + action: search + type: purchase_order +- parent: ap_reports + id: ap_reports_delivery_orders + name: Delivery Orders + order: 300 + access: purchase_delivery_order_edit + module: do.pl + params: + action: search + type: purchase_delivery_order +- parent: ap_reports + id: ap_reports_vendor_invoices_ap_transactions + name: Vendor Invoices & AP Transactions + order: 400 + access: vendor_invoice_edit + module: ap.pl + params: + action: search + nextsub: ap_transactions +- parent: ap_reports + id: ap_reports_delivery_plan + name: Delivery Plan + order: 500 + access: delivery_plan + params: + action: DeliveryPlan/list + mode: delivery_plan + vc: vendor +- parent: ap_reports + id: ap_reports_delivery_value_report + name: Delivery Value Report + order: 600 + access: delivery_value_report + params: + action: DeliveryPlan/list + vc: vendor + mode: delivery_value_report +- id: warehouse + name: Warehouse + icon: warehouse + order: 400 +- parent: warehouse + id: warehouse_stock + name: Stock + order: 100 + access: warehouse_management + params: + action: Inventory/stock_in +- parent: warehouse + id: warehouse_produce_assembly + name: Produce Assembly + icon: assembly_produce + order: 200 + access: warehouse_management + module: wh.pl + params: + action: transfer_warehouse_selection + trans_type: assembly +- parent: warehouse + id: warehouse_transfer + name: Transfer + order: 300 + access: warehouse_management + module: wh.pl + params: + action: transfer_warehouse_selection + trans_type: transfer +- parent: warehouse + id: warehouse_removal + name: Removal + order: 400 + access: warehouse_management + module: wh.pl + params: + action: transfer_warehouse_selection + trans_type: removal +- parent: warehouse + id: warehouse_reports + name: Reports + order: 500 + module: menu.pl + params: + action: acc_menu +- parent: warehouse_reports + id: warehouse_reports_warehouse_content + name: Warehouse content + order: 100 + access: warehouse_contents | warehouse_management + module: wh.pl + params: + action: report +- parent: warehouse_reports + id: warehouse_reports_whjournal + name: WHJournal + order: 200 + access: warehouse_management + module: wh.pl + params: + action: journal +- id: general_ledger + name: General Ledger + icon: gl + order: 500 +- parent: general_ledger + id: general_ledger_add_transaction + name: Add Transaction + icon: transaction_add + order: 100 + access: general_ledger + module: gl.pl + params: + action: add +- parent: general_ledger + id: general_ledger_add_ar_transaction + name: Add AR Transaction + icon: ar_transaction_add + order: 200 + access: general_ledger + module: ar.pl + params: + action: add +- parent: general_ledger + id: general_ledger_add_ap_transaction + name: Add AP Transaction + icon: ap_transaction_add + order: 300 + access: general_ledger + module: ap.pl + params: + action: add +- parent: general_ledger + id: general_ledger_datev_export_assistent + name: DATEV - Export Assistent + icon: datev + order: 400 + access: datev_export + module: datev.pl + params: + action: export +- parent: general_ledger + id: general_ledger_reports + name: Reports + icon: gl_report + order: 500 + module: menu.pl + params: + action: acc_menu +- parent: general_ledger_reports + id: general_ledger_reports_ar_aging + name: AR Aging + icon: ar_aging + order: 100 + access: general_ledger + module: rp.pl + params: + action: report + report: ar_aging +- parent: general_ledger_reports + id: general_ledger_reports_ap_aging + name: AP Aging + icon: ap_aging + order: 200 + access: general_ledger + module: rp.pl + params: + action: report + report: ap_aging +- parent: general_ledger_reports + id: general_ledger_reports_journal + name: Journal + icon: journal + order: 300 + access: general_ledger + module: gl.pl + params: + action: search +- id: cash + name: Cash + icon: cash + order: 600 +- parent: cash + id: cash_receipt + name: Receipt + icon: receipt + order: 100 + access: cash + module: cp.pl + params: + action: payment + vc: customer + type: receipt +- parent: cash + id: cash_payment + name: Payment + icon: payment + order: 200 + access: cash + module: cp.pl + params: + action: payment + vc: vendor + type: check +- parent: cash + id: cash_bank_collection_via_sepa + name: Bank collection via SEPA + order: 300 + access: cash + module: sepa.pl + params: + action: bank_transfer_add + vc: customer +- parent: cash + id: cash_bank_transfer_via_sepa + name: Bank transfer via SEPA + order: 400 + access: cash + module: sepa.pl + params: + action: bank_transfer_add + vc: vendor +- parent: cash + id: cash_bank_import + name: Bank Import + order: 500 + module: menu.pl + params: + action: acc_menu +- parent: cash_bank_import + id: cash_bank_import_csv + name: CSV + order: 100 + access: bank_transaction + params: + action: CsvImport/new + profile.type: bank_transactions +- parent: cash_bank_import + id: cash_bank_import_mt940 + name: MT940 + order: 200 + access: bank_transaction + params: + action: BankImport/upload_mt940 +- parent: cash + id: cash_bank_transactions_mt940 + name: Bank transactions MT940 + order: 600 + access: bank_transaction + params: + action: BankTransaction/search +- parent: cash + id: cash_reconciliation_with_bank + name: Reconciliation with bank + order: 700 + access: bank_transaction + params: + action: Reconciliation/search + next_sub: Reconciliation/reconciliation +- parent: cash + id: cash_reconciliation + name: Reconciliation + icon: reconcilliation + order: 800 + access: cash + module: rc.pl + params: + action: reconciliation +- parent: cash + id: cash_reports + name: Reports + icon: cash_report + order: 900 + module: menu.pl + params: + action: acc_menu +- parent: cash_reports + id: cash_reports_receipts + name: Receipts + icon: receipt_report + order: 100 + access: cash + module: rp.pl + params: + action: report + report: receipts +- parent: cash_reports + id: cash_reports_payments + name: Payments + icon: payment_report + order: 200 + access: cash + module: rp.pl + params: + action: report + report: payments +- parent: cash_reports + id: cash_reports_bank_collections_via_sepa + name: Bank collections via SEPA + order: 300 + access: cash + module: sepa.pl + params: + action: bank_transfer_search + vc: customer +- parent: cash_reports + id: cash_reports_bank_transfers_via_sepa + name: Bank transfers via SEPA + order: 400 + access: cash + module: sepa.pl + params: + action: bank_transfer_search + vc: vendor +- parent: cash_reports + id: cash_reports_bank_transactions + name: Bank transactions + order: 500 + access: bank_transaction + params: + action: BankTransaction/list_all +- id: reports + name: Reports + icon: report + order: 700 +- parent: reports + id: reports_chart_of_accounts + name: Chart of Accounts + icon: chart_of_accounts + order: 100 + access: report + module: ca.pl + params: + action: chart_of_accounts +- parent: reports + id: reports_trial_balance + name: Trial Balance + order: 200 + access: report + module: rp.pl + params: + action: report + report: trial_balance +- parent: reports + id: reports_income_statement + name: Income Statement + icon: income_statement + order: 300 + access: report + module: rp.pl + params: + action: report + report: income_statement +- parent: reports + id: reports_bwa + name: BWA + order: 400 + access: report + module: rp.pl + params: + action: report + report: bwa +- parent: reports + id: reports_balance_sheet + name: Balance Sheet + icon: balance_sheet + order: 500 + access: report + module: rp.pl + params: + action: report + report: balance_sheet +- parent: reports + id: reports_ustva + name: UStVa + icon: ustva + order: 600 + access: advance_turnover_tax_return + module: ustva.pl + params: + action: report +- parent: reports + id: reports_projecttransactions + name: Projecttransactions + order: 700 + access: report + module: rp.pl + params: + action: report + report: projects +- parent: reports + id: reports_financial_overview + name: Financial Overview + order: 800 + access: report + params: + action: FinancialOverview/list +- parent: reports + id: reports_liquidity_projection + name: Liquidity projection + order: 900 + access: report + params: + action: LiquidityProjection/show +- id: batch_printing + name: Batch Printing + icon: printing + order: 800 + access: batch_printing +- parent: batch_printing + id: batch_printing_sales_invoices + name: Sales Invoices + icon: sales_invoice_printing + order: 100 + access: invoice_edit + module: bp.pl + params: + action: search + vc: customer + type: invoice +- parent: batch_printing + id: batch_printing_sales_orders + name: Sales Orders + icon: sales_order_printing + order: 200 + access: sales_order_edit + module: bp.pl + params: + action: search + type: sales_order + vc: customer +- parent: batch_printing + id: batch_printing_quotations + name: Quotations + icon: quotation_printing + order: 300 + access: sales_quotation_edit + module: bp.pl + params: + action: search + vc: customer + type: sales_quotation +- parent: batch_printing + id: batch_printing_packing_lists + name: Packing Lists + icon: package_lists + order: 400 + access: invoice_edit | sales_order_edit + module: bp.pl + params: + action: search + type: packing_list + vc: customer +- parent: batch_printing + id: batch_printing_purchase_orders + name: Purchase Orders + icon: purchase_order_printing + order: 500 + access: purchase_order_edit + module: bp.pl + params: + action: search + type: purchase_order + vc: vendor +- parent: batch_printing + id: batch_printing_rfqs + name: RFQs + icon: rfq_printing + order: 600 + access: request_quotation_edit + module: bp.pl + params: + action: search + vc: vendor + type: request_quotation +- parent: batch_printing + id: batch_printing_checks + name: Checks + order: 700 + access: cash + module: bp.pl + params: + action: search + type: check + vc: vendor +- parent: batch_printing + id: batch_printing_receipts + name: Receipts + icon: receipt_printing + order: 800 + access: cash + module: bp.pl + params: + action: search + vc: customer + type: receipt +- id: productivity + name: Productivity + icon: productivity + order: 900 + access: productivity +- parent: productivity + id: productivity_show_todo_list + name: Show TODO list + order: 100 + module: todo.pl + params: + action: show_todo_list +- parent: productivity + id: productivity_add_follow_up + name: Add Follow-Up + order: 200 + module: fu.pl + params: + action: add +- parent: productivity + id: productivity_edit_access_rights + name: Edit Access Rights + order: 300 + module: fu.pl + params: + action: edit_access_rights +- parent: productivity + id: productivity_reports + name: Reports + order: 400 + module: menu.pl + params: + action: acc_menu +- parent: productivity_reports + id: productivity_reports_follow_ups + name: Follow-Ups + order: 100 + module: fu.pl + params: + action: search +- id: system + name: System + icon: system + order: 1000 + access: config +- parent: system + id: system_client_configuration + name: Client Configuration + order: 100 + access: admin + params: + action: ClientConfig/edit +- parent: system + id: system_ustva_einstellungen + name: UStVa Einstellungen + order: 200 + module: ustva.pl + params: + action: config_step1 +- parent: system + id: system_edit_dunning + name: Edit Dunning + order: 300 + module: dn.pl + params: + action: edit_config +- parent: system + id: system_chart_of_accounts + name: Chart of Accounts + order: 400 + module: menu.pl + params: + action: acc_menu +- parent: system_chart_of_accounts + id: system_chart_of_accounts_add_account + name: Add Account + order: 100 + module: am.pl + params: + action: add_account +- parent: system_chart_of_accounts + id: system_chart_of_accounts_list_accounts + name: List Accounts + order: 200 + module: am.pl + params: + action: list_account +- parent: system + id: system_buchungsgruppen + name: Buchungsgruppen + order: 500 + params: + action: Buchungsgruppen/list +- parent: system + id: system_taxzones + name: Taxzones + order: 600 + params: + action: Taxzones/list +- parent: system + id: system_taxes + name: Taxes + order: 700 + module: am.pl + params: + action: list_tax +- parent: system + id: system_bank_accounts + name: Bank accounts + order: 800 + params: + action: BankAccount/list +- parent: system + id: system_groups + name: Groups + order: 900 + module: pe.pl + params: + action: search + type: partsgroup +- parent: system + id: system_pricegroups + name: Pricegroups + order: 1000 + module: pe.pl + params: + action: search + type: pricegroup +- parent: system + id: system_edit_units + name: Edit units + order: 1100 + module: am.pl + params: + action: edit_units +- parent: system + id: system_price_factors + name: Price Factors + order: 1200 + module: am.pl + params: + action: list_price_factors +- parent: system + id: system_departments + name: Departments + order: 1300 + params: + action: Department/list +- parent: system + id: system_types_of_business + name: Types of Business + order: 1400 + params: + action: Business/list +- parent: system + id: system_leads + name: Leads + order: 1500 + module: am.pl + params: + action: list_lead +- parent: system + id: system_project_types + name: Project Types + order: 1600 + params: + action: ProjectType/list +- parent: system + id: system_project_status + name: Project Status + order: 1700 + params: + action: ProjectStatus/list +- parent: system + id: system_requirement_specs + name: Requirement specs + order: 1800 + module: menu.pl + target: acc_menu + params: + action: acc_menu +- parent: system_requirement_specs + id: system_requirement_specs_pre_defined_texts + name: Pre-defined Texts + order: 100 + params: + action: RequirementSpecPredefinedText/list +- parent: system_requirement_specs + id: system_requirement_specs_requirement_spec_types + name: Requirement Spec Types + order: 200 + params: + action: RequirementSpecType/list +- parent: system_requirement_specs + id: system_requirement_specs_requirement_spec_statuses + name: Requirement Spec Statuses + order: 300 + params: + action: RequirementSpecStatus/list +- parent: system_requirement_specs + id: system_requirement_specs_complexities + name: Complexities + order: 400 + params: + action: RequirementSpecComplexity/list +- parent: system_requirement_specs + id: system_requirement_specs_risks + name: Risks + order: 500 + params: + action: RequirementSpecRisk/list +- parent: system_requirement_specs + id: system_requirement_specs_acceptance_statuses + name: Acceptance Statuses + order: 600 + params: + action: RequirementSpecAcceptanceStatus/list +- parent: system + id: system_languages_and_translations + name: Languages and translations + order: 1900 + module: menu.pl + params: + action: acc_menu +- parent: system_languages_and_translations + id: system_languages_and_translations_add_language + name: Add Language + order: 100 + module: am.pl + params: + action: add_language +- parent: system_languages_and_translations + id: system_languages_and_translations_list_languages + name: List Languages + order: 200 + module: am.pl + params: + action: list_language +- parent: system_languages_and_translations + id: system_languages_and_translations_greetings + name: Greetings + order: 300 + module: generictranslations.pl + params: + action: edit_greetings +- parent: system_languages_and_translations + id: system_languages_and_translations_sepa_strings + name: SEPA strings + order: 400 + module: generictranslations.pl + params: + action: edit_sepa_strings +- parent: system + id: system_payment_terms + name: Payment Terms + order: 2000 + params: + action: PaymentTerm/list +- parent: system + id: system_delivery_terms + name: Delivery Terms + order: 2100 + params: + action: DeliveryTerm/list +- parent: system + id: system_manage_custom_variables + name: Manage Custom Variables + order: 2200 + params: + action: CustomVariableConfig/list +- parent: system + id: system_warehouses + name: Warehouses + order: 2300 + module: am.pl + params: + action: list_warehouses +- parent: system + id: system_import_csv + name: Import CSV + order: 2400 + module: menu.pl + params: + action: acc_menu +- parent: system_import_csv + id: system_import_csv_customers_and_vendors + name: Customers and vendors + order: 100 + params: + action: CsvImport/new + profile.type: customers_vendors +- parent: system_import_csv + id: system_import_csv_contacts + name: Contacts + order: 200 + params: + action: CsvImport/new + profile.type: contacts +- parent: system_import_csv + id: system_import_csv_shipto + name: Shipto + order: 300 + params: + action: CsvImport/new + profile.type: addresses +- parent: system_import_csv + id: system_import_csv_parts + name: Parts + order: 400 + params: + action: CsvImport/new + profile.type: parts +- parent: system_import_csv + id: system_import_csv_inventories + name: Inventories + order: 500 + params: + action: CsvImport/new + profile.type: inventories +- parent: system_import_csv + id: system_import_csv_projects + name: Projects + order: 600 + params: + action: CsvImport/new + profile.type: projects +- parent: system_import_csv + id: system_import_csv_orders + name: Orders + order: 700 + params: + action: CsvImport/new + profile.type: orders +- parent: system + id: system_templates + name: Templates + order: 2500 + access: admin + module: menu.pl + params: + action: acc_menu +- parent: system_templates + id: system_templates_html_templates + name: HTML Templates + order: 100 + module: amtemplates.pl + params: + action: display_template_form + type: templates + format: html +- parent: system_templates + id: system_templates_latex_templates + name: LaTeX Templates + order: 200 + module: amtemplates.pl + params: + action: display_template_form + format: tex + type: templates +- parent: system_templates + id: system_templates_stylesheet + name: Stylesheet + order: 300 + module: amtemplates.pl + params: + action: display_template_form + type: stylesheet +- parent: system + id: system_general_ledger_corrections + name: General Ledger Corrections + order: 2600 + module: acctranscorrections.pl + params: + action: analyze_filter +- parent: system + id: system_background_jobs_and_task_server + name: Background jobs and task server + order: 2700 + access: admin + module: menu.pl + params: + action: acc_menu +- parent: system_background_jobs_and_task_server + id: system_background_jobs_and_task_server_list_current_background_jobs + name: List current background jobs + order: 100 + params: + action: BackgroundJob/list +- parent: system_background_jobs_and_task_server + id: system_background_jobs_and_task_server_background_job_history + name: Background job history + order: 200 + params: + action: BackgroundJobHistory/list +- parent: system_background_jobs_and_task_server + id: system_background_jobs_and_task_server_task_server_control + name: Task server control + order: 300 + params: + action: TaskServer/show +- parent: system + id: system_audit_control + name: Audit Control + order: 2800 + module: am.pl + params: + action: audit_control +- parent: system + id: system_history_search_engine + name: History Search Engine + order: 2900 + module: am.pl + params: + action: show_history_search +- parent: system + id: system_employees + name: Employees + order: 3000 + access: admin + params: + action: Employee/list +- id: program + name: Program + icon: program + order: 1100 +- parent: program + id: program_user_preferences + name: User Preferences + order: 100 + module: am.pl + params: + action: config +- parent: program + id: program_internal_phone_list + name: Internal Phone List + order: 200 + params: + action: CTI/list_internal_extensions +- parent: program + id: program_version + name: Version + icon: version + order: 300 + module: login.pl + params: + action: company_logo + no_todo_list: 1 +- parent: program + id: program_administration_area + name: Administration area + order: 400 + access: display_admin_link + params: + action: Admin/login +- parent: program + id: program_documentation_in_german_ + name: Documentation (in German) + order: 500 + href: doc/kivitendo-Dokumentation.pdf + target: _blank +- parent: program + id: program_kivitendo_website_external_ + name: kivitendo website (external) + order: 600 + href: http://www.kivitendo.de/ + target: _blank +- parent: program + id: program_logout + name: Logout + icon: logout + order: 700 + params: + action: LoginScreen/logout diff --git a/menus/user/10-crm.yaml b/menus/user/10-crm.yaml new file mode 100644 index 000000000..c093cd955 --- /dev/null +++ b/menus/user/10-crm.yaml @@ -0,0 +1,254 @@ +--- +- id: crm + name: CRM + icon: crm + order: 50 +- parent: crm + id: crm_search + name: Search + icon: search + order: 100 + access: crm_search + module: crm/getData.php +- parent: crm + id: crm_add + name: Add + order: 200 +- parent: crm_add + id: crm_add_customer + name: Customer + icon: customer + order: 100 + access: crm_new + module: crm/firmen3.php + params: + Q: C +- parent: crm_add + id: crm_add_vendor + name: Vendor + icon: vendor + order: 200 + access: crm_new + module: crm/firmen3.php + params: + Q: V +- parent: crm_add + id: crm_add_person + name: Person + icon: contact + order: 300 + access: crm_new + module: crm/personen3.php +- parent: crm + id: crm_appointments + name: Appointments + icon: appointment + order: 300 + access: crm_termin + module: crm/termin.php +- parent: crm + id: crm_opportunity + name: Opportunity + icon: opportunity + order: 400 + access: crm_opportunity + module: crm/opportunity.php +- parent: crm + id: crm_follow_up + name: Follow-Up + icon: follow_up + order: 500 + access: crm_follow + module: crm/wvl1.php +- parent: crm + id: crm_e_mail + name: E-mail + icon: email + order: 600 + access: crm_email + module: crm/mail.php +- parent: crm + id: crm_knowledge + name: Knowledge + icon: knowledge + order: 700 + access: crm_knowhow + module: crm/wissen.php +- parent: crm + id: crm_memo + name: Memo + icon: memo + order: 800 + access: crm_notices + module: crm/postit.php +- parent: crm + id: crm_documents + name: Documents + order: 900 + access: crm_other + module: crm/dokument.php +- parent: crm + id: crm_time_tracking + name: Time Tracking + order: 1000 + access: crm_service + module: crm/timetrack.php +- parent: crm + id: crm_other + name: Other + order: 1100 +- parent: crm_other + id: crm_other_etikett + name: Etikett + order: 100 + access: crm_other + module: crm/prtetikett.php + target: _blank +- parent: crm_other + id: crm_other_dhl + name: DHL + order: 200 + access: crm_other + module: crm/dhl.php +- parent: crm_other + id: crm_other_ebayimporter + name: eBayImporter + order: 300 + access: crm_other + module: crm/ebayImporter.php +- parent: crm_other + id: crm_other_catalog + name: Catalog + order: 400 + access: crm_other + module: crm/katalog.php +- parent: crm_other + id: crm_other_warehouse_list + name: Warehouse list + order: 500 + access: crm_other + module: crm/inventur.php +- parent: crm_other + id: crm_other_warehouse_correction + name: Warehouse correction + order: 600 + access: crm_admin + module: crm/inventurlager.php +- parent: crm_other + id: crm_other_partsedit + name: Partsedit + order: 700 + access: crm_other + module: crm/partsedit.php +- parent: crm_other + id: crm_other_packliste + name: Packliste + order: 800 + access: crm_other + module: crm/packliste.php +- parent: crm_other + id: crm_other_eur + name: EuR + order: 900 + access: crm_other + module: crm/eur.php +- parent: crm_other + id: crm_other_zm + name: ZM + order: 1000 + access: crm_other + module: crm/ustva_zm.php +- parent: crm + id: crm_service + name: Service + icon: service + order: 1200 +- parent: crm_service + id: crm_service_service_contract + name: Service Contract + order: 100 + access: crm_service + module: crm/vertrag1.php +- parent: crm_service + id: crm_service_add_service_contract + name: Add Service Contract + order: 200 + access: crm_service + module: crm/vertrag3.php +- parent: crm_service + id: crm_service_machine + name: Machine + order: 300 + access: crm_service + module: crm/maschine1.php +- parent: crm_service + id: crm_service_add_machine + name: Add Machine + order: 400 + access: crm_service + module: crm/maschine3.php +- parent: crm + id: crm_admin + name: Admin + icon: admin + order: 1300 +- parent: crm_admin + id: crm_admin_document_template + name: Document Template + icon: document_template + order: 100 + access: crm_admin + module: crm/dokument1.php +- parent: crm_admin + id: crm_admin_label + name: Label + icon: label + order: 200 + access: crm_admin + module: crm/aufkleber_def.php +- parent: crm_admin + id: crm_admin_appointment_category + name: Appointment Category + order: 300 + access: crm_admin + module: crm/tcatedit.php +- parent: crm_admin + id: crm_admin_message + name: Message + icon: message + order: 400 + access: crm_admin + module: crm/user3.php +- parent: crm_admin + id: crm_admin_client + name: Client + order: 500 + access: crm_adminstatus + module: crm/mandant.php +- parent: crm_admin + id: crm_admin_user_groups + name: User Groups + icon: user_group + order: 600 + access: crm_admin + module: crm/user2.php +- parent: crm_admin + id: crm_admin_user + name: User + icon: user + order: 700 + access: crm_adminuser + module: crm/user1.php +- parent: crm_admin + id: crm_admin_dhl + name: DHL + order: 800 + access: crm_adminuser + module: crm/dhladm.php +- parent: crm_admin + id: crm_admin_status + name: Status + icon: status + order: 900 + access: crm_adminstatus + module: crm/status.php diff --git a/scripts/locales.pl b/scripts/locales.pl index b1927142e..ec9624a60 100755 --- a/scripts/locales.pl +++ b/scripts/locales.pl @@ -25,6 +25,8 @@ use IO::Dir; use List::MoreUtils qw(apply); use List::Util qw(first); use Pod::Usage; +use YAML (); +use YAML::Loader (); # YAML tries to load Y:L at runtime, but can't find it after we chdir'ed $OUTPUT_AUTOFLUSH = 1; @@ -41,7 +43,7 @@ my $basedir = "../.."; my $locales_dir = "."; my $bindir = "$basedir/bin/mozilla"; my @progdirs = ( "$basedir/SL" ); -my @menufiles = <${basedir}/menus/*.ini>; +my @menufiles = <"${basedir}/menus/*/*">; my @javascript_dirs = ($basedir .'/js', $basedir .'/templates/webpages'); my $javascript_output_dir = $basedir .'/js'; my $submitsearch = qr/type\s*=\s*[\"\']?submit/i; @@ -98,13 +100,6 @@ push @progfiles, map { m:^(.+)/([^/]+)$:; [ $2, $1 ] } grep { /\.pm$/ } map { fi # put customized files into @customfiles my %dir_h; -if ($opt_n) { - @customfiles = (); -} else { - tie %dir_h, 'IO::Dir', $basedir; - push @menufiles, map { "$basedir/$_" } grep { /.*_menu.ini$/ } keys %dir_h; -} - my @dbplfiles; foreach my $sub_dir ("Pg-upgrade2", "Pg-upgrade2-auth") { my $dir = "$basedir/sql/$sub_dir"; @@ -520,24 +515,13 @@ sub scanfile { sub scanmenu { my $file = shift; - my $fh = new FileHandle; - open $fh, '<:encoding(utf8)', $file or die "$! : $file"; - - my @a = grep m/^\[/, <$fh>; - close($fh); + print STDERR "trying to load file $file\n"; + my $menu = YAML::LoadFile($file); - # strip [] - grep { s/(\[|\])//g } @a; - - foreach my $item (@a) { - my @b = split /--/, $item; - foreach my $string (@b) { - chomp $string; - $locale{$string} = 1; - $alllocales{$string} = 1; - } + for my $node (@$menu) { + $locale{$node->{name}} = 1; + $alllocales{$node->{name}} = 1; } - } sub unescape_template_string { @@ -780,7 +764,7 @@ Be more verbose. =head1 DESCRIPTION -This script collects strings from Perl files, the menu.ini file and +This script collects strings from Perl files, the menu files and HTML templates and puts them into the file "all" for translation. =cut diff --git a/scripts/migrate_menu.pl b/scripts/migrate_menu.pl index af295c777..a0cdae80d 100644 --- a/scripts/migrate_menu.pl +++ b/scripts/migrate_menu.pl @@ -105,7 +105,59 @@ sub translate_to_yaml { } open my $out_file, '>:utf8', $new_file or die $!; - print $out_file YAML::Dump(\@menu_items); + print $out_file yaml_dump(\@menu_items); +} + +sub yaml_dump { + my ($ary_ref) = @_; + # YAML dumps keys lexically sorted, which isn't what we want. + # we want this order: + my @order = qw( + parent + id + name + icon + order + access + href + module + target + params + ); + + # ...oh and we want action in params first + # + # why this? because: + # 1. parent is what is used to anchor. one could argue that id should be + # first, but parent is easier for understanding structure. + # 2. after parent the logical structure is + # 1. id + # 2. stuff related to vidual presentation (name/icon) + # 3. stuff needed for logical presentaion (order/access) + # 4. stuff related to the action after clicking it + # 3. without parent and href (the second is pretty rare) the keys are nicely + # ascending in length, which is very easy to parse visually. + + my $yaml = "---\n"; + for my $node (@$ary_ref) { + my $first = 0; + for my $key (@order) { + next unless exists $node->{$key}; + $yaml .= ($first++ ? ' ' : '- ') . $key . ": "; + if (!ref $node->{$key}) { + $yaml .= $node->{$key} . "\n"; + } else { + $yaml .= "\n"; + for ('action', grep !/^action$/, keys %{ $node->{$key} }) { + next unless exists $node->{$key}{$_}; + $yaml .= " $_: $node->{$key}{$_}\n"; + } + } + + } + } + + $yaml; } while (my ($in, $out) = each(%menu_files)) { diff --git a/templates/webpages/menu/menunew.html b/templates/webpages/menu/menunew.html index fe5eb2135..70537e12f 100644 --- a/templates/webpages/menu/menunew.html +++ b/templates/webpages/menu/menunew.html @@ -1,33 +1,31 @@ [%- USE T8 %] -[% USE HTML %][%- USE LxERP -%] +[%- USE L %] +[%- USE HTML %] +[%- USE LxERP -%] - [%- SET main_id = '100' %]