Webgui: user definable menu implemented
This commit is contained in:
+83
-10
@@ -235,6 +235,7 @@ class User {
|
||||
public $vessel; // name of current vessel
|
||||
public $datefmt;
|
||||
public $rows_pp;
|
||||
public $menu;
|
||||
|
||||
private function __construct() {
|
||||
global $g_rows_pp;
|
||||
@@ -245,6 +246,7 @@ class User {
|
||||
$this->vessel = 'Yacht';
|
||||
$this->datefmt = 'Y-m-d';
|
||||
$this->rows_pp = $g_rows_pp;
|
||||
$this->menu = [1, 2, 3, 4, 5, 6];
|
||||
}
|
||||
|
||||
public static function getInstance() {
|
||||
@@ -350,6 +352,18 @@ class User {
|
||||
if ($user_rows_pp) {
|
||||
$this->rows_pp = $user_rows_pp;
|
||||
}
|
||||
// user defined menu
|
||||
$sql = "SELECT valstr FROM settings WHERE userid=? AND sno=3";
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute([$this->id]);
|
||||
$res = $sth->fetchColumn();
|
||||
if ($res === false) {
|
||||
$sql = "INSERT INTO settings (userid, sno, valstr) VALUES (?, 3, ?)";
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute([$this->id, implode(',', $this->menu)]);
|
||||
} else {
|
||||
$this->menu = array_map('intval', explode(',', $res));
|
||||
}
|
||||
}
|
||||
|
||||
function get_last_error() {
|
||||
@@ -1455,13 +1469,72 @@ function normalize_phone_e164($phone) {
|
||||
|
||||
// ========== MENU FUNCTIONS ==================================================
|
||||
|
||||
$g_menu = Array (
|
||||
'equipment.php' => [_('Equipment')],
|
||||
'inventory.php' => [_('Inventory')],
|
||||
'provisions.php' => [_('Provisions')],
|
||||
'maintenance.php' => [_('Maintenance')],
|
||||
'projects.php' => [_('Projects')],
|
||||
'documents.php' => [_('Documents')],
|
||||
'manual.php' => ['<i class="bi-book"></i>'],
|
||||
'logout.php' => ['<i class="bi-door-open"></i>']
|
||||
);
|
||||
$g_modules = Array(
|
||||
1 => ['file' => 'equipment.php',
|
||||
'title' => _('Equipment'),
|
||||
'type' => 'primary',
|
||||
'group' => 'main'],
|
||||
2 => ['file' => 'inventory.php',
|
||||
'title' => _('Inventory'),
|
||||
'type' => 'primary',
|
||||
'group' => 'main'],
|
||||
3 => ['file' => 'provisions.php',
|
||||
'title' => _('Provisions'),
|
||||
'type' => 'primary',
|
||||
'group' => 'main'],
|
||||
4 => ['file' => 'maintenance.php',
|
||||
'title' => _('Maintenance'),
|
||||
'type' => 'primary',
|
||||
'group' => 'main'],
|
||||
5 => ['file' => 'projects.php',
|
||||
'title' => _('Projects'),
|
||||
'type' => 'primary',
|
||||
'group' => 'main'],
|
||||
6 => ['file' => 'documents.php',
|
||||
'title' => _('Documents'),
|
||||
'type' => 'primary',
|
||||
'group' => 'main'],
|
||||
7 => ['file' => 'company.php',
|
||||
'title' => _('Companies'),
|
||||
'type' => 'primary',
|
||||
'group' => 'base'],
|
||||
8 => ['file' => 'task.php',
|
||||
'title' => _('Task'),
|
||||
'type' => 'primary',
|
||||
'group' => 'extra'],
|
||||
9 => ['file' => 'measurement.php',
|
||||
'title' => _('Measurement'),
|
||||
'type' => 'primary',
|
||||
'group' => 'extra'],
|
||||
10 => ['file' => 'storage.php',
|
||||
'title' => _('Storage'),
|
||||
'type' => 'primary',
|
||||
'group' => 'base'],
|
||||
11 => ['file' => 'box.php',
|
||||
'title' => _('Boxes'),
|
||||
'type' => 'primary',
|
||||
'group' => 'extra'],
|
||||
12 => ['file' => 'cable.php',
|
||||
'title' => _('Cables'),
|
||||
'type' => 'primary',
|
||||
'group' => 'extra'],
|
||||
13 => ['file' => 'fuse.php',
|
||||
'title' => _('Fuses'),
|
||||
'type' => 'primary',
|
||||
'group' => 'extra'],
|
||||
14 => ['file' => 'checklist.php',
|
||||
'title' => _('Checklists'),
|
||||
'type' => 'primary',
|
||||
'group' => 'extra'],
|
||||
15 => ['file' => 'tag.php',
|
||||
'title' => _('Tags'),
|
||||
'type' => 'secondary',
|
||||
'group' => 'base'],
|
||||
16 => ['file' => 'settings.php',
|
||||
'title' => _('Settings'),
|
||||
'type' => 'secondary',
|
||||
'group' => 'extra'],
|
||||
17 => ['file' => 'dropdown.php',
|
||||
'title' => _('Selection lists'),
|
||||
'type' => 'secondary',
|
||||
'group' => 'base']);
|
||||
|
||||
+6
-3
@@ -31,14 +31,17 @@ if (isset($GLOBALS['local_script'])) {
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav">
|
||||
<?php
|
||||
foreach ($g_menu as $key => $value) {
|
||||
for ($i = 0; $i < 6; $i++) {
|
||||
echo str_repeat(' ', 4);
|
||||
echo '<li class="nav-item">';
|
||||
$active = ($g_scriptname == $key) ? ' active' : '';
|
||||
echo '<a class="nav-link', $active,'" href="', $key, '">', $value[0], "</a>";
|
||||
$module = $g_modules[$user->menu[$i]];
|
||||
$active = ($g_scriptname == $module['file']) ? ' active' : '';;
|
||||
echo '<a class="nav-link', $active,'" href="', $module['file'], '">', $module['title'], "</a>";
|
||||
echo "</li>\n";
|
||||
}
|
||||
?>
|
||||
<li class="nav-item"><a class="nav-link" href="manual.php"><i class="bi-book"></i></a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="logout.php"><i class="bi-door-open"></i></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+29
-32
@@ -8,6 +8,7 @@
|
||||
|
||||
require 'globals.inc';
|
||||
require 'lib/gpc.inc';
|
||||
require 'lib/svg.inc';
|
||||
|
||||
$pagetitle = _('Start');
|
||||
|
||||
@@ -395,20 +396,26 @@ echo "</table>\n";
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><?=_('Base data')?></h5>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><a href="dropdown.php"><?=_('Selection lists')?></a></li>
|
||||
<li class="list-group-item"><a href="tag.php"><?=_('Tags')?></a></li>
|
||||
<li class="list-group-item"><a href="storage.php"><?=_('Storage')?></a></li>
|
||||
<li class="list-group-item"><a href="company.php"><?=_('Companies')?></a></li>
|
||||
<?php
|
||||
// load all base modules not in main menu
|
||||
foreach ($g_modules as $mid => $module) {
|
||||
if (!in_array($mid, $user->menu) && ($module['group'] === 'base')) {
|
||||
echo ' <li class="list-group-item"><a href="', $module['file'], '">', $module['title'],"</a></li>\n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<hr>
|
||||
<h5 class="card-title"><?=_('Additional modules')?></h5>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><a href="settings.php"><?=_('Settings')?></a></li>
|
||||
<li class="list-group-item"><a href="task.php"><?=_('Tasks')?></a></li>
|
||||
<li class="list-group-item"><a href="measurement.php"><?=_('Measurements')?></a></li>
|
||||
<li class="list-group-item"><a href="cable.php"><?=_('Cables')?></a></li>
|
||||
<li class="list-group-item"><a href="fuse.php"><?=_('Fuses')?></a></li>
|
||||
<li class="list-group-item"><a href="checklist.php"><?=_('Checklists')?></a></li>
|
||||
<?php
|
||||
// load all main or extra modules not in main menu
|
||||
foreach ($g_modules as $mid => $module) {
|
||||
if (!in_array($mid, $user->menu) && ($module['group'] === 'extra' || $module['group'] === 'main')) {
|
||||
echo ' <li class="list-group-item"><a href="', $module['file'], '">', $module['title'],"</a></li>\n";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -451,30 +458,20 @@ elseif ($action == ACT_EDIT):
|
||||
|
||||
// check if there is a shapefile-index
|
||||
$shapeindexfile = $g_doc_basepath . '/shapeindex.json';
|
||||
$shapeindex = [];
|
||||
if (!file_exists($shapeindexfile)) {
|
||||
// try to read metadata from top of svg file
|
||||
foreach (glob($g_shapedir.'/*.svg') as $f) {
|
||||
$fh = fopen($f, 'r');
|
||||
$fname = basename($f);
|
||||
$header = fread($fh, 1024);
|
||||
if (preg_match('/<title[^>]*>(.*?)<\/title>/is', $header, $match)) {
|
||||
$title = trim($match[1]);
|
||||
} else {
|
||||
$title = $fname;
|
||||
}
|
||||
$shapeindex[$fname] = $title;
|
||||
fclose($fh);
|
||||
}
|
||||
$json = json_encode($shapeindex, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
file_put_contents($shapeindexfile, $json);
|
||||
$shapeindex = create_shapeindex($shapeindexfile);
|
||||
} else {
|
||||
// read svg metadata from existing file
|
||||
$json = file_get_contents($shapeindexfile);
|
||||
$shapeindex = json_decode($json, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
// TODO some kind of error and fallback
|
||||
// perhaps regenerate index file?
|
||||
// check if shapeindex needs refresh (older than one day)
|
||||
if (time() - filemtime($shapeindexfile) > 86400) {
|
||||
$shapeindex = create_shapeindex($shapeindexfile);
|
||||
} else {
|
||||
// read svg metadata from existing file
|
||||
$json = file_get_contents($shapeindexfile);
|
||||
$shapeindex = json_decode($json, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
// TODO some kind of error and fallback
|
||||
// perhaps regenerate index file?
|
||||
}
|
||||
}
|
||||
}
|
||||
$opt_shapefiles = $g_opt_none + $shapeindex;
|
||||
|
||||
+46
-5
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/******************************************************************************
|
||||
* YMS - Yacht Management Software
|
||||
* Copyright (C) 2024 Thomas Hooge
|
||||
* Copyright (C) 2024-2026 Thomas Hooge
|
||||
*
|
||||
* SPDX-License-Identifier: WTFPL
|
||||
******************************************************************************
|
||||
@@ -10,8 +10,49 @@
|
||||
|
||||
// ========== SVG-FUNCTIONS ===================================================
|
||||
|
||||
function create_shapeindex($shapeindexfile) {
|
||||
// an existing index file will be overwritten
|
||||
global $g_shapedir;
|
||||
foreach (glob($g_shapedir.'/*.svg') as $f) {
|
||||
$fh = fopen($f, 'r');
|
||||
$fname = basename($f);
|
||||
// try to read metadata from top of svg file
|
||||
$header = fread($fh, 1024);
|
||||
if (preg_match('/<title[^>]*>(.*?)<\/title>/is', $header, $match)) {
|
||||
$title = trim($match[1]);
|
||||
} else {
|
||||
$title = $fname;
|
||||
}
|
||||
$shapeindex[$fname] = $title;
|
||||
fclose($fh);
|
||||
}
|
||||
$json = json_encode($shapeindex, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
file_put_contents($shapeindexfile, $json);
|
||||
return $shapeindex;
|
||||
}
|
||||
|
||||
function get_shapeindex() {
|
||||
global $g_doc_basepath;
|
||||
$shapeindex = [];
|
||||
$shapeindexfile = $g_doc_basepath . '/shapeindex.json';
|
||||
if (!file_exists($shapeindexfile)) {
|
||||
$shapeindex = create_shapeindex($shapeindexfile);
|
||||
} else {
|
||||
// check if shapeindex needs refresh (older than one day)
|
||||
if (time() - filemtime($shapeindexfile) > 86400) {
|
||||
$shapeindex = create_shapeindex($shapeindexfile);
|
||||
} else {
|
||||
// read svg metadata from existing file
|
||||
$json = file_get_contents($shapeindexfile);
|
||||
$shapeindex = json_decode($json, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
// some kind of error: just recreate
|
||||
$shapeindex = create_shapeindex($shapeindexfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $shapeindex;
|
||||
}
|
||||
|
||||
function svg_create_box($cx, $cy, $w, $h, $fg, $bg) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+287
-247
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -126,7 +126,7 @@ $sort = array(
|
||||
$w = array('m.vid=:vid');
|
||||
$p = array(':vid' => $user->vid);
|
||||
|
||||
if ($flt->equip == -1 or $flt->equip == 0) {
|
||||
if (isset($flt->equip) and ($flt->equip == -1 or $flt->equip == 0)) {
|
||||
$w[] = 'm.eid IS NULL';
|
||||
} elseif ($flt->equip > 0) {
|
||||
$w[] = 'm.eid=:eid';
|
||||
|
||||
+16
-2
@@ -72,6 +72,8 @@ switch ($submit = form_get_action()) {
|
||||
$p[':projname'] = gpc_get_string($_POST, 'projname');
|
||||
$p[':startdate'] = gpc_get_date($_POST, 'startdate');
|
||||
$p[':duration'] = gpc_get_int($_POST, 'duration');
|
||||
$p[':costs_plan'] = gpc_get_currency($_POST, 'costs_plan');
|
||||
$p[':costs_final'] = gpc_get_currency($_POST, 'costs_final');
|
||||
$p[':projstate'] = gpc_get_string($_POST, 'projstate');
|
||||
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||
db_exec_update('project', $p, 'projid');
|
||||
@@ -296,7 +298,8 @@ form_create_select('responsible', _('Responsible'), $opt_user, $project->respons
|
||||
elseif ($action == ACT_VIEW):
|
||||
// ========== VARIANT: view single record =====================================
|
||||
|
||||
$sql = "SELECT projname, startdate, duration, responsible, projstate, remarks "
|
||||
$sql = "SELECT projname, startdate, duration, responsible, projstate, "
|
||||
. " costs_plan, costs_final, remarks "
|
||||
. "FROM project "
|
||||
. "WHERE projid=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
@@ -308,6 +311,8 @@ echo '<tr><th scope="row" style="width:20%">', _('Name'),"</th><td>", $project->
|
||||
echo '<tr><th scope="row">', _('Responsible'),"</th><td>", $opt_user[$project->responsible], "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Start date'),"</th><td>", $project->startdate, "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Duration'),"</th><td>", $project->duration, "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Costs plan'),"</th><td>", format_currency($project->costs_plan), "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Costs final'),"</th><td>", format_currency($project->costs_final), "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('State'),"</th><td>", get_enum($project->projstate), "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Remarks'),"</th><td>", nl2br($project->remarks), "</td></tr>\n";
|
||||
echo "</table>\n";
|
||||
@@ -357,7 +362,8 @@ elseif ($action == ACT_EDIT):
|
||||
|
||||
echo '<h2>', _('Edit Project'), "</h2>\n";
|
||||
|
||||
$sql = "SELECT projname, responsible, startdate, duration, projstate, remarks "
|
||||
$sql = "SELECT projname, responsible, startdate, duration, projstate,"
|
||||
. " costs_plan, costs_final, remarks "
|
||||
. "FROM project "
|
||||
. "WHERE projid=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
@@ -382,6 +388,14 @@ form_create_select('responsible', _('Responsible'), $opt_user, $project->respons
|
||||
<label for="duration"><?=_('Duration, days')?></label>
|
||||
<input type="number" class="form-control" id="duration" name="duration" min="1" value="<?=$project->duration ?>">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="costs_plan" class="form-label"><?=sprintf(_('Costs planned, %s'), $g_lconv['currency_symbol']); ?></label>
|
||||
<input type="text" class="form-control" id="costs_plan" name="costs_plan" value="<?=format_float($project->costs_plan) ?>">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="costs_final" class="form-label"><?=sprintf(_('Costs final, %s'), $g_lconv['currency_symbol']); ?></label>
|
||||
<input type="text" class="form-control" id="costs_final" name="costs_final" value="<?=format_float($project->costs_final) ?>">
|
||||
</div>
|
||||
<?php
|
||||
form_create_select('projstate', _('Status'), $opt_state, $project->projstate);
|
||||
?>
|
||||
|
||||
@@ -39,6 +39,15 @@ switch ($submit = form_get_action()) {
|
||||
$p[':valstr'] = NULL;
|
||||
$p[':valint'] = gpc_get_int($_POST, 'rowspp');
|
||||
db_exec_update('settings', $p, $pk);
|
||||
$menu = [];
|
||||
for ($i = 1; $i <= 6; $i++) {
|
||||
$menu[] = gpc_get_uint($_POST, "menu$i", $i);
|
||||
}
|
||||
$p[':sno'] = 3; // user menu
|
||||
$p[':valint'] = NULL;
|
||||
$p[':valstr'] = implode(',', $menu);
|
||||
db_exec_update('settings', $p, $pk);
|
||||
$user->menu = $menu;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -99,6 +108,18 @@ $maximgy = $pdo->query("SELECT valint FROM settings WHERE userid=0 AND sno=21")-
|
||||
<form method="post" action="<?=$g_scriptname?>">
|
||||
<h2><?=_('for current user')?></h2>
|
||||
<?php
|
||||
|
||||
// menu configuration goes here
|
||||
$opt_modules = [];
|
||||
foreach ($g_modules as $mid => $module) {
|
||||
if ($module['type'] === 'primary') {
|
||||
$opt_modules[$mid] = $module['title'];
|
||||
}
|
||||
}
|
||||
for ($i = 1; $i <= 6; $i++) {
|
||||
form_create_select("menu$i", sprintf(_('Menu %d'), $i), $opt_modules, $user->menu[$i-1]);
|
||||
}
|
||||
|
||||
form_create_select('datefmt', _('Date format'), $opt_datefmt, $datefmt);
|
||||
?>
|
||||
<div class="mb-3">
|
||||
|
||||
Reference in New Issue
Block a user