diff --git a/INSTALL b/INSTALL
index be117b4..930b82f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -18,7 +18,7 @@ Yacht Management Software (YMS) Installation
1.3 Web GUI
- Webserver
-- PHP
+- PHP (>= 8.0)
- php-mysql
- php-xml
diff --git a/db/mariadb.sql b/db/mariadb.sql
index 7dfd123..129af98 100644
--- a/db/mariadb.sql
+++ b/db/mariadb.sql
@@ -159,7 +159,7 @@ CREATE TABLE inventory (
weight float(5,2) UNSIGNED DEFAULT NULL,
price decimal(12,2) DEFAULT NULL,
purchdate date DEFAULT NULL,
- invcond enum('unknown','new','good','normal','bad','repairable','defect') NOT NULL default 'unknown',
+ invcond enum('unknown','excellent','good','fair','bad','repairable','defect') NOT NULL default 'unknown',
remarks varchar(150) DEFAULT NULL,
PRIMARY KEY (invid),
INDEX ix_invname (invname)
@@ -178,7 +178,7 @@ CREATE TABLE cable (
color char(6) DEFAULT NULL,
supplier smallint(6) DEFAULT NULL,
manufacturer smallint(6) DEFAULT NULL,
- cablecond enum('unknown','new','good','normal','bad','repairable','defect') NOT NULL default 'unknown',
+ cablecond enum('unknown','new','excellent','good','fair','bad','repairable','defect') NOT NULL default 'unknown',
remarks varchar(150) DEFAULT NULL,
PRIMARY KEY (cableid),
INDEX ix_cablename (vid, cablename)
@@ -222,11 +222,13 @@ CREATE TABLE provisions (
sid smallint(6) UNSIGNED DEFAULT NULL,
boxid smallint(6) UNSIGNED NOT NULL DEFAULT 1,
number smallint(6) UNSIGNED NOT NULL DEFAULT 1,
+ target smallint(6) UNSIGNED DEFAULT NULL, -- for shopping list
weight float(5,2) UNSIGNED DEFAULT NULL,
weight_net float(5,2) UNSIGNED DEFAULT NULL,
unit tinyint(3) DEFAULT NULL,
storedate date DEFAULT CURRENT_DATE,
shelflife date DEFAULT NULL,
+ remarks varchar(150) DEFAULT NULL,
PRIMARY KEY (provid)
) ENGINE=InnoDB;
@@ -283,6 +285,7 @@ CREATE TABLE company (
customerno varchar(20),
contractno varchar(20),
remarks varchar(150) DEFAULT NULL,
+ flags set('deleted','historic') DEFAULT NULL,
PRIMARY KEY (compid),
UNIQUE INDEX ix_compname (compname, comptype)
) ENGINE=InnoDB;
diff --git a/webgui/box.php b/webgui/box.php
index ec65943..bdf6437 100644
--- a/webgui/box.php
+++ b/webgui/box.php
@@ -171,6 +171,11 @@ $box = $sth->fetch(PDO::FETCH_OBJ);
echo '
', $box->label, "
\n";
+// Bootstrap grid
+echo '';
+echo '
';
+echo '
';
+
echo '
', "\n";
echo '| ', _('Box type')," | ", ($opt_boxtype[$box->boxtype] ?? ''), " |
\n";
echo '| ', _('Content')," | ", $box->content, " |
\n";
@@ -184,6 +189,46 @@ echo "
\n";
form_view_buttons($g_scriptname, $id);
+echo '
'; // Column break
+echo '
', "\n";
+
+echo '
', "\n";
+echo '\n";
+echo '
', "\n";
+
+$sql = "SELECT d.docid, d.title "
+ . "FROM docref AS r INNER JOIN document AS d using (docid) "
+ . "WHERE d.doctype='picture' AND r.reftype='box' AND r.refid=? "
+ . "ORDER BY d.title";
+$sth = $pdo->prepare($sql);
+$sth->execute([$id]);
+$res = $sth->fetchAll();
+// TODO hübsche Darstellung
+$doccount = 0;
+foreach ($res as $row) {
+ $doccount += 1;
+ echo '
\n"; // card-body
+echo "
\n"; // card
+
+echo '
'; // col
+echo '
'; // row
+echo '
'; // container
+
// Inventory in box
// WIP
$sql = "SELECT invid, invname, weight, number FROM inventory WHERE conttype='box' AND boxid=?";
diff --git a/webgui/company.php b/webgui/company.php
index 350db6e..0aa05ab 100644
--- a/webgui/company.php
+++ b/webgui/company.php
@@ -63,6 +63,8 @@ switch ($submit = form_get_action()) {
$p[':customerno'] = gpc_get_string($_POST, 'customerno', 20);
$p[':contractno'] = gpc_get_string($_POST, 'contractno', 20);
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
+ $allowed = db_load_enum('company', 'flags');
+ $p[':flags'] = gpc_get_set($_POST, 'flags', $allowed, true, NULL);
db_exec_update('company', $p, 'compid');
$action = ACT_VIEW;
break;
@@ -136,7 +138,7 @@ $page = gpc_get_int($_REQUEST, 'p', 1);
$rows_pp = gpc_get_int($_REQUEST, 'n', $user->rows_pp);
$lastpage = ceil($numrows/$rows_pp);
-$sql = "SELECT compid, compname, comptype, remarks "
+$sql = "SELECT compid, compname, comptype, remarks, flags "
. "FROM company";
if ($where) $sql .= ' WHERE ' . $where;
$sql .= $order;
@@ -212,6 +214,14 @@ foreach ($res as $row) {
echo "
\n";
echo '| ', $i;
echo '', "\n";
+ // icons for some flags
+ $flags = explode(',', $row['flags']);
+ if (in_array('historic', $flags)) {
+ echo '';
+ }
+ if (in_array('deleted', $flags)) {
+ echo '';
+ }
echo " | \n";
echo "", $row['compname'], " | \n";
echo "", $opt_comptype[$row['comptype']], " | \n";
@@ -251,7 +261,7 @@ elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$sql = "SELECT compname, comptype, comptype2, shortname, street, zip, city,"
- . " country, contact, phone, email, web, customerno, contractno, remarks "
+ . " country, contact, phone, email, web, customerno, contractno, remarks, flags "
. "FROM company "
. "WHERE compid=?";
$sth = $pdo->prepare($sql);
@@ -283,6 +293,7 @@ echo make_weblink($company->web), ' ', $company->web, "
\n";
echo '
| ', _('Customer no.')," | ", $company->customerno, " |
|---|
\n";
echo '
| ', _('Contract no.')," | ", $company->contractno, " |
|---|
\n";
echo '
| ', _('Remarks')," | ", $company->remarks, " |
|---|
\n";
+echo '
| ', _('Flags')," | ", $company->flags, " |
|---|
\n";
echo "\n";
form_view_buttons($g_scriptname, $id);
@@ -330,7 +341,7 @@ elseif ($action == ACT_EDIT):
echo '
', _('Edit Company'), "
\n";
$sql = "SELECT compname, comptype, comptype2, street, zip, city, country,"
- . " contact, phone, email, web, customerno, contractno, remarks "
+ . " contact, phone, email, web, customerno, contractno, remarks, flags "
. "FROM company "
. "WHERE compid=?";
$sth = $pdo->prepare($sql);
@@ -409,6 +420,10 @@ form_create_select('comptype2', _('Secondary company type'), $g_opt_none + $opt_
+flags));
+?>
=_('Back')?>
diff --git a/webgui/documents.php b/webgui/documents.php
index d7156c3..4eb8de2 100644
--- a/webgui/documents.php
+++ b/webgui/documents.php
@@ -6,6 +6,14 @@
* SPDX-License-Identifier: WTFPL
******************************************************************************/
+/*
+doctype icons
+ generic: file-earmark
+ image: file-earmark-image
+ drawing: file-earmark-easel
+ pdf: file-earmark-pdf
+*/
+
require 'globals.inc';
require 'lib/gpc.inc';
require 'lib/fileutils.inc';
@@ -143,6 +151,12 @@ switch ($submit = form_get_action()) {
break;
case 'delete':
+ // check user rights
+ if ($user->role == ROLE_SAILOR) {
+ $g_error->Add(_('User level allows no deletion!'));
+ $action = ACT_VIEW;
+ break;
+ }
// Security token needed!
if (gpc_get_string($_POST, 'token', 16) != $_SESSION['token']) {
$g_error->Add(_('Delete prohibited, invalid security token!'));
@@ -189,21 +203,18 @@ switch ($submit = form_get_action()) {
$p[':docid'] = $id;
$p[':refid'] = gpc_get_int($_POST, 'refid');
$p[':reftype'] = gpc_get_enum($_POST, 'reftype', $opt_reftype, 'equipment');
- /* $sql = "INSERT INTO docref "
- . " (docid, refid, reftype) "
- . "VALUES "
- . " (:docid, :refid, :reftype)";
- $sth = $pdo->prepare($sql);
- $sth->bindValue(':docid', $id, PDO::PARAM_INT);
- $sth->bindValue(':refid', $refid, PDO::PARAM_INT);
- $sth->bindValue(':reftype', $reftype, PDO::PARAM_STR);
- $sth->execute(); */
db_exec_insert('docref', $p);
$action = ACT_VIEW;
break;
case 'delref':
// remove only link, not critical so get without token is ok
+ // check user rights
+ if ($user->role == ROLE_SAILOR) {
+ $g_error->Add(_('User level allows no deletion!'));
+ $action = ACT_VIEW;
+ break;
+ }
$drid = gpc_get_int($_GET, 'drid');
$sql = "DELETE FROM docref WHERE drid=?";
$sth = $pdo->prepare($sql);
@@ -582,6 +593,18 @@ foreach ($sth->fetchAll() as $row) {
$compids[] = $row['refid'];
}
+// Boxes
+$boxids = array();
+$sql = "SELECT drid, reftype, refid, CONCAT_WS(' - ', label, NULLIF(content, '')) AS target "
+ . "FROM docref INNER JOIN box ON (docref.reftype='box' AND docref.refid=box.boxid) "
+ . "WHERE docid=?";
+$sth = $pdo->prepare($sql);
+$sth->execute([$id]);
+foreach ($sth->fetchAll() as $row) {
+ $references[] = $row;
+ $boxids[] = $row['refid'];
+}
+
echo '', "\n";
echo "\n";
echo "";
@@ -600,6 +623,8 @@ foreach ($references as $ref) {
echo '';
} elseif ($ref['reftype'] == 'company') {
echo '';
+ } elseif ($ref['reftype'] == 'box') {
+ echo '';
}
echo "";
echo "| ", get_enum($ref['reftype']), " | ";
@@ -616,18 +641,12 @@ echo '', _('Add new reference'), "
\n";
// enum('vessel','box','equipment','project','task','user','company')
//
+// Reference options
+$opt_reference = db_load_enum('docref', 'reftype', lookup:true, as_dict:true);
// Equipment options
// Do not include equipment that has already been referenced in the list!
-$opt_equipment = array();
-$sql = "SELECT eid, ename FROM equipment WHERE vid=? ORDER BY ename";
-$sth = $pdo->prepare($sql);
-$sth->execute([$user->vid]);
-foreach ($sth->fetchAll() as $row) {
- if (!in_array($row['eid'], $eids)) {
- $opt_equipment[$row['eid']] = $row['ename'];
- }
-}
+$opt_equipment = db_get_opt_equip($user->vid, exclude:$eids)
?>
+vid, exclude:$boxids)
+?>
+
\n";
echo "", $i;
echo '', "\n";
+ // icons for some flags
+ $flags = explode(',', $row['flags']);
+ if (in_array('ordered', $flags)) {
+ echo '';
+ }
+ if (in_array('deleted', $flags)) {
+ echo '';
+ }
+ if (in_array('removed', $flags)) {
+ echo '';
+ }
echo " | \n";
echo "", $row['ename'], " | \n";
echo "", ($opt_manufacturer[$row['manufacturer']] ?? ''), " | \n";
@@ -624,7 +637,7 @@ foreach ($sth->fetchAll() as $row) {
}
$sql = "SELECT eid, ename, model, serial, weight, price, purchdate,"
- . " supplier, manufacturer, ecat, shortname, remarks "
+ . " supplier, manufacturer, ecat, shortname, remarks, flags "
. "FROM equipment "
. "WHERE eid=?";
$sth = $pdo->prepare($sql);
@@ -671,6 +684,10 @@ form_create_select('category', _('Category'), $g_opt_unknown + $opt_ecat, $equip
+flags));
+?>
=_('Back')?>
diff --git a/webgui/globals.inc b/webgui/globals.inc
index 49d8ddc..5d98c32 100644
--- a/webgui/globals.inc
+++ b/webgui/globals.inc
@@ -39,6 +39,11 @@ define ('ACT_UNLINK', 11);
define ('ACT_MAIL', 12);
define ('ACT_VIEW_LIST', 13);
+define('ROLE_VESSEL', 'vessel');
+define('ROLE_CAPTAIN', 'captain');
+define('ROLE_HELMSMAN', 'helmsman');
+define('ROLE_SAILOR', 'sailor');
+
// ========== PAGE START CODE =================================================
// global version string
@@ -396,8 +401,8 @@ function db_exec_insert($table, $params) {
global $pdo;
global $g_error;
$keys = array_keys($params);
- $fields = join(',', array_map(function($s) { return ltrim($s, ':'); }, $keys));
- $pnames = join(',', $keys);
+ $fields = join(', ', array_map(function($s) { return ltrim($s, ':'); }, $keys));
+ $pnames = join(', ', $keys);
$sql = "INSERT INTO $table ($fields) VALUES ($pnames)";
// $sth = $pdo->prepare("INSERT INTO $table ($fields) VALUES ($pnames)");
$sth = $pdo->prepare($sql);
@@ -433,7 +438,7 @@ function db_exec_update($table, $params, $pk) {
unset($fields[':'.$pk]);
$where = "$pk=:$pk";
}
- $fieldlist = join(',', array_map(fn($s) => ltrim($s, ':') . '=' . $s, array_keys($fields)));
+ $fieldlist = join(', ', array_map(fn($s) => ltrim($s, ':') . '=' . $s, array_keys($fields)));
$sql = "UPDATE $table SET $fieldlist WHERE $where";
$sth = $pdo->prepare($sql);
try {
@@ -526,12 +531,15 @@ function get_enum($enum) {
'drawing' => _('Drawing'),
'equipment' => _('Equipment'),
'estimated' => _('Estimated'),
+ 'excellent' => _('Excellent'),
+ 'fair' => _('Fair'),
'finished' => _('Finished'),
'fixed' => _('Fixed'),
'fuse' => _('Fuse'),
'generic' => _('Generic'),
'good' => _('Good'),
'high' => _('High'),
+ 'historic' => _('Historic'),
'invoice' => _('Invoice'),
'locked' => _('Locked'),
'low' => _('Low'),
@@ -806,7 +814,7 @@ function db_get_opt_storage($vid) {
return $list;
}
-function db_get_opt_box($vid) {
+function db_get_opt_box($vid, $exclude=[]) {
global $pdo;
global $g_error;
$list = array();
@@ -821,12 +829,14 @@ function db_get_opt_box($vid) {
$g_error->Add($e->getMessage());
}
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
- $list[$rec[0]] = $rec[1] . ' - '. $rec[2];
+ if (! in_array($rec[0], $exclude)) {
+ $list[$rec[0]] = $rec[1] . ($rec[2] ? ' - '. $rec[2] : '');
+ }
}
return $list;
}
-function db_get_opt_equip($vid, $default=NULL) {
+function db_get_opt_equip($vid, $default=NULL, $exclude=[]) {
global $pdo;
global $g_error;
if (isset($default)) {
@@ -842,7 +852,9 @@ function db_get_opt_equip($vid, $default=NULL) {
$g_error->Add($e->getMessage());
}
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
- $list[$rec[0]] = $rec[1];
+ if (! in_array($rec[0], $exclude)) {
+ $list[$rec[0]] = $rec[1];
+ }
}
return $list;
}
@@ -1050,11 +1062,21 @@ function form_create_select($fieldname, $label, $optlist, $selval=NULL, $multipl
echo "\n";
}
-function form_create_checks($fieldname, $label, $optlist, $selected) {
- echo '', "\n";
- echo '\n";
- print_r($optlist);
- echo "
\n";
+function form_create_checks($fieldname, $label, $optlist, $selected = []) {
+ echo '';
}
// TODO DEPRECATED for touch multiple adjacent buttuns are not well suited.
@@ -1418,7 +1440,7 @@ function make_weblink($dest) {
} elseif (!in_array($scheme, ['http', 'https'], true)) {
return '';
}
- return '';
+ return '';
}
function make_maillink($dest) {
diff --git a/webgui/img/pwa-192.png b/webgui/img/pwa-192.png
new file mode 100644
index 0000000..9429b13
Binary files /dev/null and b/webgui/img/pwa-192.png differ
diff --git a/webgui/img/pwa-512.png b/webgui/img/pwa-512.png
new file mode 100644
index 0000000..85175f1
Binary files /dev/null and b/webgui/img/pwa-512.png differ
diff --git a/webgui/index.php b/webgui/index.php
index 1767ded..3e0222a 100644
--- a/webgui/index.php
+++ b/webgui/index.php
@@ -242,7 +242,11 @@ if (isset($vessel->loa)) {
$h = round($row['wy'] * $f);
$x = round($row['x'] * $f - $w / 2.0);
$y = round($row['y'] * $f + $shape['height'] / 2.0 - $h / 2.0);
- $rect = $g->addChild('rect');
+
+ $a = $g->addChild('a');
+ $a->addAttribute('href', 'storage.php?f=view&id=' . $row['sid']);
+
+ $rect = $a->addChild('rect');
$rect->addChild('title', $row['sname']);
$rect->addAttribute('x', $x);
$rect->addAttribute('y', $y);
diff --git a/webgui/inventory.php b/webgui/inventory.php
index 0a4ae2b..8888bc8 100644
--- a/webgui/inventory.php
+++ b/webgui/inventory.php
@@ -121,7 +121,7 @@ if ($action == ACT_DEFAULT):
page_caption_search($pagetitle);
-$flt = db_get_filter($user->id, 201, ['cond','name','txt']);
+$flt = db_get_filter($user->id, 201, ['stor', 'cond','txt']);
/*
The only way to find out whether the inventory is on the current boat is to use
@@ -301,7 +301,7 @@ echo '', _('Add Inventory'), "
\n";