diff --git a/INSTALL b/INSTALL index 46809af..733b242 100644 --- a/INSTALL +++ b/INSTALL @@ -11,10 +11,14 @@ YMS Installation 1.2 Native GUI - Python GTK3 + - python3-gi + - gir1.2-gtk-3.0 1.3 Web GUI - Webserver - PHP + - php-mysql + - php-xml 2. Create database diff --git a/db/mariadb.sql b/db/mariadb.sql index b0262ed..cf8ca69 100644 --- a/db/mariadb.sql +++ b/db/mariadb.sql @@ -146,11 +146,12 @@ CREATE TABLE inventory ( conttype enum('storage','box') NOT NULL DEFAULT 'storage', sid smallint(6) NOT NULL DEFAULT 1, boxid smallint(6) NOT NULL DEFAULT 1, + eid smallint(6) DEFAULT NULL, number smallint(6) UNSIGNED NOT NULL DEFAULT 1, weight float(5,2) UNSIGNED DEFAULT NULL, price decimal(12,2) DEFAULT NULL, purchdate date DEFAULT NULL, - invcond enum('unknown','good','normal','bad','repairable','defect') NOT NULL default 'unknown', + invcond enum('unknown','new','good','normal','bad','repairable','defect') NOT NULL default 'unknown', remarks varchar(150) DEFAULT NULL, PRIMARY KEY (invid), INDEX ix_invname (invname) @@ -174,6 +175,7 @@ CREATE TABLE measurement ( CREATE TABLE provisions ( provid int(10) NOT NULL AUTO_INCREMENT, provname varchar(40) NOT NULL, + provcat tinyint(3) DEFAULT NULL, sid smallint(6) DEFAULT NULL, number smallint(6) UNSIGNED NOT NULL DEFAULT 1, unit tinyint(3) DEFAULT NULL, @@ -228,7 +230,7 @@ CREATE TABLE company ( contractno varchar(20), remarks varchar(150) DEFAULT NULL, PRIMARY KEY (compid), - UNIQUE INDEX ix_compname (compname) + UNIQUE INDEX ix_compname (compname, comptype) ); diff --git a/webgui/box.php b/webgui/box.php index b26633d..64ddc95 100644 --- a/webgui/box.php +++ b/webgui/box.php @@ -157,7 +157,7 @@ echo '', _('Box type'),"", ($opt_boxtype[$box echo '', _('Content'),"", $box->content, "\n"; echo '', _('Color'), '', format_color($box->color), "\n"; echo '', _('Weight'), '', format_float($box->weight, 2, 'kg'), "\n"; -echo '', _('Storage'),"", $box->sname; +echo '', _('Storage'),"", $box->sname, ' '; echo ''; echo "\n"; echo '', _('Remarks'),"", $box->remarks, "\n"; diff --git a/webgui/company.php b/webgui/company.php index 99dee33..90a90b1 100644 --- a/webgui/company.php +++ b/webgui/company.php @@ -87,6 +87,8 @@ require 'header.php'; if ($action == ACT_DEFAULT): // ========== VARIANT: default behavior ======================================= +page_caption_search($pagetitle); + // load filter from db $flt = db_get_filter($user->id, 208); @@ -103,10 +105,34 @@ if (strlen($flt->txt) > 1) { $where = join(' AND ', $w); $order = ' ORDER BY comptype, compname'; +// grand total of records for current vessel +$grandtotal = $pdo->query("SELECT COUNT(*) FROM company")->fetchColumn(); + +// get total record count for pagination and limit +$sql = "SELECT COUNT(*) FROM company"; +if ($where) { + $sql .= " 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)); +} +$numrows = $sth->fetchColumn(); +$lastpage = ceil($numrows/$g_rows_pp); +$page = gpc_get_int($_REQUEST, 'p', 1); + $sql = "SELECT compid, compname, comptype, remarks " . "FROM company"; if ($where) $sql .= ' WHERE ' . $where; $sql .= $order; + +// if pagination: +$sql .= ' LIMIT ' . ($page - 1) * $g_rows_pp . ',' . $g_rows_pp; + $sth = $pdo->prepare($sql); try { $sth->execute($p); @@ -117,8 +143,6 @@ try { } $res = $sth->fetchAll(); -echo '

', $pagetitle , "

\n"; - // Filter $opt_special = array( -2 => _('― all ―'), @@ -149,6 +173,9 @@ foreach ($opt_special + $opt_comptype as $k => $v) { ', "\n"; echo "\n"; @@ -173,10 +200,12 @@ foreach ($res as $row) { } // Table summary echo "\n"; -echo '', sprintf(_('%d records'), count($res)), '', "\n"; +echo '', sprintf(_('%d records out of total %d'), count($res), $grandtotal), '', "\n"; echo "\n"; echo "\n"; +echo $pagination; + form_add_button($g_scriptname); @@ -230,8 +259,7 @@ form_view_buttons($g_scriptname, $id); // show referenced equipment $sql = "SELECT eid, ename FROM equipment WHERE supplier=:id OR manufacturer=:id"; $sth = $pdo->prepare($sql); -$sth->bindValue(':id', $id, PDO::PARAM_INT); -$sth->execute(); +$sth->execute([':id' => $id]); if ($sth->rowCount() > 0) { echo "

Referenced in equipment:

\n"; echo " @@ -387,7 +397,8 @@ elseif ($action == ACT_EDIT): // ========== VARIANT: edit single record ===================================== // get list of shapefiles -$opt_shapefiles = array('' => _('--- none ---')); +//$opt_shapefiles = array('' => _('--- none ---')); +$opt_shapefiles = $g_opt_none; foreach (glob($g_shapedir.'/*.svg') as $f) { $f = basename($f); $opt_shapefiles[$f] = $f; diff --git a/webgui/inventory.php b/webgui/inventory.php index f94b070..fd04630 100644 --- a/webgui/inventory.php +++ b/webgui/inventory.php @@ -14,6 +14,7 @@ $id = gpc_get_int($_REQUEST, 'id', 0); $opt_storage = db_get_opt_storage($user->vid); $opt_box = db_get_opt_box($user->vid); $opt_invcond = db_load_enum('inventory', 'invcond', true, true); +$opt_equipment = db_get_opt_equip($user->vid, [-1 => _('― none ―')]); // ========== ACTIONS START =================================================== @@ -59,6 +60,7 @@ switch ($submit = form_get_action()) { $p[':purchdate'] = gpc_get_date($_POST, 'purchdate'); $p[':invcond'] = gpc_get_string($_POST, 'invcond'); $p[':remarks'] = gpc_get_string($_POST, 'remarks', 150); + $p[':eid'] = gpc_get_int($_POST, 'eid'); db_exec_update('inventory', $p, 'invid'); $action = ACT_VIEW; break; @@ -92,6 +94,8 @@ require 'header.php'; if ($action == ACT_DEFAULT): // ========== VARIANT: default behavior ======================================= +page_caption_search($pagetitle); + $flt = db_get_filter($user->id, 201); /* @@ -99,8 +103,6 @@ The only way to find out whether the inventory is on the current boat is to use the box assignment. But this is also intentional to allow easy rearrangement. */ -echo "

$pagetitle

\n"; - $w = array('vid=:vid'); $p = array(':vid' => $user->vid); if ($flt->stor == -1) { @@ -109,10 +111,10 @@ if ($flt->stor == -1) { $w[] = 'i.sid=:sid'; $p[':sid'] = $flt->stor; } -/*if ($flt->cond <> 'all') { - $w[] = 'indcond=:indcond'; - $p[':indcond'] = $flt->cond; -}*/ +if (strlen($flt->cond) > 2 ) { + $w[] = 'invcond=:invcond'; + $p[':invcond'] = $flt->cond; +} if (strlen($flt->txt) > 1) { $w[] = 'invname LIKE :txt'; $p[':txt'] = '%'.$flt->txt.'%'; @@ -120,6 +122,22 @@ if (strlen($flt->txt) > 1) { $where = join(' AND ', $w); $order = ' ORDER BY invname'; +$sql = "SELECT " + . "(SELECT COUNT(*) FROM inventory AS i JOIN storage AS s ON (i.conttype='storage' AND i.sid=s.sid) WHERE $where)" + . "+" + . "(SELECT COUNT(*) 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) 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)); +} +$numrows = $sth->fetchColumn(); +$lastpage = ceil($numrows/$g_rows_pp); +$page = gpc_get_int($_REQUEST, 'p', 1); + $sql = "SELECT i.invid, i.invname, i.number, i.invcond, s.sname AS container " . "FROM inventory AS i JOIN storage AS s ON (i.conttype='storage' AND i.sid=s.sid)"; $sql .= ' WHERE ' . $where; @@ -128,6 +146,10 @@ $sql .= " UNION SELECT i.invid, i.invname, i.number, i.invcond, b.label AS conta . " JOIN storage AS s ON (b.sid=s.sid) "; $sql .= ' WHERE ' . $where; $sql .= $order; + +// if pagination: +$sql .= ' LIMIT ' . ($page - 1) * $g_rows_pp . ',' . $g_rows_pp; + $sth = $pdo->prepare($sql); try { $sth->execute($p); @@ -169,6 +191,9 @@ foreach ($opt_special + $opt_storage as $k => $v) { -
- - -
-conttype); form_create_select('sid', _('Storage'), $opt_storage, $inventory->sid); form_create_select('boxid', _('Box'), $opt_box, $inventory->boxid); ?> @@ -358,14 +385,7 @@ form_create_select('boxid', _('Box'), $opt_box, $inventory->boxid); +eid); ?>
diff --git a/webgui/maintenance.php b/webgui/maintenance.php index b71ae45..e14e255 100644 --- a/webgui/maintenance.php +++ b/webgui/maintenance.php @@ -66,11 +66,11 @@ require 'header.php'; if ($action == ACT_DEFAULT): // ========== VARIANT: default behavior ======================================= +page_caption_search($pagetitle); + // load filter from db $flt = db_get_filter($user->id, 204); -echo '

', $pagetitle, "

\n"; - // Filter $opt_special = array( -2 => _('― all ―'), @@ -122,10 +122,11 @@ foreach ($res as $row) { echo "". $row['ename'] ."\n"; echo "". $row['remarks'] ."\n"; // Action buttons - echo ""; +/* echo ""; echo '', "\n"; echo '', "\n"; - echo "\n"; + echo "\n"; */ + form_action_buttons($g_scriptname, $row['maintid']); echo "\n"; } // Table summary @@ -202,7 +203,7 @@ echo '
'; echo '', "\n"; echo '\n"; echo '\n"; echo '\n"; echo '\n"; echo '\n"; +echo '\n"; echo "
', _('Activities'),"", $maint->activities, "
', _('Equipment'),"", $maint->ename; -if (isset($maint->eid)) { +if (isset($maint->eid) and $maint->eid>0) { // Link to equipment echo ' '; } diff --git a/webgui/manual.php b/webgui/manual.php index 1102938..a2fddb0 100644 --- a/webgui/manual.php +++ b/webgui/manual.php @@ -72,6 +72,11 @@ oder nach Betriebsstunden definiert werden.

Einem Projekt werden Aufgaben zugeordnet, es hat einen Status wie z.B. neu, laufend oder erledigt.

+

Aufgaben

+

Aufgaben sind normalerweise den aktuell ausgewählten Boot zugeordnet, +können aber auch bootsunabhängig angelegt werden. Eine projektzuordnung +ist ebenfalls vorgesehen

+

Firmen

Es können verschiedene Arten von Firmen hinterlegt werden, wie beispielsweise Hersteller, Lieferanten, Werften oder Dienstleister.

diff --git a/webgui/measurement.php b/webgui/measurement.php index d9d8cb3..09d9f22 100644 --- a/webgui/measurement.php +++ b/webgui/measurement.php @@ -240,7 +240,7 @@ form_create_select('eid', _('Equipment'), $opt_equipment, $id); elseif ($action == ACT_VIEW): // ========== VARIANT: view single record ===================================== -$sql = "SELECT mname, unit, nval, val1, val2, val3, accuracy, mdate, note " +$sql = "SELECT mname, unit, nval, val1, val2, val3, accuracy, mdate, note, eid " . "FROM measurement " . "WHERE mid=?"; $sth = $pdo->prepare($sql); @@ -259,6 +259,7 @@ echo '
', _('Value 3'),"$measurement->val3
', _('Accuracy'),"$measurement->accuracy
', _('Date'),"$measurement->mdate
', _('Note'),"$measurement->note
', _('Equipment'), '', $opt_equipment[$measurement->eid], "
\n"; form_view_buttons($g_scriptname, $id); @@ -267,7 +268,7 @@ form_view_buttons($g_scriptname, $id); elseif ($action == ACT_EDIT): // ========== VARIANT: edit single record ===================================== -$sql = "SELECT mname, nval, val1, val2, val3, unit, accuracy, note " +$sql = "SELECT mname, nval, val1, val2, val3, unit, accuracy, note, eid " . "FROM measurement " . "WHERE mid=?"; $sth = $pdo->prepare($sql); diff --git a/webgui/note.php b/webgui/note.php index 1e297a2..f1f3fa2 100644 --- a/webgui/note.php +++ b/webgui/note.php @@ -62,7 +62,7 @@ switch ($submit = form_get_action()) { // now really delete $sth = $pdo->prepare("DELETE FROM note WHERE noteid=?"); $sth->execute([$id]); - header_location($backlink); + header_location($backlink, ['info' => _('Note deleted.')]); break; default: @@ -111,6 +111,7 @@ foreach ($res as $row) { echo "", $row['refid'], "\n"; echo "", $row['notetype'], "\n"; echo "", $row['annotation'], "\n"; + form_action_buttons($g_scriptname, $row['noteid']); echo "\n"; } @@ -204,8 +205,6 @@ echo "\n"; elseif ($action == ACT_DELETE): // ========== VARIANT: delete record ========================================== -echo '

', _('Delete Note'), "

\n"; - $sql = "SELECT notetype, annotation FROM note WHERE noteid=?"; $sth = $pdo->prepare($sql); $sth->execute([$id]); diff --git a/webgui/projects.php b/webgui/projects.php index 9fdc039..d7c067b 100644 --- a/webgui/projects.php +++ b/webgui/projects.php @@ -81,7 +81,7 @@ require 'header.php'; if ($action == ACT_DEFAULT): // ========== VARIANT: default behavior ======================================= -echo '

', $pagetitle, "

\n"; +page_caption_search($pagetitle); $sql = "SELECT projid, projname, startdate, duration, remarks " . "FROM project " diff --git a/webgui/provisions.php b/webgui/provisions.php index 3355cbd..125758e 100644 --- a/webgui/provisions.php +++ b/webgui/provisions.php @@ -12,7 +12,7 @@ $pagetitle=_('Provisions'); $id = gpc_get_int($_REQUEST, 'id', 0); $opt_storage = db_get_opt_storage($user->vid); -$opt_catgory = db_get_options(5); +$opt_category = db_get_options(5); $opt_unit = db_get_options(6); // ========== ACTIONS START =================================================== @@ -28,6 +28,7 @@ switch ($submit = form_get_action()) { case 'filter': $flt = array(); + $flt['cat'] = gpc_get_enum($_POST, 'flt_cat', array_merge(array_keys($opt_category), ['-2', '-1'])); $flt['txt'] = gpc_get_string($_POST, 'flt_txt'); db_save_filter($flt, 202); $action = ACT_DEFAULT; @@ -46,6 +47,7 @@ switch ($submit = form_get_action()) { case 'update': $p[':provid'] = $id; $p[':provname'] = gpc_get_string($_POST, 'provname'); + $p[':provcat'] = gpc_get_int($_POST, 'provcat'); $p[':number'] = gpc_get_int($_POST, 'number'); $p[':unit'] = gpc_get_int($_POST, 'unit'); $p[':storedate'] = gpc_get_string($_POST, 'storedate'); @@ -104,12 +106,15 @@ $sth = $pdo->prepare($sql); $sth->execute($p); $res = $sth->fetchAll(); -echo "

", $pagetitle, "

\n"; +page_caption_search($pagetitle); ?>
Filter
+cat); +?> @@ -187,7 +192,7 @@ echo '

', _('Add provisions'), "

\n"; elseif ($action == ACT_VIEW): // ========== VARIANT: view single record ===================================== -$sql = "SELECT provname, number, unit, storedate, shelflife, sid " +$sql = "SELECT provname, provcat, number, unit, storedate, shelflife, sid " . "FROM provisions " . "WHERE provid=?"; $sth = $pdo->prepare($sql); @@ -199,6 +204,7 @@ echo '

', $prov->provname, "

\n"; echo '', "\n"; echo '\n"; echo '\n"; +echo '\n"; echo '\n"; echo '\n"; echo '\n"; @@ -209,7 +215,7 @@ form_view_buttons($g_scriptname, $id); elseif ($action == ACT_EDIT): // ========== VARIANT: edit single record ===================================== -$sql = "SELECT provname, number, unit, storedate, shelflife, sid " +$sql = "SELECT provname, provcat, number, unit, storedate, shelflife, sid " . "FROM provisions " . "WHERE provid=?"; $sth = $pdo->prepare($sql); @@ -228,7 +234,10 @@ echo '

', _('Edit provision'), "

\n"; -unit); ?> +unit); +form_create_select('provcat', _('Category'), array_merge($g_opt_none, $opt_category), $prov->provcat); +?>
diff --git a/webgui/search.php b/webgui/search.php index f641dda..7f9da9f 100644 --- a/webgui/search.php +++ b/webgui/search.php @@ -26,57 +26,112 @@ echo "

$pagetitle

\n";
- - ', _('Back'), "\n"; +} + +echo "\n"; + if (isset($needle)) { $sqlneedle = '%'.$needle.'%'; - $remarks = isset($_POST['ck_remarks']) ? ' OR remarks LIKE :needle' : ''; // equipment + $remarks = isset($_POST['ck_remarks']) ? ' OR remarks LIKE :needle' : ''; $sql = "SELECT eid, ename, model, remarks " . "FROM equipment " - . "WHERE ename LIKE :needle OR model LIKE :needle" . $remarks; + . "WHERE vid=:vid AND (ename LIKE :needle OR model LIKE :needle)" . $remarks; $sth = $pdo->prepare($sql); - $sth->execute([':needle' => $sqlneedle]); + $sth->execute([':vid' => $user->vid, ':needle' => $sqlneedle]); if ($sth->rowCount() > 0) { echo '

', _('Equipment'), "

\n"; foreach ($sth->fetchAll() as $row) { $out = $row['ename'] . ' ' . $row['model']; // mark needle in result - $p0 = strpos($out, $needle); - if ($p0 > 0) { + $p0 = stripos($out, $needle); + if ($p0 >= 0) { $out = substr_replace($out, '', $p0 + strlen($needle), 0); $out = substr_replace($out, '', $p0, 0); } - echo '

', $out; - echo ''; + echo '

', $out, ' '; + echo ''; echo "

\n"; } } // inventory - $sql = "SELECT invid, invname, remarks " - . "FROM inventory " - . "WHERE invname LIKE :needle" . $remarks; + $remarks = isset($_POST['ck_remarks']) ? 'OR i.remarks LIKE :needle ' : ''; + $sql = "SELECT invid, invname, i.remarks " + . "FROM inventory AS i JOIN storage AS s ON (i.conttype='storage' AND i.sid=s.sid) " + . "WHERE s.vid=:vid AND i.invname LIKE :needle " . $remarks + . "UNION " + . "SELECT invid, invname, i.remarks " + . "FROM inventory AS i JOIN box AS b ON (i.conttype='box' AND i.boxid=b.boxid) " + . " JOIN storage AS s ON (i.sid=s.sid) " + . "WHERE s.vid=:vid AND i.invname LIKE :needle " . $remarks; $sth = $pdo->prepare($sql); - $sth->execute([':needle' => $sqlneedle]); + $sth->execute([':vid' => $user->vid, ':needle' => $sqlneedle]); if ($sth->rowCount() > 0) { echo '

', _('Inventory'), "

\n"; foreach ($sth->fetchAll() as $row) { - $out = $row['invname'] . ' ' . $row['model']; + $out = rtrim($row['invname'] . ' ' . $row['model']); // mark needle in result - $p0 = strpos($out, $needle); - if ($p0 > 0) { + $p0 = stripos($out, $needle); + if ($p0 >= 0) { $out = substr_replace($out, '
', $p0 + strlen($needle), 0); $out = substr_replace($out, '', $p0, 0); } - echo '

', $out; - echo ''; + echo '

', $out, ' '; + echo ''; + echo "

\n"; + } + } + + // notes + $sql = "SELECT taskid, taskname " + . "FROM task " + . "WHERE taskname LIKE :needle AND (vid IS NULL OR vid=:vid)"; + $sth = $pdo->prepare($sql); + $sth->execute([':needle' => $sqlneedle, ':vid' => $user->vid]); + if ($sth->rowCount() > 0) { + echo '

', _('Tasks'), "

\n"; + foreach ($sth->fetchAll() as $row) { + // mark needle in result + $out = $row['taskname']; + $p0 = stripos($out, $needle); + if ($p0 >= 0) { + $out = substr_replace($out, '
', $p0 + strlen($needle), 0); + $out = substr_replace($out, '', $p0, 0); + } + echo '

', $out, ' '; + echo ''; + echo "

\n"; + } + } + + // notes + $sql = "SELECT noteid, annotation " + . "FROM note " + . "WHERE annotation LIKE :needle"; + $sth = $pdo->prepare($sql); + $sth->execute([':needle' => $sqlneedle]); + if ($sth->rowCount() > 0) { + echo '

', _('Annotations'), "

\n"; + foreach ($sth->fetchAll() as $row) { + // mark needle in result + $out = $row['annotation']; + $p0 = stripos($out, $needle); + if ($p0 >= 0) { + $out = substr_replace($out, '
', $p0 + strlen($needle), 0); + $out = substr_replace($out, '', $p0, 0); + } + echo '

', $out, ' '; + echo ''; echo "

\n"; } } } + include 'footer.php'; diff --git a/webgui/storage.php b/webgui/storage.php index 25dfb2c..1e11f22 100644 --- a/webgui/storage.php +++ b/webgui/storage.php @@ -91,7 +91,7 @@ require 'header.php'; if ($action == ACT_DEFAULT): // ========== VARIANT: default behavior ======================================= -echo '

', $pagetitle, "

\n"; +page_caption_search($pagetitle); // Storage // stype from dropdown @@ -219,7 +219,7 @@ if (count($res) > 0) { foreach ($res as $row) { echo "
"; echo '"; - echo '"; + echo '"; echo ''; echo "\n"; } diff --git a/webgui/tag.php b/webgui/tag.php index a3f3de5..b85cc6d 100644 --- a/webgui/tag.php +++ b/webgui/tag.php @@ -38,7 +38,7 @@ switch ($submit = form_get_action()) { case 'update': $p[':tagid'] = $id; $p[':tagname'] = gpc_get_string($_POST, 'tagname'); - $p[':color'] = gpc_get_string($_POST, 'color'); + $p[':color'] = gpc_get_color($_POST, 'color'); $p[':description'] = gpc_get_string($_POST, 'description'); db_exec_update('tag', $p, 'tagid'); $action = ACT_VIEW; @@ -77,6 +77,8 @@ $flt = db_get_filter($user->id, 210); echo "

$pagetitle

\n"; +// db_save_taglist('inv', 1, 'apple, banana , , , orange, ddd'); + // Filter ?> @@ -85,7 +87,7 @@ echo "

$pagetitle

\n";
- +
@@ -110,7 +112,7 @@ foreach ($res as $row) { echo "\n"; echo "\n"; echo "\n"; - echo "\n"; + echo "\n"; echo "\n"; echo "\n"; @@ -92,16 +195,19 @@ echo ''; echo '"; echo '"; echo '"; +echo '"; echo ""; echo "\n"; echo "\n"; echo "\n"; foreach ($res as $row) { echo "\n"; - echo "\n"; + // mark generic tasks with braces + echo "\n"; echo "\n"; echo "\n"; echo "\n"; + echo "\n"; // Action buttons form_action_buttons($g_scriptname, $row['taskid']); echo "\n"; @@ -141,7 +247,7 @@ elseif ($action == ACT_VIEW): // ========== VARIANT: view single record ===================================== $sql = "SELECT t.taskname, t.priority, t.plandate, t.duedate," - . " t.started, t.finished, p.projname " + . " t.started, t.finished, t.taskstate, p.projname " . "FROM task AS t LEFT JOIN project AS p USING (projid) " . "WHERE taskid=?"; $sth = $pdo->prepare($sql); @@ -150,18 +256,19 @@ $task = $sth->fetch(PDO::FETCH_OBJ); echo '

', _('View Task'), "

\n"; echo '
', _('Number'),"", $prov->number, "
', _('Unit'),"", $opt_unit[$prov->unit], "
', _('Category'),"", $opt_category[$prov->provcat] ?? 'n/a', "
', _('Storedate'),"", $prov->storedate, "
', _('Shelflife'),"$prov->shelflife
', _('Storage'),"", ($opt_storage[$prov->sid] ?? ''), "
', $row['label'], "', $row['color'], "', format_color($row['color']), "
", $row['tagname'], "", $row['description'], "", $row['color'], "", format_color($row['color']), ""; // Action buttons form_action_buttons($g_scriptname, $row['tagid']); @@ -147,6 +149,50 @@ echo "\n"; elseif ($action == ACT_VIEW): // ========== VARIANT: view single record ===================================== +$sql = "SELECT tagname, description, color " + . "FROM tag " + . "WHERE tagid=?"; +$sth = $pdo->prepare($sql); +$sth->execute([$id]); +$tag = $sth->fetch(PDO::FETCH_OBJ); + +echo '

', _('View Tag'), "

\n"; + +echo '', "\n"; +echo '\n"; +echo '\n"; +echo '\n"; +echo "
', _('Tag'),"", $tag->tagname, "
', _('Color'),"", format_color($tag->color), "
', _('Description'),"", $tag->description, "
\n"; + +form_view_buttons($g_scriptname, $id); + +echo '

', _('Tag usage'), "

\n"; +$sql = "SELECT objid, objtype FROM tagref WHERE tagid=?"; +$sth = $pdo->prepare($sql); +$sth->execute([$id]); + +$link = array( + 'equip' => 'equipment.php', + 'inv' => 'inventory.php', + 'prov' => 'provisions.php', + 'doc' => 'documents.php', + 'proj' => 'projects.php', + 'task' => 'task.php', + 'maint' => 'maintenance.php' + ); +echo '

'; +if ($sth->rowCount() > 0) { + foreach ($sth->fetchAll() as $row) { + echo '', $row['objid'], '/', $row['objtype'], "\n"; + } +} else { + echo _('Tag is not used anywhere'); +} +echo "

\n"; + +echo '

', _('Related tags'), "

\n"; +echo '

', _('Not yet implemented'), "

\n"; + elseif ($action == ACT_EDIT): // ========== VARIANT: edit single record ===================================== @@ -181,6 +227,21 @@ echo "\n"; elseif ($action == ACT_DELETE): // ========== VARIANT: delete record ========================================== +echo '

', _('Delete tag'), "

\n"; + +$sql = "SELECT objid, objtype FROM tagref WHERE tagid=?"; +$sth = $pdo->prepare($sql); +$sth->execute([$id]); +if ($sth->rowCount() > 0) { + foreach ($sth->fetchAll() as $row) { + echo '', $row['objid'], '/', $row['objtype'], "\n"; + } +} else { + echo _('Tag is not used anywhere'); + $_SESSION['token'] = bin2hex(random_bytes(8)); + form_delete_buttons($g_scriptname, $id, $_SESSION['token']); +} + else: // ========== ERROR UNKNOWN VARIANT =========================================== diff --git a/webgui/task.php b/webgui/task.php index 24704af..b910055 100644 --- a/webgui/task.php +++ b/webgui/task.php @@ -13,6 +13,7 @@ $id = gpc_get_int($_REQUEST, 'id', 0); $opt_projects = db_get_opt_proj($user->vid, array(-1 => _('unassigned'))); $opt_priority = db_load_enum('task', 'priority', true, true); +$opt_state = db_load_enum('task', 'taskstate', true, true); // ========== ACTIONS START =================================================== @@ -25,6 +26,15 @@ switch ($submit = form_get_action()) { case 'edit': $action = ACT_EDIT; break; case 'del': $action = ACT_DELETE; break; + case 'filter': + $flt = array(); + $flt['prio'] = gpc_get_enum($_POST, 'flt_prio', array_merge(array_keys($opt_priority), ['-2', '-1'])); + $flt['stat'] = gpc_get_enum($_POST, 'flt_stat', array_merge(array_keys($opt_state), ['-2', '-1'])); + $flt['txt'] = gpc_get_string($_POST, 'flt_txt'); + db_save_filter($flt, 206); + $action = ACT_DEFAULT; + break; + case 'insert': $p[':vid'] = $user->vid; $p[':projid'] = gpc_get_int($_POST, 'projid'); @@ -39,21 +49,52 @@ switch ($submit = form_get_action()) { case 'update': $p[':taskid'] = $id; $p[':projid'] = gpc_get_int($_POST, 'projid'); - $p[':plandate'] = gpc_get_string($_POST, 'plandate'); - $p[':duedate'] = gpc_get_string($_POST, 'duedate'); + $p[':plandate'] = gpc_get_date($_POST, 'plandate'); + $p[':duedate'] = gpc_get_date($_POST, 'duedate'); if ($p[':projid'] == -1) { $p[':projid'] = NULL; } $p[':taskname'] = gpc_get_string($_POST, 'taskname'); $p[':priority'] = gpc_get_string($_POST, 'priority', 10); - if ($p[':priority'] == 'X') { - $p[':projid'] = NULL; + if ($p[':priority'] == '-1') { + $p[':priority'] = NULL; } + $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)); db_exec_update('task', $p, 'taskid'); $action = ACT_VIEW; break; case 'delete': + // Only captain is allowed to delete + if ($user->role != 'captain') { + $g_warning->Add('Only captain is allowed to delete tasks.'); + $action = ACT_VIEW; + break; + } + // Security token needed! + if (gpc_get_string($_POST, 'token', 16) != $_SESSION['token']) { + $g_error->Add(_('Delete prohibited, invalid security token!')); + $action = ACT_VIEW; + break; + } + unset($_SESSION['token']); + // get information for possible redirect + $sth = $pdo->prepare("SELECT projid FROM task WHERE taskid=?"); + $sth->execute([$id]); + $task = $sth->fetch(PDO::FETCH_OBJ); + if (isset($task->projid)) { + $backlink = 'project.php?id='.$task->projid; + } + // now really delete + $sth = $pdo->prepare("DELETE FROM task WHERE taskid=?"); + $sth->execute([$id]); + $g_success->Add(_('Task deleted')); + if (isset($backlink)) { + header_location($backlink, ['info' => _('Note deleted.')]); + } + $action = ACT_DEFAULT; break; default: @@ -71,20 +112,82 @@ require 'header.php'; if ($action == ACT_DEFAULT): // ========== VARIANT: default behavior ======================================= -echo "

$pagetitle

\n"; +page_caption_search($pagetitle); + +// load filter from db +$flt = db_get_filter($user->id, 206); + +$w = array('(t.vid=:vid OR t.vid IS NULL)'); +$p = array(':vid' => $user->vid); +if (strlen($flt->txt) > 1) { + $w[] = '(taskname LIKE :txt)'; + $p[':txt'] = '%'.$flt->txt.'%'; +} +if (strlen($flt->prio) > 2 ) { + $w[] = 'priority=:priority'; + $p[':priority'] = $flt->prio; +} elseif ($flt->prio == -1) { + $w[] = 'priority IS NULL'; +} +if (strlen($flt->stat) > 2 ) { + $w[] = 'taskstate=:taskstate'; + $p[':taskstate'] = $flt->stat; +} +$where = join(' AND ', $w); +$order = ' ORDER BY t.taskid'; + +// get total recond count for pagination and limit +$sql = "SELECT COUNT(*) FROM task"; +if ($where) $sql .= " WHERE $where"; -$sql = "SELECT t.taskid, t.projid, t.taskname, t.priority, p.projname " - . "FROM task AS t LEFT JOIN project AS p USING (projid) " - . "WHERE p.projid IS NULL OR p.vid=? " - . "ORDER BY t.taskid"; $sth = $pdo->prepare($sql); try { - $sth->execute([$user->vid]); + $sth->execute($p); +} catch(PDOException $e) { + $g_error->Add($e->getMessage()); + $g_error->Add($sql); + $g_error->Add(print_r($p, true)); +} +$numrows = $sth->fetchColumn(); +$lastpage = ceil($numrows/$g_rows_pp); +$page = gpc_get_int($_REQUEST, 'p', 1); + +$sql = "SELECT t.taskid, t.vid, t.projid, t.taskname, t.priority, t.taskstate," + . " p.projname " + . "FROM task AS t LEFT JOIN project AS p USING (projid) " + . "WHERE $where"; +if ($order) $sql .= $order; + +// if pagination: +// $sql .= ' LIMIT ' . ($page - 1) * $g_rows_pp . ',' . $g_rows_pp; +$sth = $pdo->prepare($sql); +try { + $sth->execute($p); } catch (PDOexception $e) { $g_error->Add('SQL-Error: '. $e->getMessage()); + $g_error->Add($sql); + $g_error->Add(print_r($p, true)); } $res = $sth->fetchAll(); +?> +
+
+
Filter
+
+prio); +filter_create_select('flt_stat', _('State'), $g_opt_all + $opt_state, $flt->stat); +?> + + + + +
+
+
+', "\n"; echo "
#', _('Task'), "', _('Project'), "', _('Priority'), "', _('Status'), "
", $row['taskid'], "", $row['vid'] ? $row['taskid'] : '('.$row['taskid'].')', "", $row['taskname'], "", $row['projname'], "", ($opt_priority[$row['priority']] ?? ''), "", ($opt_state[$row['taskstate']]), "
', "\n"; -echo '\n"; +echo '\n"; echo '\n"; echo '\n"; echo '\n"; echo '\n"; echo '\n"; echo '\n"; +echo '\n"; echo "
', _('Task'),"", $task->taskname, "
', _('Task'),"", $task->taskname, "
', _('Project'),"", ($task->projname ?? _('unassigned')), "
', _('Priority'),"", ($task->priority ?? _('none')), "
', _('Plan date'),"", $task->plandate, "
', _('Due date'),"", $task->duedate, "
', _('Started at'),"", $task->started, "
', _('Finished at'),"", $task->finished, "
', _('Status'),"", $opt_state[$task->taskstate], "
\n"; form_view_buttons($g_scriptname, $id); -echo "

Annotations

"; +echo '

', _('Annotations'), "

"; $sql = "SELECT noteid, annotation " . "FROM note " @@ -184,13 +291,14 @@ echo '\n"; echo "
\n"; -echo "

Documents

"; -echo "

Not yet implemented

"; +echo '

', _('Documents'), "

"; +echo '

', _('Not yet implemented'), "

"; elseif ($action == ACT_EDIT): // ========== VARIANT: edit single record ===================================== -$sql = "SELECT taskname, projid, priority, plandate, duedate, started, finished " +$sql = "SELECT taskname, projid, priority, plandate, duedate, started, finished," + . " taskstate " . "FROM task " . "WHERE taskid=?"; $sth = $pdo->prepare($sql); @@ -228,13 +336,26 @@ form_create_select('priority', _('Priority'), $opt_none + $opt_priority, $task->
taskstate); + form_edit_buttons($g_scriptname, $id); echo "\n"; elseif ($action == ACT_DELETE): // ========== VARIANT: delete record ========================================== +$sql = "SELECT taskname FROM task WHERE taskid=?"; +$sth = $pdo->prepare($sql); +$sth->execute([$id]); +$task = $sth->fetch(PDO::FETCH_OBJ); + echo '

', _('Delete Task'), "

\n"; +echo '

', sprintf(_('Task no. %d'), $id), "

\n"; +echo '

', $task->taskname, "

"; + +echo '

', _('Deleting a task item is final. There is no way back. Only delete if you are absolute sure.'), "

\n"; +$_SESSION['token'] = bin2hex(random_bytes(8)); +form_delete_buttons($g_scriptname, $id, $_SESSION['token']); else: // ========== ERROR UNKNOWN VARIANT ===========================================