dolibarr 23.0.3
documentation.class.php
1<?php
2/* Copyright (C) 2024 Anthony Damhet <a.damhet@progiseize.fr>
3 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
29{
35 public $view = array();
36
42 public $menu = array();
43
49 public $summary = array();
50
54 public $db;
55
59 public $baseUrl = 'admin/tools/ui';
60
67 public function __construct(DoliDB $db)
68 {
69 $this->db = $db;
70
71 // https://www.figma.com/community/file/1393171578760389765/dolibarr-ui-ux-kit
72
73 // Menu Constructor
74 $this->setMenu();
75 }
76
82 private function setMenu()
83 {
84 global $hookmanager;
85
86 $hookmanager->initHooks(array('uidocumentation'));
87
88 // Go back to Dolibarr
89 $this->menu['BackToDolibarr'] = array(
90 'url' => dol_buildpath('modulebuilder/index.php', 1),
91 'icon' => 'fas fa-arrow-left',
92 'submenu' => array(),
93 );
94
95 // Home for Ui documentation
96 $this->menu['DocumentationHome'] = array(
97 'url' => dol_buildpath($this->baseUrl.'/index.php', 1),
98 'icon' => 'fas fa-book',
99 'submenu' => array(),
100 );
101
102 // Components
103 $this->menu['Components'] = array(
104 'url' => dol_buildpath($this->baseUrl.'/components/index.php', 1),
105 'icon' => 'fas fa-th-large',
106 'submenu' => array(
107 'Badges' => array(
108 'url' => dol_buildpath($this->baseUrl.'/components/badges.php', 1),
109 'icon' => 'fas fa-certificate',
110 'submenu' => array(),
111 'summary' => array(
112 'DocBasicUsage' => '#badgesection-basicusage',
113 'DocBadgeContextualVariations' => '#badgesection-contextvariations',
114 'DocBadgeDefaultStatus' => '#badgesection-defaultstatus',
115 'DocBadgePillBadges' => '#badgesection-pill',
116 'DocBadgeDotBadges' => '#badgesection-dot',
117 'DocBadgeLinks' => '#badgesection-links',
118 'DocBadgeHelper' => '#badgesection-dolgetbadge'
119 ),
120 ),
121 'Buttons' => array(
122 'url' => dol_buildpath($this->baseUrl.'/components/buttons.php', 1),
123 'icon' => 'fas fa-mouse',
124 'submenu' => array(),
125 'summary' => array(
126 'DocBasicUsage' => '#buttonsection-basicusage',
127 'DocButtonModal' => '#buttonsection-modals',
128 'DocButtonSubmenu' => '#buttonsection-submenu',
129 ),
130 ),
131 'Icons' => array(
132 'url' => dol_buildpath($this->baseUrl.'/components/icons.php', 1),
133 'icon' => 'far fa-flag',
134 'submenu' => array(),
135 'summary' => array(
136 'DocIconsList' => '#img-picto-section-list',
137 'DocIconsFontAwesomeList' => '#icon-section-list',
138 ),
139 ),
140 'Progress' => array(
141 'url' => dol_buildpath($this->baseUrl.'/components/progress-bars.php', 1),
142 'icon' => 'fas fa-battery-half',
143 'submenu' => array(),
144 'summary' => array(
145 'DocBasicUsage' => '#progresse-section-basic-usage',
146 'DocColorVariants' => '#progress-section-color',
147 'DocStripedVariants' => '#progresse-section-stripped',
148 ),
149 ),
150 'Event Message' => array(
151 'url' => dol_buildpath($this->baseUrl.'/components/event-message.php', 1),
152 'icon' => 'fas fa-comments',
153 'submenu' => array(),
154 'summary' => array(
155 'DocBasicUsage' => '#seteventmessagesection-basicusage',
156 'DocSetEventMessageContextualVariations' => '#seteventmessagesection-contextvariations',
157 )
158 ),
159 'Inputs' => array(
160 'url' => dol_buildpath($this->baseUrl.'/components/inputs.php', 1),
161 'icon' => 'fas fa-comments',
162 'submenu' => array(),
163 'summary' => array(
164 'DocBasicUsage' => '#setinputssection-basicusage',
165 'DocHelperFunctionsInputUsage' => '#setinputssection-helperfunctions',
166 'DocHelperFunctionsGetSearchFilterToolInput' => '#setinputssection-getSearchFilterToolInput',
167 )
168 ),
169 ),
170 );
171
172 // Elements
173 $this->menu['Content'] = array(
174 'url' => dol_buildpath($this->baseUrl.'/content/index.php', 1),
175 'icon' => 'far fa-file-alt',
176 'submenu' => array(
177 'Titles' => array(
178 'url' => dol_buildpath('admin/tools/ui/content/titles.php', 1),
179 'icon' => 'fas fa-heading',
180 'submenu' => array(),
181 'summary' => array(
182 'DocBasicUsage' => '#titlesection-basicusage',
183 'DocTitleWithFilters' => '#titlesection-withfilters',
184 ),
185 ),
186 'Tables' => array(
187 'url' => dol_buildpath('admin/tools/ui/content/tables.php', 1),
188 'icon' => 'fas fa-table',
189 'submenu' => array(),
190 'summary' => array(
191 'DocBasicUsage' => '#tablesection-basicusage',
192 'DocTableWithFilters' => '#tablesection-withfilters',
193 'DocTableBeforeFilters' => '#tablesection-beforefilters',
194 'DocTableCSSClass' => '#tablesection-cssclasses',
195 ),
196 ),
197
198 'TableRowIntuitiveSelect' => array(
199 'url' => dol_buildpath($this->baseUrl.'/content/intuitive-table-row-select.php', 1),
200 'icon' => 'far fa-check-square',
201 'submenu' => array(),
202 'summary' => array(),
203 ),
204
205 'FreezeTooltip' => array(
206 'url' => dol_buildpath($this->baseUrl.'/content/freeze-tooltip.php', 1),
207 'icon' => 'far fa-comment',
208 'submenu' => array(),
209 'summary' => array(),
210 ),
211 )
212 );
213
214 // Elements
215 $this->menu['Resources'] = array(
216 'url' => dol_buildpath($this->baseUrl.'/resources/index.php', 1),
217 'icon' => 'fas fa-wrench',
218 'submenu' => array(
219 'Contributing' => array(
220 'url' => dol_buildpath($this->baseUrl.'/resources/contributing.php', 1),
221 'icon' => 'fas fa-code',
222 'submenu' => array(),
223 'summary' => array(
224 'DocContributeStep1' => '#contributesection-step1',
225 'DocContributeStep2' => '#contributesection-step2',
226 'DocContributeStep3' => '#contributesection-step3',
227 ),
228 ),
229 )
230 );
231
232
233
234 // Elements
235 $this->menu['ExperimentalUx'] = array(
236 'url' => dol_buildpath($this->baseUrl.'/experimental/index.php', 1),
237 'icon' => 'fas fa-flask',
238 'submenu' => array(
239 'ExperimentalUxIntroductionMenu' => array(
240 'url' => dol_buildpath($this->baseUrl.'/experimental/index.php', 1),
241 'icon' => 'fas fa-flask',
242 'submenu' => array(),
243 'summary' => array(
244 'Index' => '#top',
245 'ExperimentalUxIntroductionTitle' => '#experimental-ux-introduction',
246 'ExperimentalUxContributionTitle' => '#experimental-ux-contribution',
247 ),
248 ),
249 'ExperimentalUxInputAjaxFeedback' => array(
250 'url' => dol_buildpath($this->baseUrl.'/experimental/experiments/input-feedback/index.php', 1),
251 'icon' => 'fas fa-flask',
252 'submenu' => array(),
253 'summary' => array(),
254 ),
255 'UxDolibarrContext' => array(
256 'url' => dol_buildpath($this->baseUrl.'/experimental/experiments/dolibarr-context/index.php', 1),
257 'icon' => 'fas fa-flask',
258 'submenu' => array(
259 'UxDolibarrContextHowItWork' => array(
260 'url' => dol_buildpath($this->baseUrl.'/experimental/experiments/dolibarr-context/index.php', 1),
261 'icon' => 'fas fa-flask',
262 'submenu' => array(),
263 'summary' => array(
264 'Introduction' => '#titlesection-basicusage',
265 'ConsoleHelp' => '#titlesection-console-help',
266 'JSDolibarrhooks' => '#titlesection-hooks',
267 'JSDolibarrhooksReadyVsInit' => '#titlesection-event-init-vs-ready',
268 'JSDolibarrAwaitHooks' => '#titlesection-await-hooks',
269 'ExampleOfCreatingNewContextTool' => '#titlesection-create-tool-example',
270 'SetEventMessageTool' => '#titlesection-tool-seteventmessage',
271 'SetAndUseContextVars' => '#titlesection-contextvars',
272 ),
273 ),
274 'UxDolibarrContextLangsTool' => array(
275 'url' => dol_buildpath($this->baseUrl.'/experimental/experiments/dolibarr-context/langs-tool.php', 1),
276 'icon' => 'fas fa-flask',
277 'submenu' => array(),
278 'summary' => array(),
279 ),
280 ),
281 'summary' => array(),
282 ),
283 )
284 );
285
286 $parameters = array(
287 'baseUrl' => $this->baseUrl,
288 );
289 $action = '';
290
291 $reshook = $hookmanager->executeHooks('setMenu', $parameters, $this, $action);
292 if ($reshook < 0) {
293 return false;
294 }
295 }
296
306 public function docHeader($title = '', $arrayofjs = [], $arrayofcss = [], $hidenavmenu = '')
307 {
308 global $langs;
309 $title = (!empty($title)) ? dol_escape_htmltag($title) : $langs->trans('Documentation');
310
311 $arrayofcss[] = 'admin/tools/ui/css/documentation.css';
312
313 top_htmlhead('', $title, 0, 0, $arrayofjs, $arrayofcss);
314
315 print '<body class="dolibarr-doc'.($hidenavmenu ? "-bis" : "").'">';
316 }
317
322 public function docFooter()
323 {
324 global $langs;
325
326 // DIV FOR SCROLL ANIMATION
327 print '<div id="documentation-scrollwrapper">';
328 print '<div id="documentation-scroll"></div>';
329 print '</div>';
330
331 // JS
332 print '<script src="'.dol_buildpath('admin/tools/ui/js/documentation.js', 1).'"></script>';
333 print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.'"></script>';
334
335 print '</body>';
336 print '</html>';
337
339 }
340
346 public function showSidebar()
347 {
348 print '<div class="doc-sidebar">';
349
350 // LOGO
351 print '<div class="sidebar-logo">';
352 if (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) {
353 $urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg';
354 print '<img src="'.$urllogo.'" />';
355 }
356 print '</div>';
357
358 // NAVIGATION
359 print '<nav>';
360 if (!empty($this->menu)) {
361 $this->displayMenu($this->menu);
362 }
363 print '</nav>';
364
365 print '</div>';
366 }
367
375 private function displayMenu($menu, $level = 0)
376 {
377 global $langs;
378 $level++;
379
380 print '<ul>';
381 foreach ($menu as $key => $item) {
382 $levelclass = (!empty($item['submenu'])) ? 'li-withsubmenu' : '';
383 $levelclass .= (in_array($key, $this->view)) ? ' active' : '';
384 $levelclass .= ($key == 'BackToDolibarr') ? ' li-withseparator' : '';
385
386 print '<li class="'.trim($levelclass).' level-'.$level.'">';
387 print '<a href="'.$item['url'].'" class="'.((!empty($item['submenu'])) ? 'link-withsubmenu' : '').'">';
388 print ((!empty($item['icon'])) ? '<i class="menu-icon '.$item['icon'].' pictofixedwidth" aria-hidden="true"></i>' : '');
389 print '<span class="label">'.$langs->transnoentities($key).'</span>';
390 print ((!empty($item['submenu'])) ? '<i class="submenu-toggle fas fa-chevron-right" aria-hidden="true"></i>' : '');
391 print '</a>';
392 if (!empty($item['submenu'])) {
393 $this->displayMenu($item['submenu'], $level); // Appel récursif pour afficher les sous-menus
394 }
395 echo '</li>';
396 }
397 print '</ul>';
398 }
399
404 public function showBreadcrumb()
405 {
406 global $langs;
407
408 print '<nav class="doc-breadcrumbs">';
409 print '<ul>';
410 print '<li class="breadcrumb-item"><a href="'.$this->menu['DocumentationHome']['url'].'"><i class="'.$this->menu['DocumentationHome']['icon'].'" aria-hidden="true"></i></a></li>';
411 if (!empty($this->view)) {
412 $nb_entries = count($this->view);
413 $i = 0;
414
415 $menu_entry = $this->menu;
416 foreach ($this->view as $page) {
417 $i++;
418 if ($i < $nb_entries && isset($menu_entry[$page])) {
419 print '<li class="breadcrumb-item"><a href="'.$menu_entry[$page]['url'].'">'.$langs->transnoentities($page).'</a></li>';
420 $menu_entry = $menu_entry[$page]['submenu'];
421 } else {
422 print '<li class="breadcrumb-item">'.$langs->transnoentities($page).'</li>';
423 }
424 }
425 } else {
426 print '<li class="breadcrumb-item">'.$langs->trans('Documentation').'</li>';
427 }
428 print '</ul>';
429 print '</nav>';
430 }
431
439 public function showSummary($showsubmenu = 1, $showsubmenu_summary = 1)
440 {
441 $i = 0;
442 $menu_entry = [];
443 if (!empty($this->view)) {
444 // On se place au bon niveau
445 foreach ($this->view as $view) {
446 $i++;
447 if ($i == 1) {
448 $menu_entry = $this->menu[$view];
449 } else {
450 $menu_entry = $menu_entry['submenu'][$view];
451 }
452 }
453 }
454
455 if (!empty($menu_entry['summary']) || (!empty($menu_entry['submenu']) && $showsubmenu)) {
456 print '<div class="summary-wrapper">';
457 $this->displaySummary($menu_entry);
458 print '</div>';
459 }
460 }
461
462
472 public function displaySummary($menu, $level = 0, $showsubmenu = 1, $showsubmenu_summary = 1)
473 {
474 global $langs;
475
476 $level++;
477 print '<ul class="documentation-summary level-'.$level.'"">';
478
479 if (!empty($menu['summary'])) {
480 foreach ($menu['summary'] as $summary_label => $summary_link) {
481 /*
482 if ($summary_link[0] == '#') {
483 $tmp_summary_link = $menu['url'];
484 if (GETPOSTINT('hidenavmenu')) {
485 $tmp_summary_link .= (strpos($tmp_summary_link, '?') === false ? '?' : '&').'hidenavmenu=1';
486 }
487 if (GETPOSTINT('displayMode')) {
488 $tmp_summary_link .= (strpos($tmp_summary_link, '?') === false ? '?' : '&').'displayMode=1';
489 }
490 $summary_link = $tmp_summary_link;
491 }
492 */
493
494 print '<li><a href="'.$summary_link.'">'.$langs->trans($summary_label).'</a></li>';
495 }
496 }
497
498 if ($showsubmenu && !empty($menu['submenu'])) {
499 foreach ($menu['submenu'] as $key => $item) {
500 print '<li class="summary-title ">';
501
502 if (!empty($item['url'])) {
503 print '<h3 class="level-'.$level.'"><a href="'.dolBuildUrl($item['url']).'" >'.$langs->trans($key).'</a></h3>';
504 } else {
505 print '<h3 class="level-'.$level.'">'.$langs->trans($key).'</h3>';
506 }
507
508 if ($showsubmenu_summary) {
509 $this->displaySummary($item, $level);
510 }
511 print '</li>';
512 }
513 }
514 print '</ul>';
515 }
516
524 public function showCode($lines = array(), $option = 'html')
525 {
526 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
527 print '<div class="documentation-code">';
528
529 if (isset($lines[0])) {
530 if ($option === 'html' && strpos(strtolower($lines[0]), '<!doctype') === false) {
531 array_unshift($lines, '<!DOCTYPE html>', '');
532 }
533 }
534
535 $content = implode("\n", $lines) . "\n";
536 $doleditor = new DolEditor(md5($content), $content, '', 0, 'Basic', 'In', true, false, 'ace', 0, '99%', 1);
537 print $doleditor->Create(1, '', false, '', $option);
538 print '</div>';
539 }
540}
Class to manage UI documentation.
showBreadcrumb()
Output breadcrumb.
displayMenu($menu, $level=0)
Recursive function to set Menu.
showSummary($showsubmenu=1, $showsubmenu_summary=1)
Output summary.
docFooter()
Output close body + html.
showCode($lines=array(), $option='html')
Output a View Code area.
docHeader($title='', $arrayofjs=[], $arrayofcss=[], $hidenavmenu='')
Output header + body.
showSidebar()
Output sidebar.
__construct(DoliDB $db)
Constructor.
setMenu()
Set Documentation Menu.
displaySummary($menu, $level=0, $showsubmenu=1, $showsubmenu_summary=1)
Recursive function for Automatic Summary.
Class to manage a WYSIWYG editor.
Class to manage Dolibarr database access.
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
dol_htmloutput_events($disabledoutputofmessages=0)
Print formatted messages to output (Used to show messages on html output).
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs=array(), $arrayofcss=array(), $disableforlogin=0, $disablenofollow=0, $disablenoindex=0)
Output html header of a page.