Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 66fab876

Von Moritz Bunkus vor mehr als 8 Jahren hinzugefügt

  • ID 66fab87643fee5b4c7d85f4bf32ce4fb81118089
  • Vorgänger b8388d68
  • Nachfolger f770f74a

Hilfesystem: Hilfe-Link anzeigen; Hilfe-Seiten zu Kontext anzeigen; Hilfe-Start-Seite

Unterschiede anzeigen:

SL/Controller/Base.pm
6 6

  
7 7
use Carp;
8 8
use IO::File;
9
use List::MoreUtils qw(apply);
9 10
use List::Util qw(first);
11
use SL::HelpSystem;
10 12
use SL::Request qw(flatten);
11 13
use SL::MoreCommon qw(uri_encode);
12 14
use SL::Presenter;
......
228 230
  }
229 231
}
230 232

  
233
#
234
# Other class methods
235
#
236

  
237
sub override_help_contexts {
238
  my $class      = shift;
239
  my $controller = apply { s{.+:}{} } $class;
240

  
241
  SL::HelpSystem->override_help_contexts($controller, @_);
242
}
243

  
231 244
#
232 245
#  behaviour. override these
233 246
#
......
244 257
sub keep_auth_vars_in_form {
245 258
  return 0;
246 259
}
247

  
248 260
#
249 261
# private functions -- for use in Base only
250 262
#
......
628 640

  
629 641
=back
630 642

  
643
=head2 OTHER CLASS FUNCTIONS
644

  
645
=over 4
646

  
647
=item C<override_help_contexts %help_contexts>
648

  
649
Created overrides for the help context auto-detection by
650
L<SL::HelpSystem/context>. The keys given in the hash are action names
651
for which the help context is overridden.
652

  
653
The value can contain a slash in which case its used
654
verbatim. Otherwise value is taken to be an action name in the calling
655
controller and the controller's name will be prepended.
656

  
657
For example, in this example both targets will effectively be
658
C<BackgroundJob/edit>:
659

  
660

  
661
  package SL::Controller::BackgroundJob;
662

  
663
  use parent qw(SL::Controller::Base);
664

  
665
  __PACKAGE__->set_help_contexts(
666
    new    => 'edit',
667
    create => 'BackgroundJob/edit',
668
  );
669

  
670
=back
671

  
631 672
=head2 PRIVATE FUNCTIONS
632 673

  
633 674
These functions are supposed to be used from this base class only.
SL/Controller/Help.pm
1
package SL::Controller::Help;
2

  
3
use strict;
4

  
5
use parent qw(SL::Controller::Base);
6

  
7
use SL::HelpSystem;
8
use SL::Helper::Flash;
9
use SL::Locale::String;
10

  
11
use Rose::Object::MakeMethods::Generic
12
(
13
  'scalar --get_set_init' => [ qw(context context_controller context_action) ],
14
);
15

  
16
#
17
# actions
18
#
19

  
20
sub action_show {
21
  my ($self) = @_;
22

  
23
  my @potential_pages;
24

  
25
  my $language = $::myconfig{countrycode};
26
  $language    = undef if ($language // '') eq 'de';
27

  
28
  if ($self->context_controller) {
29
    if ($language) {
30
      push @potential_pages, { language => $language, category => $self->context_controller, topic => $self->context_action } if $self->context_action;
31
      push @potential_pages, { language => $language, category => $self->context_controller, topic => '_index' };
32
    }
33

  
34
    push @potential_pages, { language => 'de', category => $self->context_controller, topic => $self->context_action } if $self->context_action;
35
    push @potential_pages, { language => 'de', category => $self->context_controller, topic => '_index' };
36
  }
37

  
38
  push @potential_pages, { language => $language, topic => '_index' } if $language;
39
  push @potential_pages, { language => 'de',      topic => '_index' };
40

  
41
  my $page = $::request->help_system->page_available(@potential_pages);
42

  
43
  return $::form->error(t8("No help page to show was found.")) if !$page;
44

  
45
  $::request->layout(SL::Layout::Dispatcher->new(style => 'none'));
46
  $::request->layout->use_stylesheet('help.css');
47

  
48
  $self->render(
49
    'help/show',
50
    title   => t8('kivitendo help'),
51
    content => $::request->help_system->convert_page_to_html(%$page),
52
  );
53
}
54

  
55
#
56
# helpers
57
#
58

  
59
sub init_context            { $::form->{context} // ''           }
60
sub init_context_controller { (split m{/}, $_[0]->context, 2)[0] }
61
sub init_context_action     { (split m{/}, $_[0]->context, 2)[1] }
62

  
63
1;
SL/HelpSystem.pm
1
package SL::HelpSystem;
2

  
3
use strict;
4

  
5
use parent qw(Rose::Object);
6

  
7
use List::Util qw(first);
8

  
9
use SL::System::Process;
10

  
11
use Rose::Object::MakeMethods::Generic (
12
  'scalar --get_set_init' => [ qw(context base_path driver) ],
13
);
14

  
15
my %custom_help_contexts;
16

  
17
sub init_base_path { SL::System::Process::exe_dir() . '/templates/webpages/help' }
18

  
19
sub init_driver {
20
  require SL::HelpSystem::MultiMarkdown;
21
  return SL::HelpSystem::MultiMarkdown->new;
22
}
23

  
24
sub init_context {
25
  my ($controller, $action) = $::request ? ($::request->controller, $::request->action) : ();
26

  
27
  return undef if !$controller;
28

  
29
  my $override = ($custom_help_contexts{$controller} // {})->{$action};
30

  
31
  return $override               if $override && ($override =~ m{/});
32
  return "$controller/$override" if $override;
33
  return "$controller/$action"   if $action;
34
  return $controller;
35
}
36

  
37
sub page_available {
38
  my ($self, @pages) = @_;
39

  
40
  return first { -f $self->file_name_for_page(%$_) } @pages;
41
}
42

  
43
sub file_name_for_page {
44
  my ($self, %page) = @_;
45

  
46
  my $sub_path = join '/', grep { ($_ // '') ne '' } @page{ qw(language category topic) };
47

  
48
  return $self->base_path . '/content/' . $sub_path . '.' . $self->driver->file_name_extension;
49
}
50

  
51
sub convert_page_to_html {
52
  my ($self, %page) = @_;
53

  
54
  my $file_name = $self->file_name_for_page(%page);
55

  
56
  return -f $file_name ? $self->driver->convert_to_html($file_name) : undef;
57
}
58

  
59
sub sanitize {
60
  my ($self, $name) = @_;
61

  
62
  $name //= '';
63
  $name   =~ s{[^a-z0-9_-]+}{}gi;
64

  
65
  return $name;
66
}
67

  
68
sub override_help_contexts {
69
  my ($class, $controller, %help_contexts) = @_;
70

  
71
  $custom_help_contexts{$controller} = \%help_contexts;
72
}
73

  
74
1;
75

  
76
__END__
77

  
78
=pod
79

  
80
=encoding utf8
81

  
82
=head1 NAME
83

  
84
SL::HelpSystem - Help system helper functions
85

  
86
=head1 SYNOPSIS
87

  
88
  my $help_system = SL::HelpSystem->new;
89
  my $page = $help_system->page_available('de/ic/add');
90
  if ($page) {
91
    $self->render(
92
      'help/show',
93
      title   => t8('kivitendo help'),
94
      content => $help_system->convert_page_to_html($page),
95
    );
96
  }
97

  
98
=head1 FUNCTIONS
99

  
100
=over 4
101

  
102
=item C<base_path>
103

  
104
Returns the base path where all the help pages are stored.
105

  
106
=item C<context>
107

  
108
This gets or sets the help context. The help context is used by the
109
layout when displaying a link to the help system.
110

  
111
If a controller does not set a help context then it defaults to
112
C<controller/action> as returned by the two functions with the same
113
name in the L<SL::Request> object.
114

  
115
=item C<convert_page_to_html %page>
116

  
117
Converts a markup help page to HTML and returns the converted
118
HTML. The C<%page> parameter must be a hash suitable for
119
L</file_name_for_page>.
120

  
121
=item C<driver>
122

  
123
Gets or sets the driver to use. The default driver supports
124
MultiMarkdown via L<SL::HelpSystem::MultiMarkdown>.
125

  
126
=item C<file_name_for_page %page>
127

  
128
Returns the file name for a help page. Note that the file may or may
129
not exist.
130

  
131
The C<%page> must be a hash with the following keys: C<language>,
132
C<category> and C<topic>. Their values are sanitized with the
133
L</sanitize> function and concatenated in exactly this order to form
134
the actual file name. Elements that aren't set are skipped.
135

  
136
The C<category> will usually be a controller name and the C<topic>
137
will usually be an action for that controller.
138

  
139
=item C<page_available @pages>
140

  
141
Returns the first page for which a file name as given by
142
L</file_name_for_page> exists. C<@pages> must be an array of hash refs
143
suitable for L</file_name_for_page>.
144

  
145
=item C<sanitize $name>
146

  
147
Page name components may only consist of the following characters: the
148
characters C<a-z> and C<A-Z>, digits C<0-9> and the special characters
149
C<_> and C<->.
150

  
151
This function removes all other characters from C<$name> and returns
152
the cleaned version.
153

  
154
=back
155

  
156
=head1 BUGS
157

  
158
Nothing here yet.
159

  
160
=head1 AUTHOR
161

  
162
Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
163

  
164
=cut
SL/HelpSystem/MultiMarkdown.pm
1
package SL::HelpSystem::MultiMarkdown;
2

  
3
use strict;
4

  
5
use parent qw(Rose::Object);
6

  
7
use Encode ();
8
use File::Slurp ();
9
use Text::MultiMarkdown;
10

  
11
use Rose::Object::MakeMethods::Generic (
12
  'scalar --get_set_init' => [ qw(multimarkdown) ],
13
);
14

  
15
sub init_multimarkdown {
16
  return Text::MultiMarkdown->new(
17
    empty_element_suffix => '>',
18
    tab_width            => 4,
19
  );
20
}
21

  
22
sub file_name_extension { "mmd" }
23

  
24
sub convert_to_html {
25
  my ($self, $file_name) = @_;
26

  
27
  my $markup = Encode::decode('utf-8', scalar(File::Slurp::slurp($file_name)));
28
  return $self->multimarkdown->markdown($markup);
29
}
30

  
31
1;
SL/InstallationCheck.pm
51 51
  { name => "Template",        version => '2.18',  url => "http://search.cpan.org/~abw/",       debian => 'libtemplate-perl' },
52 52
  { name => "Text::CSV_XS",    version => '0.23',  url => "http://search.cpan.org/~hmbrand/",   debian => 'libtext-csv-xs-perl' },
53 53
  { name => "Text::Iconv",     version => '1.2',   url => "http://search.cpan.org/~mpiotr/",    debian => 'libtext-iconv-perl' },
54
  { name => "Text::MultiMarkdown",                 url => "https://metacpan.org/pod/Template::Plugin::MultiMarkdown", debian => 'libtext-multimarkdown-perl' },
54 55
  { name => "URI",             version => '1.35',  url => "http://search.cpan.org/~gaas/",      debian => 'liburi-perl' },
55 56
  { name => "XML::Writer",     version => '0.602', url => "http://search.cpan.org/~josephw/",   debian => 'libxml-writer-perl' },
56 57
  { name => "YAML",            version => '0.62',  url => "http://search.cpan.org/~ingy/",      debian => 'libyaml-perl' },
SL/Layout/Top.pm
14 14
  # certain columns that are only created by said database upgrades.
15 15
  push @options, (quick_search => SL::Controller::TopQuickSearch->new) unless $::request->applying_database_upgrades;
16 16

  
17
  # The help system is currently disabled by default as most of its
18
  # content is still missing. It would be a disservice to users if it
19
  # were enabled in such a state. For developers and documenters
20
  # working on the documentation the feature must be turned on. Once
21
  # enough documentation has been written the feature will be enabled
22
  # unconditionally.
23
  push @options, (help_context => $::request->help_system->context) if $::lx_office_conf{devel}->{enable_help_system};
24

  
17 25
  $self->presenter->render('menu/header',
18 26
    now        => DateTime->now_local,
19 27
    is_fastcgi => $::dispatcher ? scalar($::dispatcher->interface_type =~ /fastcgi/i) : 0,
SL/Request.pm
10 10
use Exporter qw(import);
11 11

  
12 12
use SL::Common;
13
use SL::HelpSystem;
13 14
use SL::MoreCommon qw(uri_encode uri_decode);
14 15
use SL::Layout::None;
15 16
use SL::Presenter;
......
19 20
use Rose::Object::MakeMethods::Generic
20 21
(
21 22
  scalar                  => [ qw(applying_database_upgrades routing_type controller action) ],
22
  'scalar --get_set_init' => [ qw(cgi layout presenter is_ajax type) ],
23
  'scalar --get_set_init' => [ qw(cgi layout presenter is_ajax type help_system) ],
23 24
);
24 25

  
25 26
sub init_cgi {
......
34 35
  return SL::Presenter->new;
35 36
}
36 37

  
38
sub init_help_system {
39
  return SL::HelpSystem->new;
40
}
41

  
37 42
sub init_is_ajax {
38 43
  return ($ENV{HTTP_X_REQUESTED_WITH} || '') eq 'XMLHttpRequest' ? 1 : 0;
39 44
}
config/kivitendo.conf.default
257 257
# database ID or its name.
258 258
client =
259 259

  
260
# The help system is currently disabled by default as most of its
261
# content is still missing. It would be a disservice to users if it
262
# were enabled in such a state. For developers and documenters working
263
# on the documentation the feature must be turned on. Once enough
264
# documentation has been written the feature will be enabled
265
# unconditionally.
266
enable_help_system = 0
267

  
260 268
[debug]
261 269
# Use DBIx::Log4perl for logging DBI calls. The string LXDEBUGFILE
262 270
# will be replaced by the file name configured for $::lxdebug.
css/kivitendo/help.css
1
.kivitendo-help pre {
2
  background-color: #eee;
3
  overflow: auto;
4
}
5

  
6
.kivitendo-help thead th {
7
	padding: 0.2em;
8
	background-color: #EBEBEB;
9
	color: #006400;
10
	font-weight: bolder;
11
	text-align: left;
12
	border-style: none;
13
}
14

  
15
.kivitendo-help tbody tr:nth-child(odd) {
16
	background-color: #FFFF99;
17
	color: black;
18
	vertical-align: top;
19
}
20

  
21
.kivitendo-help tbody tr:nth-child(even) {
22
	background-color: #FFFFFF;
23
	color: black;
24
	vertical-align: top;
25
}
css/lx-office-erp/help.css
1
.kivitendo-help pre {
2
  background-color: #eee;
3
  overflow: auto;
4
}
locale/de/all
1357 1357
  'Has serial number'           => 'Hat eine Serienummer',
1358 1358
  'Headers'                     => 'Kopfzeilen',
1359 1359
  'Heading'                     => 'Überschrift',
1360
  'Help'                        => 'Hilfe',
1360 1361
  'Help Template Variables'     => 'Hilfe zu Dokumenten-Variablen',
1361 1362
  'Help on column names'        => 'Hilfe zu Spaltennamen',
1362 1363
  'Here'                        => 'Hier',
......
1778 1779
  'No file has been uploaded yet.' => 'Es wurde noch keine Datei hochgeladen.',
1779 1780
  'No function blocks have been created yet.' => 'Es wurden noch keine Funktionsblöcke angelegt.',
1780 1781
  'No groups have been created yet.' => 'Es wurden noch keine Gruppen angelegt.',
1782
  'No help page to show was found.' => 'Es wurde keine anzuzeigende Hilfeseite gefunden.',
1781 1783
  'No internal phone extensions have been configured yet.' => 'Es wurden noch keine internen Durchwahlen konfiguriert.',
1782 1784
  'No invoices have been selected.' => 'Es wurden keine Rechnungen ausgewählt.',
1783 1785
  'No or an unknown authenticantion module specified in "config/kivitendo.conf".' => 'Es wurde kein oder ein unbekanntes Authentifizierungsmodul in "config/kivitendo.conf" angegeben.',
......
1886 1888
  'Open amount'                 => 'offener Betrag',
1887 1889
  'Open in new window'          => 'In neuem Fenster &ouml;ffnen.',
1888 1890
  'Open invoice'                => 'Offene Rechnungen',
1891
  'Open kivitendo\'s help system in a new window' => 'Öffnet kivitendo\'s Hilfesystem in einem neuen Fenster',
1889 1892
  'Open new tab'                => 'Neuen Tab öffnen',
1890 1893
  'Open sales delivery orders'  => 'Offene Verkaufslieferscheine',
1891 1894
  'Open this Website'           => 'Homepage in neuem Fenster &ouml;ffnen',
......
3470 3473
  'kivitendo can fix these problems automatically.' => 'kivitendo kann solche Probleme automatisch beheben.',
3471 3474
  'kivitendo has been extended to handle multiple clients within a single installation.' => 'kivitendo wurde um Mandantenfähigkeit erweitert.',
3472 3475
  'kivitendo has found one or more problems in the general ledger.' => 'kivitendo hat ein oder mehrere Probleme im Hauptbuch gefunden.',
3476
  'kivitendo help'              => 'kivitendo-Hilfe',
3473 3477
  'kivitendo is about to update the database [ #1 ].' => 'kivitendo wird gleich die Datenbank [ #1 ] aktualisieren.',
3474 3478
  'kivitendo is now able to manage warehouses instead of just tracking the amount of goods in your system.' => 'kivitendo enth&auml;lt jetzt auch echte Lagerverwaultung anstatt reiner Mengenz&auml;hlung.',
3475 3479
  'kivitendo modules'           => 'Module',
templates/webpages/help/content/de/_index.mmd
1
# kivitendo-Hilfe
2

  
3
Willkommen bei der [kivitendo](http://www.kivitendo.org/)-Hilfe. Dies ist die Startseite.
4

  
5
## Externe Hilfequellen
6

  
7
Es gibt mehrere externe Hilfequellen, die Sie kontaktieren können:
8

  
9
* [das Forum](https://forum.kivitendo.de:32443/)
10
* [den Bugtracker](http://redmine.kivitendo-premium.de/projects/forum/issues)
11
* [die Mailinglisten](http://www.kivitendo.org/community/mailinglisten.html)
templates/webpages/help/content/de/_tests/features_1.mmd
1
# Hauptüberschrift
2

  
3
Dieser Abschnitt enthält Informationen zum Anlegen neuer oder Bearbeiten bestehender Artikel in den Stammdaten.
4

  
5
Doppelte Zeilenumbrüche sollten einen neuen Absatz einleiten.
6

  
7
Einzelne Zeilenumbrüche im Quelltext
8
sollten auch in der Ausgabe
9
einen Zeilenumbruch erzeugen.
10

  
11
## Kleinere Überschrift
12
Eine Leerzeile nach einer Überschrift sollte nicht nötig sein.
13

  
14
Eine Leerzeile vor einer Überschrift sollte nicht nötig sein.
15
## Auch eine Überschrift
16

  
17
Bauen wir eine Aufzählungsliste:
18

  
19
* Punkt eins
20
* Punkt zwei
21
* Noch ein Punkt
22

  
23
Und nun eine mit Nummerierung:
24

  
25
1. Weil ich das toll finde.
26
2. Weil ich immer Recht habe.
27
3. Mehr Begründungen werden selbstverständlich dann auch nicht benötigt.
28

  
29
Jezt folgt ein Block, der besonders hervorgehoben werden soll:
30

  
31
==Achtung!
32
Dies ist die öffentliche Bekanntmachung, dass kivitendo toll ist!==
33

  
34
Jut. Nun dann. Was brauchen wir noch? Richtig, eine Tabelle!
35

  
36
| Film/Serie | Zitat |
37
|--------|--------|
38
| Battlestar Galactica |  So say we all! |
39
| Dirty Dancing | Ich habe eine Wassermelone getragen. |
40
| Ghostbusters | Er schleimte mich voll. |
41

  
42
Textauszeichnung[^1] ist auch wichtig. Reden wir über *kursiv* oder **fett** oder gar `typesetter`? Wer weiß das schon so genau!
43

  
44
Externe Links wie z.B. zur [kivitendo-Homepage](http://www.kivitendo.org/) sind auch wichtig.
45

  
46
Codeblöcke sind interessant. Diese werden eingerückt:
47

  
48
    package Sparta;
49
    sub new {
50
      say "This is ", $_[0], "!";
51
    }
52

  
53
Das geht aber auch anders:
54

  
55
```
56
package Sparta;
57
sub new {
58
  say "This is ", $_[0], "!";
59
}
60
```
61

  
62
Alrighty.
63

  
64
Ein Bild sagt mehr als ein besoffener Hund.
65

  
66
![Ein Bild, ein Bild](image/kivitendo.png)
67

  
68
[^1]: Stay away from da Voodoo, mon!
templates/webpages/help/show.html
1
[%- USE HTML -%]
2
<html>
3
 <head>
4
  <title>[% HTML.escape(title) %]</title>
5
 </head>
6

  
7
 <body class="kivitendo-help">
8
  [% content %]
9
 </body>
10
</html>
templates/webpages/menu/header.html
1
[%- USE T8 %][%- USE LxERP -%]
1
[%- USE T8 %][%- USE LxERP -%][%- USE HTML -%]
2 2
[%- UNLESS skip_frame_header %]
3 3
<div id="frame-header">
4 4
[%- UNLESS is_links %]
5 5
 <span class="frame-header-element frame-header-left">
6 6
    [<a href="controller.pl?action=LoginScreen/user_login" target="_blank" title="[% 'Open a further kivitendo window or tab' | $T8 %]">[% 'New window/tab' | $T8 %]</a>]
7 7
    [<a href="JavaScript:top.print();" title="[% 'Hardcopy' | $T8 %]">[% 'Print' | $T8 %]</a>]
8
[%- IF help_context %]
9
    [<a href="controller.pl?action=Help/show&context=[% HTML.url(help_context) %]" target="_kivitendo_help", title="[% LxERP.t8("Open kivitendo's help system in a new window") %]">[% LxERP.t8("Help") %]</a>]
10
[%- END %]
8 11

  
9 12
[%- FOREACH search = quick_search.enabled_modules %]
10 13
    [<input id="top-quick-search-[% search.name %]" module="[% search.name %]" placeholder="[% search.description_field %]" maxlength="20">]

Auch abrufbar als: Unified diff