Webgui: More mobile friendly touch and much more improvements

This commit is contained in:
2026-06-14 10:56:17 +02:00
parent a59f02e21b
commit f109e2621f
25 changed files with 1624 additions and 583 deletions
+3
View File
@@ -3,3 +3,6 @@ Prototype
Many features are incomplete, buggy or missing.
Use at your own risk!
If inserting a new user you have also to insert a setting value
to assign boat 0.
+24 -5
View File
@@ -8,7 +8,7 @@ CREATE TABLE user (
login varchar(20) NOT NULL,
pass binary(60) NOT NULL,
displayname varchar(100) NOT NULL,
role set('vessel', 'captain','helmsman','sailor') NOT NULL DEFAULT 'sailor',
role enum('vessel','captain','helmsman','sailor') NOT NULL DEFAULT 'sailor',
flags set('deleted','locked'),
language char(2) NOT NULL DEFAULT 'en',
PRIMARY KEY (userid),
@@ -84,6 +84,8 @@ CREATE TABLE storage (
wx smallint(6) UNSIGNED NOT NULL DEFAULT 0,
wy smallint(6) UNSIGNED NOT NULL DEFAULT 0,
wz smallint(6) UNSIGNED NOT NULL DEFAULT 0,
angle smallint(4) NOT NULL DEFAULT 0,
color char(6) DEFAULT NULL,
remarks varchar(150) DEFAULT NULL,
PRIMARY KEY (sid)
);
@@ -137,7 +139,7 @@ CREATE TABLE equipment (
price decimal(12,2) DEFAULT NULL,
weight float(5,2) UNSIGNED DEFAULT NULL,
remarks varchar(150) DEFAULT NULL,
flags set('ordered','deleted') DEFAULT NULL,
flags set('ordered','removed','deleted') DEFAULT NULL,
PRIMARY KEY(eid)
);
@@ -157,9 +159,12 @@ CREATE TABLE inventory (
PRIMARY KEY (invid),
INDEX ix_invname (invname)
);
/*
TODO: unit -> unit1, unit2, unit3
*/
CREATE TABLE measurement (
mid smallint(6) NOT NULL AUTO_INCREMENT,
mtype enum('generic','cable','fuse') NOT NULL default 'generic',
mname varchar(80) NOT NULL,
nval tinyint(1) UNSIGNED NOT NULL DEFAULT 1,
val1 int(10) NOT NULL,
@@ -178,7 +183,10 @@ CREATE TABLE provisions (
provname varchar(40) NOT NULL,
provcat tinyint(3) DEFAULT NULL,
sid smallint(6) DEFAULT NULL,
boxid smallint(6) NOT NULL DEFAULT 1,
number smallint(6) UNSIGNED NOT NULL DEFAULT 1,
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,
@@ -197,6 +205,7 @@ CREATE TABLE document (
title varchar(40) DEFAULT NULL,
pages smallint(6) unsigned NOT NULL DEFAULT 1,
remarks varchar(150) DEFAULT NULL,
roleaccess enum('captain','helmsman','sailor','unauth') NOT NULL DEFAULT 'captain',
PRIMARY KEY (docid),
UNIQUE INDEX ix_hash (hash)
) ENGINE=InnoDB;
@@ -270,7 +279,8 @@ CREATE TABLE task (
projid smallint(6) DEFAULT NULL,
taskname varchar(60) NOT NULL,
priority enum('high','medium','low') DEFAULT NULL,
taskstate enum('pending','waiting','deleted','completed') NOT NULL DEFAULT 'pending',
taskstate enum('pending','active','waiting','deleted','completed') NOT NULL DEFAULT 'pending',
state_ts timestamp DEFAULT NULL,
plandate date DEFAULT NULL,
duedate date DEFAULT NULL,
started datetime DEFAULT NULL,
@@ -280,9 +290,10 @@ CREATE TABLE task (
PRIMARY KEY (taskid)
);
// Notes can be assigned to tasks,maintenances and equipment
CREATE TABLE note (
noteid int(10) NOT NULL AUTO_INCREMENT,
notetype enum('task','maint') NOT NULL DEFAULT 'task',
notetype enum('task','maint','equip') NOT NULL DEFAULT 'task',
refid smallint(6) NOT NULL,
annotation text NOT NULL,
PRIMARY KEY (noteid)
@@ -291,6 +302,7 @@ CREATE TABLE note (
CREATE TABLE checklist (
clid smallint(6) NOT NULL AUTO_INCREMENT,
title varchar(30) NOT NULL,
parent smallint(6) DEFAULT NULL,
clstate enum('new','open','closed') NOT NULL DEFAULT 'new',
PRIMARY KEY (clid)
);
@@ -299,6 +311,7 @@ CREATE TABLE checkitem (
checkid int(10) NOT NULL AUTO_INCREMENT,
checkname varchar(60) NOT NULL,
groupid tinyint(3) DEFAULT NULL,
checkresult enum('unchecked','checked','unused') NOT NULL DEFAULT 'unused',
PRIMARY KEY (checkid)
);
@@ -308,3 +321,9 @@ CREATE TABLE checkref (
sort smallint(6) DEFAULT NULL,
PRIMARY KEY (clid, checkid)
);
CREATE TABLE checkgroup (
groupid int(10) NOT NULL,
title varchar(30) NOT NULL,
PRIMARY KEY (groupid)
);
+9 -3
View File
@@ -12,13 +12,19 @@ INSERT INTO user (userid, login, pass, displayname, role) VALUES
(1, 'captain', '$2y$10$naVMnC4S6bZ3IakxLJPJK.iSazlkYxVLeiRt9CB/j0jSExQZU1SCK', 'Captain', 'captain');
INSERT INTO settings (userid, sno, valint) VALUES
(0, 0, 1), -- Databankschema-Version
(0, 1, 0), -- Keine Bootszuordnung für SYSTEM
(1, 1, 0); -- Keine Bootszuordnung für Benutzer "captain"
(0, 0, 1), -- Database schema version
(0, 1, 0), -- No vessel assignment to SYSTEM
(1, 1, 0), -- No vessel assignment to user "captain"
(0, 20, 1280), -- Image width limit
(0, 21, 1024); -- Image height limit
/* setting descriptions */
INSERT INTO settings (userid, sno, valstr) VALUES
(-1, 1, 'vessel id'),
(-1, 2, 'date format'),
(-1, 10, 'rows in table'),
(-1, 20, 'maximum image width'),
(-1, 21, 'maximum image height'),
(-1, 100, 'equipment sorting order'),
(-1, 101, 'inventory sorting order'),
(-1, 102, 'provision sorting order'),
+37 -15
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: YMS 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-15 09:05+0200\n"
"POT-Creation-Date: 2026-05-07 11:50+0200\n"
"PO-Revision-Date: 2025-05-15 09:05+0200\n"
"Last-Translator: Thomas Hooge <thomas@hoogi.de>\n"
"Language-Team: de <thomas@hoogi.de>\n"
@@ -16,11 +16,11 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: ymsgui.py:98
#: ymsgui.py:150
msgid "Configuration file not found"
msgstr "Konfigurationsdatei nicht gefunden"
#: ymsgui.py:110
#: ymsgui.py:172
msgid "Database connection cannot be established"
msgstr "Datenbankverbindung kann nicht hergestellt werden"
@@ -28,46 +28,68 @@ msgstr "Datenbankverbindung kann nicht hergestellt werden"
msgid "YMS"
msgstr ""
#: yms/ui/main.ui:27
#: yms/ui/main.ui:28
msgid "empty"
msgstr "leer"
#: yms/ui/main.ui:55
#: yms/ui/main.ui:56
msgid "Name"
msgstr ""
#: yms/ui/main.ui:76
#: yms/ui/main.ui:77
msgid "Model"
msgstr "Modell"
#: yms/ui/main.ui:109
#: yms/ui/main.ui:119
msgid "Vessel"
msgstr "Boot"
#: yms/ui/main.ui:138
#: yms/ui/main.ui:148
msgid "Lists"
msgstr "Listen"
#: yms/ui/main.ui:173
#: yms/ui/main.ui:186
msgid "Ok"
msgstr ""
#: yms/ui/main.ui:194
#: yms/ui/main.ui:207
msgid "User"
msgstr "Benutzer"
#: yms/ui/main.ui:207
#: yms/ui/main.ui:220
msgid "Base data"
msgstr "Basisdaten"
#: yms/ui/main.ui:217 yms/ui/main.ui:238
msgid "label"
#: yms/ui/main.ui:230
msgid ""
"Equipment\n"
"Here be dragons"
msgstr ""
#: yms/ui/main.ui:227
#: yms/ui/main.ui:241
msgid "Equipment"
msgstr "Ausrüstung"
#: yms/ui/main.ui:248
#: yms/ui/main.ui:252
msgid "label"
msgstr ""
#: yms/ui/main.ui:262
msgid "Inventory"
msgstr "Inventar"
#: yms/ui/main.ui:292
msgid "Provisions"
msgstr "Verpflegung"
#: yms/ui/main.ui:322
msgid "Maintenance"
msgstr "Wartung"
#: yms/ui/main.ui:352
msgid "Projects"
msgstr "Projekte"
#: yms/ui/main.ui:382
msgid "Documents"
msgstr "Dokumente"
+24 -8
View File
@@ -1,11 +1,18 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024 Thomas Hooge
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************/
/*
Box weight can be entered directly and is meant as weight of box itself plus
weights of contained items.
The weight of the contained items can be displayed separately
There can be a difference because not all items have a weight entered
*/
require 'globals.inc';
$pagetitle = _('Boxes');
@@ -79,21 +86,30 @@ $res = $sth->fetchAll();
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>";
echo "<th>" . _('Label') . "</th>";
echo "<th>" . _('Type') . "</th>";
echo "<th>" . _('Color') . "</th>";
echo "<th>" . _('Content') . "</th>";
echo '<th>#</th>';
echo "<th>", _('Label'), "</th>";
echo "<th>", _('Type'), "</th>";
echo "<th>", _('Color'), "</th>";
echo "<th>", _('Content'), "</th>";
echo '<th class="text-end">', _('Weight'), "</th>";
echo "<td></td>";
echo "</tr>\n";
$i = 0;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo '<td>', $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['boxid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo '<td>', $row['label'], "</td>\n";
echo '<td>', ($opt_boxtype[$row['boxtype']] ?? ''), "</td>\n";
echo '<td>', format_color(strtoupper($row['color'])), "</td>\n";
echo '<td>', $row['content'], "</td>\n";
echo '<td class="text-end">', format_float($row['weight'], 2), "</td>\n";
form_action_buttons($g_scriptname, $row['boxid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['boxid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
@@ -110,7 +126,7 @@ elseif ($action == ACT_ADD):
echo '<h2>', _('Add Box'), "</h2>\n";
?>
<form method="post" action="<?=$g_Scriptname?>">
<form method="post" action="<?=$g_scriptname?>">
<div class="mb-3">
<label for="label" class="form-label"><?=_('Label')?></label>
<input type="text" maxlength="20" class="form-control" id="label" name="label" autofocus>
@@ -143,7 +159,7 @@ foreach ($opt_storage as $k => $v) {
elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$sql = "SELECT boxtype, label, content, color, weight, box.remarks, box.sid, sname "
$sql = "SELECT boxtype, label, content, box.color, weight, box.remarks, box.sid, sname "
. "FROM box LEFT JOIN storage USING (sid) "
. "WHERE boxid=?";
$sth = $pdo->prepare($sql);
+7
View File
@@ -127,6 +127,13 @@ $checklist = $sth->fetch(PDO::FETCH_OBJ);
</table>
<?php
/*
$sql = "SELECT checkname, groupid FROM checkitem";
$sql = "SELECT clid, checkid, sort FROM checkref";
*/
form_view_buttons($g_scriptname, $id);
elseif ($action == ACT_EDIT):
+16 -8
View File
@@ -126,10 +126,12 @@ try {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$numrows = $sth->fetchColumn();
$lastpage = ceil($numrows/$g_rows_pp);
$page = gpc_get_int($_REQUEST, 'p', 1);
$rows_pp = gpc_get_int($_REQUEST, 'n', $g_rows_pp);
$lastpage = ceil($numrows/$rows_pp);
$sql = "SELECT compid, compname, comptype, remarks "
. "FROM company";
@@ -156,7 +158,7 @@ $opt_special = array(
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body">
<label for="flt_type">Type</label>
<select id="flt_type" name="flt_type">
@@ -187,27 +189,33 @@ echo $pagination;
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>";
echo '<th>#</th>';
echo "<th>" . _('Name') . "</th>";
echo "<th>" . _('Type') . "</th>";
echo "<th>" . _('Remarks') . "</th>";
echo "<th>&nbsp;</th>";
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo "<td>". $row['compname'] ."</td>\n";
echo "<td>". $opt_comptype[$row['comptype']] ."</td>\n";
echo "<td>". $row['remarks'] ."</td>\n";
// Action buttons
echo '<td>', $i;
echo '<a title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['compid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>", $row['compname'], "</td>\n";
echo "<td>", $opt_comptype[$row['comptype']], "</td>\n";
echo "<td>", $row['remarks'], "</td>\n";
// Edit current record button
echo "<td>";
echo '<a title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['compid'], '"><i class="bi-eye"></i></a>', "\n";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['compid'], '"><i class="bi-pencil"></i></a>';
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
echo "<tfoot>\n";
echo '<tr><td colspan="6">', sprintf(_('%d records out of total %d'), count($res), $grandtotal), '</td></tr>', "\n";
echo '<tr><td colspan="6">', sprintf(_('Records %d to %d of %d'), $i0, $i, $numrows), '</td></tr>', "\n";
echo "</tfoot>\n";
echo "</table>\n";
+1 -1
View File
@@ -7,7 +7,7 @@
******************************************************************************/
/* Document Downloader
Doucuments are not directly accessible via filesystem
Documents are not directly accessible via filesystem
dl.php must be used with "docid" as parameter: e.g, dl.php?id=23
In additional parameter "t" (thumb) is set a thumbnail will be returned
Possible values are: s (small), m (medium), l (large)
+42 -12
View File
@@ -1,7 +1,7 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024-2025 Thomas Hooge
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************/
@@ -222,6 +222,8 @@ page_caption_search($pagetitle);
$flt = db_get_filter($user->id, 209);
// $w = array('(vid=:vid OR vid IS NULL)');
// $p = array(':vid' => $user->vid);
$w = array();
$p = array();
if (isset($flt->doctype) and $flt->doctype != 'all') {
@@ -244,8 +246,28 @@ if (strlen($flt->txt) > 1) {
$where = join(' AND ', $w);
$order = ' ORDER BY docid';
/*
WIP
Attention: Do not count duplicate, so first select docid from different sources
an as laststep get a distinct list of docids to count.
Documents with no reference at all
SELECT docid FROM document LEFT OUTER JOIN docref USING (docid) WHERE docref.drid IS NULL;
Documents for current vessel
SELECT docid FROM document LEFT OUTER JOIN docref USING (docid) WHERE docref.reftype='vessel' AND docref.refid=:vid
Documents for equipment in current vessel
SELECT DISTINCT d.docid AS docid FROM document AS d
LEFT OUTER JOIN docref AS r USING (docid) LEFT OUTER JOIN equipment AS e ON (r.refid=e.eid)
WHERE r.reftype='equipment' AND e.vid=:vid
*/
// get total recond count for pagination and limit
$sql = "SELECT COUNT(*) FROM document LEFT OUTER JOIN docref USING (docid)";
$sql = "SELECT COUNT(DISTINCT docid) FROM document LEFT OUTER JOIN docref USING (docid)";
if ($where) $sql .= ' WHERE ' . $where;
$sth = $pdo->prepare($sql);
try {
@@ -254,10 +276,12 @@ try {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$numrows = $sth->fetchColumn();
$lastpage = ceil($numrows/$g_rows_pp);
$page = gpc_get_int($_REQUEST, 'p', 1);
$rows_pp = gpc_get_int($_REQUEST, 'n', $g_rows_pp);
$lastpage = ceil($numrows/$rows_pp);
$sql = "SELECT d.docid, d.doctype, d.filename, d.title, COUNT(r.drid) AS refcount "
. "FROM document AS d LEFT OUTER JOIN docref AS r USING (docid)";
@@ -279,7 +303,7 @@ $opt_special = array(
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body">
<label for="flt_doctype">Type</label>
<select id="flt_doctype" name="flt_doctype">
@@ -323,7 +347,7 @@ echo $pagination;
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>";
echo "<th>", _('ID'), "</th>";
echo '<th>#</th>';
echo "<th>", _('Type'), "</th>";
echo "<th>", _('Filename'), "</th>";
echo "<th>", _('Title'), "</th>";
@@ -331,23 +355,28 @@ echo "<th>", _('Links'), "</th>";
echo "<th>&nbsp;</th>";
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo "<td>", $row['docid'], "</td>\n";
echo "<td>", $i;
echo '<a title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['docid'], '"><i class="bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>", $opt_doctype[$row['doctype']], "</td>\n";
echo "<td>", $row['filename'], "</td>\n";
echo "<td>", $row['title'], "</td>\n";
echo "<td>", $row['refcount'], "</td>\n";
// Action buttons
// Edit current record button
echo "<td>";
echo '<a title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['docid'], '"><i class="bi-eye"></i></a>', "\n";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['docid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
echo "<tfoot>\n";
echo '<tr><td colspan="6">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
echo '<tr><td colspan="6">', sprintf(_('Records %d to %d of %d'), $i0, $i, $numrows), '</td></tr>', "\n";
echo "</tfoot>\n";
echo "</table>\n";
@@ -402,7 +431,7 @@ elseif ($action == ACT_VIEW):
/* mutool: preview of page thumbs */
$sql = "SELECT docid, doctype, mimetype, filename, extension, hash,"
. " docsize, doctime, title, pages, remarks "
. " docsize, doctime, title, pages, remarks, roleaccess "
. "FROM document "
. "WHERE docid=?";
$sth = $pdo->prepare($sql);
@@ -428,13 +457,14 @@ if ($document->doctype == 'picture') {
echo '</div>'; // gallery
?>
<div class="modal fade" id="imageModal" tabindex="-1" aria-labelledby="imageModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-dialog modal-dialog-centered custom-image-modal">
<div class="modal-content">
<div class="modal-header">
<?=$document->title;?>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<img src="dl.php?id=<?=$document->docid ?>">
<img src="dl.php?id=<?=$document->docid ?>" class="preview-image">
</div>
</div>
</div>
+64 -18
View File
@@ -1,7 +1,7 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024, 2025 Thomas Hooge
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************/
@@ -222,6 +222,9 @@ if (strlen($flt->txt) > 1) {
$w[] = '(ename LIKE :txt OR model LIKE :txt OR remarks LIKE :txt)';
$p[':txt'] = '%'.$flt->txt.'%';
}
// TODO flags (ordered, removed, deleted)
// if (strlen($flt->flags) > 0) {
// }
$where = join(' AND ', $w);
$order = ' ORDER BY ename';
@@ -233,19 +236,22 @@ try {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$numrows = $sth->fetchColumn();
$lastpage = ceil($numrows/$g_rows_pp);
$page = gpc_get_int($_REQUEST, 'p', 1);
// TODO check against allowed values for rows per page
$rows_pp = gpc_get_int($_REQUEST, 'n', $g_rows_pp);
$sql = "SELECT eid, ename, manufacturer, model, serial, remarks,"
$sql = "SELECT eid, ename, manufacturer, model, serial, remarks, flags,"
. " TIMESTAMPDIFF(MONTH, purchdate, NOW()) AS age_mon "
. "FROM equipment";
$sql .= ' WHERE ' . $where;
$sql .= $order;
// if pagination:
$sql .= ' LIMIT ' . ($page - 1) * $g_rows_pp . ',' . $g_rows_pp;
$sql .= ' LIMIT ' . ($page - 1) * $rows_pp . ',' . $rows_pp;
$sth = $pdo->prepare($sql);
$sth->execute($p);
@@ -260,15 +266,25 @@ $opt_none_male = array(-1 => pgettext('male', '&horbar; none &horbar;'));
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-body">
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body d-flex flex-wrap gap-3">
<?php
filter_create_select('flt_category', _('Category'), $g_opt_all + $g_opt_none + $opt_ecat, $flt->cat);
filter_create_select('flt_manuf', _('Manufacturer'), $g_opt_all + $opt_none_male + $opt_manufacturer, $flt->manuf);
filter_create_select('flt_supp', _('Supplier'), $g_opt_all + $opt_none_male + $opt_supplier, $flt->supp);
?>
<div class="d-flex flex-nowrap gap-2">
<label for="flt_txt"><?=_('Text')?></label>
<input type="text" name="flt_txt" size="15" maxlength="30" value="<?=$flt->txt ?>">
</div>
<div class="d-flex flex-nowrap gap-2">
<?php
$enum_data = db_load_enum('equipment', 'flags', true, true, false);
form_create_checks('flags', _('Flags'), $enum_data, []);
?>
</div>
</div>
<div class="card-footer">
<button name="submit[filter]" class="btn btn-sm btn-primary" title="<?=_('Apply')?>"><?=_('Go')?></button>
<button name="submit[freset]" class="btn btn-sm btn-secondary float-end" title="<?=_('Reset filter to defaults')?>"><?=_('Clear')?></button>
</div>
@@ -284,6 +300,7 @@ echo $pagination;
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo '<tr>';
echo '<th>#</th>';
echo '<th>', _('Description'), "</th>";
echo '<th>', _('Manufacturer'), "</th>";
echo '<th>', _('Model'), "</th>";
@@ -293,6 +310,8 @@ echo '<th>', _('Remarks'), "</th>";
echo "<th>&nbsp;</th>";
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
// calc nice age display
if (!isset($row['age_mon'])) {
@@ -302,19 +321,26 @@ foreach ($res as $row) {
} else {
$age = sprintf(_('%dy'), intdiv($row['age_mon'], 12));
}
$i++; // record number
echo "<tr>\n";
echo "<td>", $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['eid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>", $row['ename'], "</td>\n";
echo "<td>", ($opt_manufacturer[$row['manufacturer']] ?? ''), "</td>\n";
echo "<td>", $row['model'], "</td>\n";
echo "<td>", $row['serial'], "</td>\n";
echo "<td>", $age, "</td>\n";
echo "<td>", $row['remarks'], "</td>\n";
// Action buttons
form_action_buttons($g_scriptname, $row['eid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['eid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
?>
<tfoot>
<tr><td colspan="6"><?php printf(_('%d records of %d'), count($res), $numrows); ?></td></tr>
<tr><td colspan="8"><?php printf(_('Records %d to %d of %d'), $i0, $i, $numrows); ?></td></tr>
</tfoot>
</table>
<?php
@@ -344,7 +370,7 @@ form_create_select('manufacturer', _('Manufacturer'), $opt_manufacturer, $flt->m
</div>
<div class="mb-3">
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
<textarea class="form-control" id="remarks" name="remarks" rows="3"></textarea>
<textarea class="form-control" id="remarks" name="remarks" rows="3" maxlength="150"></textarea>
</div>
<div class="container-fluid px-0 my-3">
<button type="submit" name="submit[insert]" class="btn btn-primary"><?=_('Save')?></button>
@@ -356,7 +382,7 @@ elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$sql = "SELECT eid, ename, model, serial, purchdate, price, weight, "
. " supplier, manufacturer, ecat, shortname, remarks "
. " supplier, manufacturer, ecat, shortname, remarks, flags "
. "FROM equipment "
. "WHERE eid=?";
$sth = $pdo->prepare($sql);
@@ -371,7 +397,9 @@ echo '<div class="col">';
echo '<table class="table">', "\n";
echo '<tr><th>', _('Short name'),"</th><td>", $equipment->shortname, "</td></tr>\n";
echo '<tr><th>', _('Manufacturer'),"</th><td>", $opt_manufacturer[$equipment->manufacturer], "</td></tr>\n";
echo '<tr><th>', _('Manufacturer'),"</th><td>", $opt_manufacturer[$equipment->manufacturer];
echo '&nbsp;<a title="', _('View'), '" href="company.php?f=view&id=', $equipment->manufacturer, '"><i class="bi-eye"></i></a>';
echo "</td></tr>\n";
echo '<tr><th>', _('Model'),"</th><td>", $equipment->model, "</td></tr>\n";
echo '<tr><th>', _('Serial'),"</th><td>", $equipment->serial, "</td></tr>\n";
echo '<tr><th>', _('Weight'),"</th><td>", format_float($equipment->weight, 2, 'kg'), "</td></tr>\n";
@@ -379,14 +407,17 @@ echo '<tr><th>', _('Price'),"</th><td>", format_currency($equipment->price), "</
echo '<tr><th>', _('Purchase date'),"</th><td>", $equipment->purchdate, "</td></tr>\n";
echo '<tr><th>', _('Supplier'),"</th><td>", $equipment->supplier ? $opt_supplier[$equipment->supplier] : 'n/a', "</td></tr>\n";
echo '<tr><th>', _('Category'),"</th><td>", $opt_ecat[$equipment->ecat], "</td></tr>\n";
echo '<tr><th>', _('Remarks'),"</th><td>", $equipment->remarks, "</td></tr>\n";
echo '<tr><th>', _('Remarks'),"</th><td>", nl2br($equipment->remarks), "</td></tr>\n";
echo '<tr><th>', _('Flags'),"</th><td>", $equipment->flags, "</td></tr>\n";
echo "</table>\n";
echo '</div>'; // Column break
echo '<div class="col">';
?>
<p>Images and documents go here</p>
<?php
echo '<div class="col">', "\n";
echo '<div class="card">', "\n";
echo '<div class="card-header">', _('Images and documents'), "</div>\n";
echo '<div class="card-body">', "\n";
$sql = "SELECT d.docid, d.doctype, d.title "
. "FROM docref AS r INNER JOIN document AS d using (docid) "
. "WHERE r.reftype='equipment' AND r.refid=? "
@@ -394,31 +425,46 @@ $sql = "SELECT d.docid, d.doctype, d.title "
$sth = $pdo->prepare($sql);
$sth->execute([$id]);
$res = $sth->fetchAll();
// TODO hübsche Darstellung
$doccount = 0;
foreach ($res as $row) {
$doccount += 1;
if ($row['doctype'] == 'picture') {
echo '<a href="dl.php?id=', $row['docid'], '">';
// echo '<img width="120" src="doc/pic-', $row['hash'], '.', $row['extension'],'">';
echo '<img width="120" src="dl.php?id=', $row['docid'], '" alt="', $row['title'], '">';
echo "</a>\n";
} elseif ($row['doctype'] == 'drawing') {
echo "<p>Drawing: ", $row['title'], "<br>";
echo '<a href="dl.php?id=', $row['docid'], '">';
echo '<img width="180" src="dl.php?id=', $row['docid'], '">';
echo "</a>";
echo "</p>\n";
} elseif ($row['doctype'] == 'generic') {
echo '<a href="dl.php?id=', $row['docid'], '">';
echo '<img width="120" src="dl.php?id=', $row['docid'], '&t=s" alt="', $row['title'], '">';
// echo $row['title'];
echo "</a>\n";
} elseif ($row['doctype'] == 'manual') {
echo "Manual: ";
echo "<p>Manual: ";
echo '<a href="documents.php?f=view&id=', $row['docid'], '">';
echo $row['title'];
echo "</a>\n";
echo "</a></p>\n";
} else {
// unknown document type
echo "<span>Unknown document type:", $row['doctype'], "</span>\n";
}
}
if ($doccount == 0) {
echo _('No referenced documents'), "\n";
}
echo "</div>\n"; // card-body
echo "</div>\n"; // card
?>
<form method="post" enctype="multipart/form-data" action="<?=$g_scriptname?>">
<input type="hidden" name="id" value="<?=$id?>">
<div class="card">
<div class="card-header"><?=_('Add Image');?></div>
<div class="card-body">
<input type="file" name="files[]" multiple accept="image/*" capture="camera">
<input type="submit" name="submit[upload]" value="Upload">
+1 -1
View File
@@ -1,7 +1,7 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024-2025 Thomas Hooge
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************
+2
View File
@@ -7,7 +7,9 @@
<title><?=APP_TITLE_SHORT?> - <?=$pagetitle?></title>
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="bootstrap/bootstrap-icons.min.css" rel="stylesheet">
<link href="css/choices.css" rel="stylesheet">
<script src="bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="js/choices.min.js"></script>
<link rel="stylesheet" href="default.css">
<?php
if (isset($GLOBALS['local_script'])) {
+13 -8
View File
@@ -1,7 +1,7 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024 Thomas Hooge
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************/
@@ -142,7 +142,7 @@ $vessel = $sth->fetch(PDO::FETCH_OBJ);
// Show remarks first
if (strlen($vessel->remarks) > 0) {
echo "<p>";
echo $vessel->remarks;
echo nl2br($vessel->remarks);
echo "</p>\n";
}
@@ -321,24 +321,28 @@ $sth->execute([$user->vid]);
echo '<tr><td>&nbsp;</td><td>', _('Boxes'), '</td><td>', $sth->fetchColumn(), "</td></tr>\n";
// Equipment
$sth = $pdo->prepare("SELECT COUNT(*) FROM equipment WHERE vid=?");
$sth = $pdo->prepare("SELECT COUNT(*), SUM(weight) FROM equipment WHERE vid=?");
$sth->execute([$user->vid]);
$row = $sth->fetch(PDO::FETCH_NUM);
echo '<tr><td colspan="3">', _('Equipment') , "</td>";
echo '<tr><td>&nbsp;</td><td>', _('Count'), '</td><td>', $sth->fetchColumn(), "</td></tr>\n";
echo '<tr><td>&nbsp;</td><td>', _('Count'), '</td><td>', $row[0], "</td></tr>\n";
echo '<tr><td>&nbsp;</td><td>', _('Weight'), '</td><td>', format_float($row[1], 1, 'kg'), "</td></tr>\n";
// Inventory
// All items from vessel storage and all items from boxes in vessel storage
$sql = "SELECT SUM(n) FROM ("
. "SELECT COUNT(*) AS n FROM inventory JOIN storage USING (sid) WHERE conttype='storage' AND vid=:vid "
$sql = "SELECT SUM(n), SUM(w) FROM ("
. "SELECT COUNT(*) AS n, SUM(i.weight * i.number) as w FROM inventory AS i JOIN storage USING (sid) WHERE conttype='storage' AND vid=:vid "
. "UNION "
. "SELECT COUNT(*) AS n FROM inventory JOIN box USING (boxid) JOIN storage ON (box.sid=storage.sid) WHERE conttype='box' AND vid=:vid"
. "SELECT COUNT(*) AS n, SUM(i.weight * i.number) as w FROM inventory AS i JOIN box USING (boxid) JOIN storage ON (box.sid=storage.sid) WHERE conttype='box' AND vid=:vid"
. ") AS x";
$sth = $pdo->prepare($sql);
$sth->bindValue(':vid', $user->vid, PDO::PARAM_INT);
$sth->execute();
$row = $sth->fetch(PDO::FETCH_NUM);
echo '<tr><td colspan="3">', _('Inventory') , "</td>";
echo '<tr><td>&nbsp;</td><td>', _('Count'), '</td><td>', $sth->fetchColumn(), "</td></tr>\n";
echo '<tr><td>&nbsp;</td><td>', _('Count'), '</td><td>', $row[0], "</td></tr>\n";
echo '<tr><td>&nbsp;</td><td>', _('Weight'), '</td><td>', format_float($row[1], 1, 'kg'), "</td></tr>\n";
// Documents
$sth = $pdo->query("SELECT COUNT(*) FROM document");
@@ -368,6 +372,7 @@ echo "</table>\n";
<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="checklist.php"><?=_('Checklists')?></a></li>
+35 -12
View File
@@ -138,15 +138,17 @@ try {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$numrows = $sth->fetchColumn();
$lastpage = ceil($numrows/$g_rows_pp);
$page = gpc_get_int($_REQUEST, 'p', 1);
$rows_pp = gpc_get_int($_REQUEST, 'n', $g_rows_pp);
$lastpage = ceil($numrows/$rows_pp);
$sql = "SELECT i.invid, i.invname, i.number, i.invcond, s.sname AS container "
$sql = "SELECT i.invid, i.invname, i.number, i.invcond, i.eid, s.sname AS container "
. "FROM inventory AS i JOIN storage AS s ON (i.conttype='storage' AND i.sid=s.sid)";
$sql .= ' WHERE ' . $where;
$sql .= " UNION SELECT i.invid, i.invname, i.number, i.invcond, b.label AS container "
$sql .= " UNION SELECT i.invid, i.invname, i.number, i.invcond, i.eid, b.label AS container "
. "FROM inventory AS i JOIN box AS b ON (i.conttype='box' AND i.boxid=b.boxid) "
. " JOIN storage AS s ON (b.sid=s.sid) ";
$sql .= ' WHERE ' . $where;
@@ -162,6 +164,7 @@ try {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$res = $sth->fetchAll();
@@ -173,14 +176,15 @@ $opt_special = array(
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-body">
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body d-flex flex-wrap gap-3">
<?php
// page specific filter start
// - selection for storage
// - selection for box
// page specific filter end
?>
<div class="d-flex flex-nowrap gap-2">
<label for="flt_stor"><?=_('Storage')?></label>
<select id="flt_stor" name="flt_stor">
<?php
@@ -193,6 +197,8 @@ foreach ($opt_special + $opt_storage as $k => $v) {
}
?>
</select>
</div>
<div class="d-flex flex-nowrap gap-2">
<label for="flt_cond"><?=_('Condition')?></label>
<select id="flt_cond" name="flt_cond">
<?php
@@ -208,8 +214,13 @@ foreach ($opt_special + $opt_invcond as $k => $v) {
}
?>
</select>
</div>
<div class="d-flex flex-nowrap gap-2">
<label for="flt_txt">Text</label>
<input type="text" name="flt_txt" size="15" maxlength="30" value="<?=$flt->txt ?>">
</div>
</div>
<div class="card-footer">
<button name="submit[filter]" class="btn btn-sm btn-primary" title="<?=_('Apply')?>"><?=_('Go')?></button>
<button name="submit[freset]" class="btn btn-sm btn-secondary float-end" title="<?=_('Reset filter to defaults')?>"><?=_('Clear')?></button>
</div>
@@ -224,6 +235,7 @@ echo $pagination;
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>\n";
echo '<th>#</th>';
echo "<th>", _('Name'), "</th>\n";
echo "<th>", _('Container'), "</th>\n";
echo "<th>", _('Number'), "</th>\n";
@@ -232,19 +244,30 @@ echo "<th>", _('Tags'), "</th>\n";
echo "<td></td>\n";
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo '<td>', $row['invname'], "</td>\n";
echo '<td>', $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['invid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
// alternative symbols: wrench, wrench-adjustable, tools
echo '<td>', $row['invname'];
echo isset($row['eid']) && $row['eid'] > 0 ? ' <i class="bi bi-wrench"></i>' : '', "</td>\n";
echo "<td>", $row['container'], "</td>\n";
echo "<td>", $row['number'], "</td>\n";
echo "<td>", ($opt_invcond[$row['invcond']] ?? ''), "</td>\n";
echo "<td>", _('No tags assigned'), "</td>\n";
form_action_buttons($g_scriptname, $row['invid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['invid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
echo "<tfoot>\n";
echo '<tr><td colspan="5">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
echo '<tr><td colspan="7">', sprintf(_('Records %d to %d of %d'), $i0, $i, $numrows), '</td></tr>', "\n";
echo "</tfoot>\n";
echo "</table>\n";
@@ -274,8 +297,8 @@ echo '<h2>', _('Add Inventory'), "</h2>\n";
</select>
</div>
<?php
form_create_select('sid', _('Storage'), $opt_storage);
form_create_select('boxid', _('Box'), $opt_box);
form_create_select('sid', _('Storage'), $g_opt_none + $opt_storage);
form_create_select('boxid', _('Box'), $g_opt_none + $opt_box);
?>
<div class="container-fluid px-0 my-3">
<button type="submit" name="submit[insert]" class="btn btn-primary"><?=_('Save')?></button>
@@ -337,7 +360,7 @@ echo "<tr><th>", _('Weight'), "</th><td>", format_float($inventory->weight, 2, '
echo "<tr><th>", _('Price'), "</th><td>", format_currency($inventory->price), "</td></tr>\n";
echo "<tr><th>", _('Purchase date'), "</th><td>", $inventory->purchdate, "</td></tr>\n";
echo "<tr><th>", _('Condition'), "</th><td>", $opt_invcond[$inventory->invcond], "</td></tr>\n";
echo "<tr><th>", _('Remarks'), "</th><td>", $inventory->remarks, "</td></tr>\n";
echo "<tr><th>", _('Remarks'), "</th><td>", nl2br($inventory->remarks), "</td></tr>\n";
$tags = db_load_taglist('inv', $id);
form_tag_assignment($g_scriptname, $id, $tags);
@@ -377,7 +400,7 @@ $inventory = $sth->fetch(PDO::FETCH_OBJ);
$opt_conttype = db_load_enum('inventory', 'conttype', true, true);
form_create_select('conttype', _('Container type'), $opt_conttype, $inventory->conttype);
form_create_select('sid', _('Storage'), $opt_storage, $inventory->sid);
form_create_select('boxid', _('Box'), $opt_box, $inventory->boxid);
form_create_select('boxid', _('Box'), $g_opt_none + $opt_box, $inventory->boxid);
?>
<div class="mb-3">
<label for="price" class="form-label"><?=sprintf(_('Price, %s'), $g_lconv['currency_symbol']); ?></label>
+965 -362
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+9 -5
View File
@@ -1,7 +1,7 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024 Thomas Hooge
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************/
@@ -33,6 +33,10 @@ if (isset($_POST['login'])) {
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="bootstrap/bootstrap-icons.min.css" rel="stylesheet">
<script src="bootstrap/js/bootstrap.bundle.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
});
</script>
</head>
<body>
<div class="container">
@@ -70,10 +74,10 @@ if (isset($err)) {
<?=_('Login')?>
</button>
</form>
</div> <!-- card body -->
</div>
</div>
</div>
</div> <?php /* card body */?>
</div> <?php /* columns */?>
</div> <?php /* rows */?>
</div> <?phph /* card */?>
</section>
</div>
</body>
+51 -11
View File
@@ -84,8 +84,9 @@ $opt_special = array(
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-body">
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body d-flex flex-wrap gap-3">
<div class="d-flex flex-nowrap gap-2">
<label for="flt_equip">Equipment</label>
<select id="flt_equip" name="flt_equip">
<?php
@@ -98,8 +99,13 @@ foreach ($opt_special + $opt_equipment as $k => $v) {
}
?>
</select>
</div>
<div class="d-flex flex-nowrap gap-2">
<label for="flt_txt">Text</label>
<input type="text" name="flt_txt" size="15" maxlength="30" value="<?=$flt->txt ?? ''?>">
</div>
</div>
<div class="card-footer">
<button name="submit[filter]" class="btn btn-sm btn-primary" title="<?=_('Apply')?>"><?=_('Go')?></button>
<button name="submit[freset]" class="btn btn-sm btn-secondary float-end" title="<?=_('Reset filter to defaults')?>"><?=_('Clear')?></button>
</div>
@@ -107,32 +113,66 @@ foreach ($opt_special + $opt_equipment as $k => $v) {
</form>
<?php
$sort = array(
1 => 'm.maintid',
2 => 'm.maintid DESC'
);
$w = array('m.vid=:vid');
$p = array(':vid' => $user->vid);
if ($flt->equip == -1 or $flt->equip == 0) {
$w[] = 'm.eid IS NULL';
} elseif ($flt->equip > 0) {
$w[] = 'm.eid=:eid';
$p[':eid'] = $flt->equip;
}
if (strlen($flt->txt) > 1) {
$w[] = '(m.activities LIKE :txt OR m.remarks LIKE :txt)';
$p[':txt'] = '%'.$flt->txt.'%';
}
$where = join(' AND ', $w);
$order = ' ORDER BY m.maintid';
$sql = "SELECT m.maintid, m.activities, m.remarks, e.ename "
. "FROM maintenance AS m LEFT OUTER JOIN equipment AS e USING (eid)"
. "WHERE m.vid=? "
. "ORDER BY m.maintid";
. "FROM maintenance AS m LEFT OUTER JOIN equipment AS e USING (eid)";
$sql .= ' WHERE ' . $where;
$sql .= $order;
// if pagination:
// $sql .= ' LIMIT ' . ($page - 1) * $rows_pp . ',' . $rows_pp;
$sth = $pdo->prepare($sql);
$sth->execute([$user->vid]);
$sth->execute($p);
$res = $sth->fetchAll();
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>";
echo '<th>#</th>';
echo "<th>", _('Activities'), "</th>";
echo "<th>", _('Equipment'), "</th>";
echo "<th>", _('Remarks'), "</th>";
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo '<td>', $i;
echo '<a title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['maintid'], '"><i class="bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>". $row['activities'] ."</td>\n";
echo "<td>". $row['ename'] ."</td>\n";
echo "<td>". $row['remarks'] ."</td>\n";
// Action buttons
/* echo "<td>";
echo '<a title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['maintid'], '"><i class="bi-eye"></i></a>', "\n";
echo "<td>";
// Edit current record button
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['maintid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n"; */
form_action_buttons($g_scriptname, $row['maintid']);
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
+21 -3
View File
@@ -13,6 +13,9 @@ require 'header.php';
?>
<h1>Yacht Management System</h1>
<p>Hinweis: Es handelt sich hier um einen Prototyp!</p>
<h2>Integriertes Handbuch</h2>
<p>Es können mehrere Yachten mit dem Programm verwaltet werden.
@@ -47,6 +50,10 @@ Wasserlinie.</p>
<p>Ausrüstung ist zumeist fest mit der Yacht verbunden, jeder Ausrüstungsgegenstand
existiert nur ein mal und kann eine Seriennummer besitzen.</p>
<p>Ausrüstung kann gewartet werden.</p>
<p>Ein Ausrüstungsgegenstand kann als bestellt, entfernt oder gelöscht gekennzeichnet
werden. Entfernt bedeutet der Gegenstand ist noch vorhanden aber nicht auf dem
Boot installiert. Gelöschte Gegenstände werden bei der nächsten Reorganisation
komplett aus dem System entfernt.</p>
<h3>Inventar</h3>
<p>Unter Inventar sind bewegliche Dinge zusammengefaßt.
@@ -54,6 +61,8 @@ Ein Inventargegenstand kann auch mehrfach vorkommen.
Beispiel: <em>Winschkurbel, Anzahl: 3</em></p>
<p>Inventar kann in einem Stauraum abgelegt werden oder aber in einer
Kiste.</p>
<p>Inventar welches einem Ausrüstungsgegenstand zugeordnet ist, wird
als Ersatzteil geführt.</p>
<h3>Proviant</h3>
<p>Proviant ist verderblich.
@@ -61,7 +70,9 @@ Es wird das Einlagerungsdatum erfaßt und das Haltbarkeitsdatum</p>
<p>Proviant kann einem Stauraum und somit einem Boot zugeordnet sein
oder aber <em>frei</em>.
Freier Proviant kann später zugeordnet
werden. Er ist erkennbar am Einkaufswagen-Symbol <i class="bi bi-basket"></i>.<p>
werden. Er ist erkennbar am Einkaufswagen-Symbol <i class="bi bi-cart3"></i>.<p>
<p>TODO/Noch nichtimplementiert: Proviant kann auch in eine Kiste gelegt werden</p>
<h3>Wartung</h3>
<p>Es können einmalige und wiederkehrende Wartungen erfaßt werden</p>
@@ -74,8 +85,11 @@ z.B. <em>neu</em>, <em>laufend</em> oder <em>erledigt</em>.</p>
<h3>Aufgaben</h3>
<p>Aufgaben sind normalerweise den aktuell ausgewählten Boot zugeordnet,
können aber auch bootsunabhängig angelegt werden. Eine projektzuordnung
ist ebenfalls vorgesehen</p>
können aber auch bootsunabhängig angelegt werden. Eine Projektzuordnung
ist ebenfalls vorgesehen.</p>
<p>Die Aufgaben sind nicht als Menüpunkt auf oberster Ebene vorhanden.
Die Aufgabenübersicht kann über Zusatzmodule auf der Startseine erreicht
werden.</p>
<h3>Firmen</h3>
<p>Es können verschiedene Arten von Firmen hinterlegt werden, wie
@@ -108,6 +122,10 @@ ist es möglich Flächen <span style="white-space:nowrap">(L x B)</span> oder
Volumen <span style="white-space:nowrap">(L x B x H)</span> zusammenhängend
zu erfassen.</p>
<h3>Notizen</h3>
<p>Notizen können für verschiedene Aufgaben und Wartungen hinterlegt werden.
Es handelt sich um die Eingabemöglichkeit in ein einzelnes Textfeld.</p>
<h3>Benutzer</h3>
<p>Benutzer können nicht über die Web-GUI eingerichtet werden.</p>
<p>Es gibt die Berechtigungsebenen <em>Kapitän (captain)</em>,
+5 -2
View File
@@ -11,6 +11,7 @@ $pagetitle = _('Measurements');
$id = gpc_get_int($_REQUEST, 'id', 0);
$opt_mtype = db_load_enum('measurement', 'mtype', true, false);
$opt_unit = db_get_options(8);
$opt_accuracy = array(
'unknown' => _('Unknown'),
@@ -147,9 +148,11 @@ $opt_special = array(
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body">
<?php
filter_create_select('flt_mtype', _('Type'), $g_opt_all + $g_opt_none + $opt_mtype);
?>
<label for="flt_txt">Text</label>
<input type="text" name="flt_txt" size="15" maxlength="30" value="<?=$flt->txt?>">
<button name="submit[filter]" class="btn btn-sm btn-primary" title="<?=_('Apply')?>"><?=_('Go')?></button>
+88 -20
View File
@@ -19,6 +19,18 @@ foreach ($sth->fetchAll() as $row) {
}
$opt_state = db_load_enum('project', 'projstate', true, true);
/* Nur für choices benötigt
$local_script = "
document.addEventListener('DOMContentLoaded', function () {
const element = document.getElementById('flt_state[]');
const choices = new Choices(element, {
removeItemButton: true,
duplicateItemsAllowed: false,
searchEnabled: false
});
});
"; */
// ========== ACTIONS START ===================================================
switch ($submit = form_get_action()) {
@@ -33,7 +45,7 @@ switch ($submit = form_get_action()) {
case 'filter':
$flt = array();
$flt['name'] = gpc_get_string($_POST, 'flt_name');
$flt['state'] = gpc_get_string($_POST, 'flt_state');
$flt['state'] = $_POST['flt_state']; // Array! gpc_get_string($_POST, 'flt_state');
$flt['remarks'] = gpc_get_string($_POST, 'flt_remarks');
db_save_filter($flt, 205);
$action = ACT_DEFAULT;
@@ -95,28 +107,67 @@ page_caption_search($pagetitle);
// load filter from db
$flt = db_get_filter($user->id, 205);
$w = array();
$p = array();
// name, status, text
$w = array('vid=:vid');
$p = array(':vid' => $user->vid);
if (strlen($flt->txt) > 1) {
$w[] = '(projname LIKE :txt OR remarks LIKE :txt)';
$p[':txt'] = '%'.$flt->txt.'%';
}
$where = join(' AND ', $w);
$order = ' ORDER BY comptype, compname';
$order = ' ORDER BY projname';
// grand total of records for current vessel
$grandtotal = $pdo->query("SELECT COUNT(*) FROM project")->fetchColumn();
$sth = $pdo->prepare("SELECT COUNT(*) FROM project WHERE " . $where);
try {
$sth->execute($p);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$numrows = $sth->fetchColumn();
$page = gpc_get_int($_REQUEST, 'p', 1);
$rows_pp = gpc_get_int($_REQUEST, 'n', $g_rows_pp);
$lastpage = ceil($numrows/$rows_pp);
// $grandtotal = $pdo->query("SELECT COUNT(*) FROM project WHERE " . $where)->fetchColumn();
$sql = "SELECT projid, projname, startdate, duration, projstate, remarks "
. "FROM project";
$sql .= " WHERE " . $where;
$sql .= $order;
// if pagination:
$sql .= ' LIMIT ' . ($page - 1) * $g_rows_pp . ',' . $g_rows_pp;
$sth = $pdo->prepare($sql);
$sth->execute($p);
$res = $sth->fetchAll();
// Filter
?>
<form method="post" action="<?=$g_scriptname?>">
<form id="filterform" method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-body">
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body d-flex flex-wrap gap-3">
<div class="d-flex flex-nowrap gap-2">
<label for="flt_name">Name</label>
<input type="text" name="flt_name" size="15" maxlength="30" value="<?=$flt->name;?>">
</div>
<?php
filter_create_select('flt_state', _('State'), $g_opt_all + $opt_state, $flt->state);
filter_create_select('flt_state[]', _('State'), $g_opt_all + $opt_state, $flt->state, FALSE);
?>
<div class="d-flex flex-nowrap gap-2">
<label for="flt_remarks">Text</label>
<input type="text" name="flt_remarks" size="15" maxlength="30" value="<?=$flt->remarks ?>">
</div>
</div>
<div class="card-footer">
<button name="submit[filter]" class="btn btn-sm btn-primary" title="<?=_('Apply')?>"><?=_('Go')?></button>
<button name="submit[freset]" class="btn btn-sm btn-secondary float-end" title="<?=_('Reset filter to defaults')?>"><?=_('Clear')?></button>
</div>
@@ -124,16 +175,11 @@ filter_create_select('flt_state', _('State'), $g_opt_all + $opt_state, $flt->sta
</form>
<?php
$sql = "SELECT projid, projname, startdate, duration, projstate, remarks "
. "FROM project "
. "WHERE vid=? "
. "ORDER BY projid";
$sth = $pdo->prepare($sql);
$sth->execute([$user->vid]);
$res = $sth->fetchAll();
echo '<table class="table table-striped">'. "\n";
echo "<thead>\n";
echo "<tr>";
echo '<th>#</th>';
echo "<th>" . _('Name') . "</th>";
echo "<th>" . _('Start date') . "</th>";
echo "<th>" . _('Duration') . "</th>";
@@ -142,15 +188,24 @@ echo "<th>" . _('Remarks') . "</th>";
echo "<th>&nbsp;</th>";
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo '<td>', $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['projid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>". $row['projname'] ."</td>\n";
echo "<td>". $row['startdate'] ."</td>\n";
echo "<td>". $row['duration'] ."</td>\n";
echo "<td>". $row['projstate'] ."</td>\n";
echo "<td>". $row['remarks'] ."</td>\n";
// Action buttons
form_action_buttons($g_scriptname, $row['projid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['projid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
echo "<tfoot>\n";
@@ -172,15 +227,28 @@ $res = $sth->fetchAll();
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>";
echo '<th>#</th>';
echo "<th>" . _('Name') . "</th>";
echo "<th>" . _('State') . "</th>";
echo "</tr>\n";
echo "</thead>\n";
// TODO own pagination
// $i = ($page - 1) * $rows_pp;
$i = 0;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo '<td>', $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="task.php?f=view&id=', $row['taskid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>". $row['taskname'] ."</td>\n";
echo "<td>". $row['taskstate'] ."</td>\n";
form_action_buttons('task.php', $row['taskid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="task.php?f=edit&id=', $row['taskid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
@@ -230,7 +298,7 @@ echo '<tr><th scope="row">', _('Responsible'),"</th><td>", $opt_user[$project->r
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">', _('State'),"</th><td>", $project->projstate, "</td></tr>\n";
echo '<tr><th scope="row">', _('Remarks'),"</th><td>", $project->remarks, "</td></tr>\n";
echo '<tr><th scope="row">', _('Remarks'),"</th><td>", nl2br($project->remarks), "</td></tr>\n";
echo "</table>\n";
form_view_buttons($g_scriptname, $id);
+92 -22
View File
@@ -54,10 +54,13 @@ switch ($submit = form_get_action()) {
$p[':provname'] = gpc_get_string($_POST, 'provname');
$p[':provcat'] = gpc_get_int($_POST, 'provcat');
$p[':number'] = gpc_get_int($_POST, 'number');
$p[':weight'] = min(gpc_get_float($_POST, 'weight'), 999.99); // limit max value
$p[':weight_net'] = min(gpc_get_float($_POST, 'weight_net'), 999.99);
$p[':unit'] = gpc_get_int($_POST, 'unit');
$p[':storedate'] = gpc_get_string($_POST, 'storedate');
$p[':shelflife'] = gpc_get_string($_POST, 'shelflife');
$p[':sid'] = gpc_get_int($_POST, 'sid');
if ($p[':sid'] <= 0) $p[':sid'] = NULL;
db_exec_update('provisions', $p, 'provid');
$action = ACT_VIEW;
break;
@@ -88,11 +91,19 @@ require 'header.php';
if ($action == ACT_DEFAULT):
// ========== VARIANT: default behavior =======================================
page_caption_search($pagetitle);
// load filter from db
$flt = db_get_filter($user->id, 202);
$w = array('(vid=:vid OR sid IS NULL)');
$p = array(':vid' => $user->vid);
if ($flt->cat == -1) {
$w[] = 'provcat IS NULL';
} elseif ($flt->cat > 0) {
$w[] = 'provcat=:provcat';
$p[':provcat'] = $flt->cat;
}
if (strlen($flt->txt) > 1) {
$w[] = 'provname LIKE :txt';
$p[':txt'] = '%'.$flt->txt.'%';
@@ -101,27 +112,53 @@ $where = join(' AND ', $w);
$order = ' ORDER BY provid';
// get total record count for pagination and limit
$sql = "SELECT COUNT(*) FROM provisions LEFT OUTER JOIN storage USING (sid) WHERE " . $where;
$sth = $pdo->prepare($sql);
try {
$sth->execute($p);
} catch(PDOException $e) {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$numrows = $sth->fetchColumn();
$page = gpc_get_int($_REQUEST, 'p', 1);
$rows_pp = gpc_get_int($_REQUEST, 'n', $g_rows_pp);
$lastpage = ceil($numrows/$rows_pp);
// provisions can be assigned to a store or be free
// d0 is the maximum number of days age
// d1 is the current age in days. If negative then it is over limit
// TODO display over with warning levels: 50% over, 100% over etc.
$sql = "SELECT provid, provname, number, unit, storedate, shelflife, sid,"
. " DATEDIFF(shelflife, storedate) AS d0, DATEDIFF (CURDATE(), storedate) AS d1 "
. " DATEDIFF(shelflife, storedate) AS d0, DATEDIFF (shelflife, CURDATE()) AS d1 "
. "FROM provisions LEFT OUTER JOIN storage USING (sid)";
$sql .= ' WHERE ' . $where;
$sql .= $order;
// if pagination:
$sql .= ' LIMIT ' . ($page - 1) * $rows_pp . ',' . $rows_pp;
$sth = $pdo->prepare($sql);
$sth->execute($p);
$res = $sth->fetchAll();
page_caption_search($pagetitle);
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-body">
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body d-flex flex-wrap gap-3">
<?php
filter_create_select('flt_cat', _('Category'), $g_opt_all + $g_opt_none + $opt_category, $flt->cat);
?>
<div class="d-flex flex-nowrap gap-2">
<label for="flt_txt">Text</label>
<input type="text" name="flt_txt" size="15" maxlength="30" value="<?=$flt->txt?>">
<input type="text" name="flt_txt" size="15" maxlength="30" value="<?=$flt->txt;?>">
</div>
</div>
<div class="card-footer">
<button name="submit[filter]" class="btn btn-sm btn-primary" title="<?=_('Apply')?>"><?=_('Go')?></button>
<button name="submit[freset]" class="btn btn-sm btn-secondary float-end" title="<?=_('Reset filter to defaults')?>"><?=_('Clear')?></button>
</div>
@@ -129,39 +166,62 @@ filter_create_select('flt_cat', _('Category'), $g_opt_all + $g_opt_none + $opt_c
</form>
<?php
// Pagination on top
$pagination = get_pagination($g_scriptname, '', $page, $lastpage);
echo $pagination;
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>\n";
echo '<th>#</th>';
echo '<th>', _('Description'), "</th>";
echo '<th>', _('Number'), "</th>";
echo '<th>', _('Unit'), "</th>";
echo '<th>', _('Stored'), "</th>";
echo '<th>', _('Best before'), "</th>";
echo "<th></th>";
echo "<th></th>\n";
echo "<th></th>"; // Meter
echo "<th></th>\n"; // Buttons
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo "<td>", ! isset($row['sid']) ? '<i class="bi bi-basket"></i> ' : '', $row['provname'], "</td>\n";
echo "<td>". $row['number'] ."</td>\n";
echo "<td>". $opt_unit[$row['unit']] ."</td>\n";
echo "<td>". $row['storedate'] ."</td>\n";
echo "<td>". $row['shelflife'] ."</td>\n";
echo "<td>";
echo '<meter min="0" max="', $row['d0'], '" value="', $row['d1'], '">';
// Action buttons
form_action_buttons($g_scriptname, $row['provid']);
echo "<td>", $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['provid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>", ! isset($row['sid']) ? '<i class="bi bi-cart3"></i> ' : '', $row['provname'], "</td>\n";
echo "<td>", $row['number'], "</td>\n";
echo "<td>", $opt_unit[$row['unit']], "</td>\n";
echo "<td>", $row['storedate'], "</td>\n";
echo "<td>", $row['shelflife'], "</td>\n";
// TODO shelflife in der Vergangenheit
echo "<td>";
if ($row['d1'] > 0) {
echo '<meter min="0" max="', $row['d0'], '" value="', $row['d1'], '"></meter>';
} else {
if ($row['d1'] < 0) {
echo '<i class="bi bi-exclamation-triangle-fill"></i>&nbsp;', abs($row['d1']);
}
}
echo "</td>\n";
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['provid'], '"><i class="bi-pencil"></i></a>';
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
echo "<tfoot>\n";
echo '<tr><td colspan="6">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
echo '<tr><td colspan="8">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
echo "</tfoot>\n";
echo "</table>\n";
echo $pagination;
form_add_button($g_scriptname);
elseif ($action == ACT_ADD):
@@ -187,7 +247,7 @@ echo '<h2>', _('Add provisions'), "</h2>\n";
<label for="shelflife"><?=_('Shelflife')?></label>
<input type="date" class="form-control" id="shelflife" name="shelflife">
</div>
<?php form_create_select('sid', _('Storage'), [-1 => '- none -'] + $opt_storage); ?>
<?php form_create_select('sid', _('Storage'), $g_opt_none + $opt_storage); ?>
<div class="container-fluid px-0 my-3">
<button type="submit" name="submit[insert]" class="btn btn-primary"><?=_('Save')?></button>
<a href="<?=$g_scriptname?>" class="btn btn-secondary"><?=_('Back')?></a>
@@ -198,7 +258,7 @@ echo '<h2>', _('Add provisions'), "</h2>\n";
elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$sql = "SELECT provname, provcat, number, unit, storedate, shelflife, sid "
$sql = "SELECT provname, provcat, number, unit, weight, weight_net, storedate, shelflife, sid "
. "FROM provisions "
. "WHERE provid=?";
$sth = $pdo->prepare($sql);
@@ -209,6 +269,8 @@ echo '<h2>', $prov->provname, "</h2>\n";
echo '<table class="table">', "\n";
echo '<tr><th style="width:20%">', _('Number'),"</th><td>", $prov->number, "</td></tr>\n";
echo "<tr><th>", _('Weight'), "</th><td>", format_float($prov->weight, 2, 'kg'), "</td></tr>\n";
echo "<tr><th>", _('Weight net'), "</th><td>", format_float($prov->weight_net, 2, 'kg'), "</td></tr>\n";
echo '<tr><th>', _('Unit'),"</th><td>", $opt_unit[$prov->unit], "</td></tr>\n";
echo '<tr><th>', _('Category'),"</th><td>", $opt_category[$prov->provcat] ?? 'n/a', "</td></tr>\n";
echo '<tr><th>', _('Storedate'),"</th><td>", $prov->storedate, "</td></tr>\n";
@@ -221,7 +283,7 @@ form_view_buttons($g_scriptname, $id);
elseif ($action == ACT_EDIT):
// ========== VARIANT: edit single record =====================================
$sql = "SELECT provname, provcat, number, unit, storedate, shelflife, sid "
$sql = "SELECT provname, provcat, number, weight, weight_net, unit, storedate, shelflife, sid "
. "FROM provisions "
. "WHERE provid=?";
$sth = $pdo->prepare($sql);
@@ -240,9 +302,17 @@ echo '<h2>', _('Edit provision'), "</h2>\n";
<label for="number"><?=_('Number')?></label>
<input type="number" min="0" max="1000" class="form-control" id="number" name="number" value="<?=$prov->number ?>">
</div>
<div class="mb-3">
<label for="weight" class="form-label"><?=_('Weight, kg')?></label>
<input type="text" class="form-control" id="weight" name="weight" value="<?=format_float($prov->weight); ?>">
</div>
<div class="mb-3">
<label for="weight_net" class="form-label"><?=_('Weight net, kg')?></label>
<input type="text" class="form-control" id="weight" name="weight_net" value="<?=format_float($prov->weight_net); ?>">
</div>
<?php
form_create_select('unit', _('Unit'), $opt_unit, $prov->unit);
form_create_select('provcat', _('Category'), array_merge($g_opt_none, $opt_category), $prov->provcat);
form_create_select('provcat', _('Category'), $g_opt_none + $opt_category, $prov->provcat);
?>
<div class="mb-3">
<label for="storedate"><?=_('Storedate')?></label>
@@ -253,7 +323,7 @@ form_create_select('provcat', _('Category'), array_merge($g_opt_none, $opt_categ
<input type="date" class="form-control" id="shelflife" name="shelflife" value="<?=$prov->shelflife ?>">
</div>
<?php
form_create_select('sid', _('Storage'), $opt_storage, $prov->sid);
form_create_select('sid', _('Storage'), $g_opt_none + $opt_storage, $prov->sid);
form_edit_buttons($g_scriptname, $id);
echo "</form>\n";
+32 -7
View File
@@ -1,7 +1,7 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024 Thomas Hooge
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************/
@@ -95,7 +95,7 @@ page_caption_search($pagetitle);
// Storage
// stype from dropdown
$sql = "SELECT sid, sname, x, y, z, remarks "
$sql = "SELECT sid, sname, x, y, z, angle, remarks "
. "FROM storage "
. "WHERE vid=? "
. "ORDER BY sid";
@@ -105,22 +105,36 @@ $res = $sth->fetchAll();
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>";
echo '<th>#</th>';
echo "<th>", _('Name'), "</th>";
echo "<th>", _('Position'), "</th>";
echo "<th>", _('Remarks'), "</th>";
echo "<th>&nbsp;</th>";
echo "</tr>\n";
echo "</thead>\n";
$i = 0;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo '<td>', $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['sid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>", $row['sname'], "</td>\n";
echo "<td>", join(',', array($row['x'] ?? '?', $row['y'] ?? '?', $row['z'])), "</td>\n";
if ($row['angle'] != 0) {
$angle = " (" . $row['angle'] . "°)";
} else {
$angle = "";
}
echo "<td>", join(',', array($row['x'] ?? '?', $row['y'] ?? '?', $row['z'])), $angle, "</td>\n";
echo "<td>", $row['remarks'], "</td>\n";
form_action_buttons($g_scriptname, $row['sid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['sid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
echo "<tfoot>\n";
echo '<tr><td colspan="3">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
echo '<tr><td colspan="5">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
echo "</tfoot>\n";
echo "</table>\n";
@@ -136,17 +150,26 @@ $res = $sth->fetchAll();
echo '<table class="table table-striped">', "\n";
echo "<thead>\n";
echo "<tr>";
echo '<th>#</th>';
echo "<th>" . _('Label') . "</th>";
echo "<th>" . _('Color') . "</th>";
echo "<th>" . _('Content') . "</th>";
echo "<td></td>";
echo "</tr>\n";
$i = 0;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
echo '<td>', $i;
echo '<a class="text-nowrap" title="', _('View'), '" href="box.php?f=view&id=', $row['boxid'], '"><i class="bi bi-eye ms-2"></i></a>', "\n";
echo "</td>\n";
echo "<td>". $row['label'] ."</td>\n";
echo '<td>', format_color($row['color']), "</td>\n";
echo "<td>". $row['content'] ."</td>\n";
form_action_buttons('box.php', $row['boxid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="box.php?f=edit&id=', $row['boxid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
@@ -189,7 +212,7 @@ elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$opt_unit = db_get_options(6);
$sql = "SELECT sid, sname, stype, capacity, capaunit, x, y, z, wx, wy, wz, remarks "
$sql = "SELECT sid, sname, stype, capacity, capaunit, x, y, z, wx, wy, wz, angle, color, remarks "
. "FROM storage "
. "WHERE sid=?";
$sth = $pdo->prepare($sql);
@@ -202,6 +225,8 @@ echo '<tr><th style="width:33%">', _('Typ'),"</th><td>", $stype[$storage->stype]
echo '<tr><th>', _('Capacity'),"</th><td>", $storage->capacity, ' ', $storage->capaunit, "</td></tr>\n";
echo '<tr><th>', _('Location (x, y, z)'),"</th><td>(", $storage->x, ', ', $storage->y, ', ', $storage->z, ")</td></tr>\n";
echo '<tr><th>', _('Width (wx, wy, wz)'),"</th><td>(", $storage->wx, ', ', $storage->wy, ', ', $storage->wz, ")</td></tr>\n";
echo '<tr><th>', _('Angle'),"</th><td>", $storage->angle, "°</td></tr>\n";
echo '<tr><th>', _('Color'),"</th><td>", $storage->color, "</td></tr>\n";
echo '<tr><th>', _('Remarks'),"</th><td>", $storage->remarks, "</td></tr>\n";
echo "</table>\n";
+1 -1
View File
@@ -88,7 +88,7 @@ echo "<h1>$pagetitle</h1>\n";
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body">
<label for="flt_txt">Text</label>
+30 -7
View File
@@ -35,6 +35,11 @@ switch ($submit = form_get_action()) {
$action = ACT_DEFAULT;
break;
case 'freset':
db_clear_filter(206);
$action = ACT_DEFAULT;
break;
case 'insert':
$p[':vid'] = $user->vid;
$p[':projid'] = gpc_get_int($_POST, 'projid');
@@ -42,6 +47,7 @@ switch ($submit = form_get_action()) {
$p[':projid'] = NULL;
}
$p[':taskname'] = gpc_get_string($_POST, 'taskname');
$p[':responsible'] = $user->id;
$id = db_exec_insert('task', $p);
$action = ACT_VIEW;
break;
@@ -62,6 +68,7 @@ switch ($submit = form_get_action()) {
$p[':started'] = gpc_get_datetime($_POST, 'started');
$p[':finished'] = gpc_get_datetime($_POST, 'finished');
$p[':taskstate'] = gpc_get_enum($_POST, 'taskstate', array_keys($opt_state));
$p[':responsible'] = gpc_get_int($_POST, 'responsible');
db_exec_update('task', $p, 'taskid');
$action = ACT_VIEW;
break;
@@ -137,7 +144,7 @@ $where = join(' AND ', $w);
$order = ' ORDER BY t.taskid';
// get total recond count for pagination and limit
$sql = "SELECT COUNT(*) FROM task";
$sql = "SELECT COUNT(*) FROM task AS t";
if ($where) $sql .= " WHERE $where";
$sth = $pdo->prepare($sql);
@@ -147,10 +154,12 @@ try {
$g_error->Add($e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->PrintOut();
}
$numrows = $sth->fetchColumn();
$lastpage = ceil($numrows/$g_rows_pp);
$page = gpc_get_int($_REQUEST, 'p', 1);
$rows_pp = gpc_get_int($_REQUEST, 'n', $g_rows_pp);
$lastpage = ceil($numrows/$rows_pp);
$sql = "SELECT t.taskid, t.vid, t.projid, t.taskname, t.priority, t.taskstate,"
. " p.projname "
@@ -167,13 +176,14 @@ try {
$g_error->Add('SQL-Error: '. $e->getMessage());
$g_error->Add($sql);
$g_error->Add(print_r($p, true));
$g_error->Printout();
}
$res = $sth->fetchAll();
?>
<form method="post" action="<?=$g_scriptname?>">
<div id="filter" class="card">
<div class="card-header">Filter</div>
<div class="card-header"><i class="bi bi-funnel me-2"></i>Filter</div>
<div class="card-body">
<?php
filter_create_select('flt_prio', _('Priority'), $g_opt_all + $g_opt_none + $opt_priority, $flt->prio);
@@ -200,16 +210,23 @@ echo "<th></th>";
echo "<th></th>\n";
echo "</tr>\n";
echo "</thead>\n";
$i = ($page - 1) * $rows_pp;
$i0 = $i + 1;
foreach ($res as $row) {
$i++; // record number
echo "<tr>\n";
// mark generic tasks with braces
echo "<td>", $row['vid'] ? $row['taskid'] : '('.$row['taskid'].')', "</td>\n";
echo "<td>", $row['vid'] ? $i : "($i)";
echo '<a class="text-nowrap" title="', _('View'), '" href="', $g_scriptname, '?f=view&id=', $row['taskid'], '"><i class="bi bi-eye ms-2"></i></a>';
echo "</td>\n";
echo "<td>", $row['taskname'], "</td>\n";
echo "<td>", $row['projname'], "</td>\n";
echo "<td>", ($opt_priority[$row['priority']] ?? ''), "</td>\n";
echo "<td>", ($opt_state[$row['taskstate']]), "</td>\n";
// Action buttons
form_action_buttons($g_scriptname, $row['taskid']);
// Edit current record button
echo "<td>";
echo '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['taskid'], '"><i class="bi-pencil"></i></a>', "\n";
echo "</td>\n";
echo "</tr>\n";
}
// Table summary
@@ -247,8 +264,10 @@ elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$sql = "SELECT t.taskname, t.priority, t.plandate, t.duedate,"
. " t.started, t.finished, t.taskstate, p.projname "
. " t.started, t.finished, t.taskstate, t.responsible,"
. " u.displayname, p.projname "
. "FROM task AS t LEFT JOIN project AS p USING (projid) "
. " LEFT JOIN user AS u ON (t.responsible=u.userid) "
. "WHERE taskid=?";
$sth = $pdo->prepare($sql);
$sth->execute([$id]);
@@ -264,6 +283,7 @@ echo '<tr><th>', _('Due date'),"</th><td>", $task->duedate, "</td></tr>\n";
echo '<tr><th>', _('Started at'),"</th><td>", $task->started, "</td></tr>\n";
echo '<tr><th>', _('Finished at'),"</th><td>", $task->finished, "</td></tr>\n";
echo '<tr><th>', _('Status'),"</th><td>", $opt_state[$task->taskstate], "</td></tr>\n";
echo '<tr><th>', _('Responsible'),"</th><td>", $task->displayname, "</td></tr>\n";
echo "</table>\n";
form_view_buttons($g_scriptname, $id);
@@ -297,6 +317,8 @@ echo '<p>', _('Not yet implemented'), "</p>";
elseif ($action == ACT_EDIT):
// ========== VARIANT: edit single record =====================================
$opt_user = db_get_opt_user($user->id); // only used here
$sql = "SELECT taskname, projid, priority, plandate, duedate, started, finished,"
. " taskstate "
. "FROM task "
@@ -337,6 +359,7 @@ form_create_select('priority', _('Priority'), $opt_none + $opt_priority, $task->
</div>
<?php
form_create_select('taskstate', _('Status'), $opt_state, $task->taskstate);
form_create_select('responsible', _('Responsible'), $opt_user, $user->id);
form_edit_buttons($g_scriptname, $id);
echo "</form>\n";