First web gui prototype
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
*~
|
||||||
|
__pycache__/
|
||||||
|
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
YMS Installation
|
||||||
|
|
||||||
|
1. Install requirements
|
||||||
|
|
||||||
|
1.1 Generic
|
||||||
|
- MariaDB
|
||||||
|
- Python 3
|
||||||
|
- python3-bcrypt
|
||||||
|
- optional
|
||||||
|
- mupdf-tools for extended pdf file management
|
||||||
|
|
||||||
|
1.2 Native GUI
|
||||||
|
- Python GTK3
|
||||||
|
|
||||||
|
1.3 Web GUI
|
||||||
|
- Webserver
|
||||||
|
- PHP
|
||||||
|
|
||||||
|
|
||||||
|
2. Create database
|
||||||
|
|
||||||
|
Create a database for YMS on your server, as well as a MariaDB user who has
|
||||||
|
the privileges for accessing and modifying it.
|
||||||
|
|
||||||
|
CREATE DATABASE yms;
|
||||||
|
|
||||||
|
Create database-user for application with minimum necessary rights.
|
||||||
|
|
||||||
|
CREATE USER 'yms'@'localhost' IDENTIFIED BY '********';
|
||||||
|
GRANT SELECT, INSERT, UPDATE, DELETE ON yms.* TO 'yms'@'localhost';
|
||||||
|
|
||||||
|
3. Run database import
|
||||||
|
|
||||||
|
Import the mariadb.sql file into your database, which will create the tables
|
||||||
|
|
||||||
|
mariadb yms < mariadb.sql
|
||||||
|
|
||||||
|
Optional import some sample data
|
||||||
|
|
||||||
|
mariadb yms < mariadb_sample.sql
|
||||||
|
|
||||||
|
4. Initialize document storage
|
||||||
|
Customize path and accessrights to your needs
|
||||||
|
|
||||||
|
mkdir /var/local/yms
|
||||||
|
mkdir /var/local/yms/thumb
|
||||||
|
chown -R www-data /var/local/yms
|
||||||
|
chmod -R 750 /var/local/yms
|
||||||
|
|
||||||
|
5. Upload webgui files
|
||||||
|
|
||||||
|
Upload all files and directories (except the install directory) to your
|
||||||
|
webserver.
|
||||||
|
Disallow access to include files (.inc). There is an example _htaccess
|
||||||
|
file.
|
||||||
|
|
||||||
|
6. Create and edit webgui config file
|
||||||
|
|
||||||
|
Rename sample configfile config.php-sample:
|
||||||
|
|
||||||
|
mv config.inc-sample config.inc
|
||||||
|
|
||||||
|
Open config.inc in a text editor and fill in your database details.
|
||||||
|
|
||||||
|
7. Check file access rights for security
|
||||||
|
|
||||||
|
Configfile should be readable by webserver but not writeable.
|
||||||
|
|
||||||
|
chmod 640 config.inc
|
||||||
|
chgrp www-data config.inc
|
||||||
|
|
||||||
|
8. Start using YMS
|
||||||
|
|
||||||
|
Start your browser and login to YMS with the default username/password:
|
||||||
|
captain/captain
|
||||||
|
|
||||||
+275
@@ -0,0 +1,275 @@
|
|||||||
|
/* SPDX-License-Identifier: WTFPL */
|
||||||
|
|
||||||
|
/* MariaDB Scheme
|
||||||
|
Version: 1 */
|
||||||
|
|
||||||
|
CREATE TABLE user (
|
||||||
|
userid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
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',
|
||||||
|
flags SET('deleted','locked'),
|
||||||
|
language CHAR(2) NOT NULL DEFAULT 'en',
|
||||||
|
PRIMARY KEY (userid),
|
||||||
|
UNIQUE INDEX ix_login (login)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Settings
|
||||||
|
E.g. the currently selected boat. Users logged in via the web are allowed
|
||||||
|
to write to this table. Therefore a separate table and not additional
|
||||||
|
fields in the user data record.
|
||||||
|
|
||||||
|
userid=0: Global program settings
|
||||||
|
sno=0: db_scheme_version
|
||||||
|
sno=1: doc_base_path
|
||||||
|
|
||||||
|
userid = -1: description of user settings for development and admin use
|
||||||
|
|
||||||
|
userid >=1: setings per user
|
||||||
|
sno=1 current vessel
|
||||||
|
|
||||||
|
*/
|
||||||
|
CREATE TABLE settings (
|
||||||
|
userid SMALLINT(6) NOT NULL,
|
||||||
|
sno SMALLINT(6) NOT NULL,
|
||||||
|
valstr VARCHAR(200) DEFAULT NULL,
|
||||||
|
valint INT(10) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (userid, sno)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ddid=0 is list of lists, not editable
|
||||||
|
flags: fixed=not deletable, value not changeable
|
||||||
|
locked=not editable */
|
||||||
|
CREATE TABLE dropdown (
|
||||||
|
ddid TINYINT(3) UNSIGNED NOT NULL,
|
||||||
|
ddval TINYINT(3) NOT NULL,
|
||||||
|
sort TINYINT(3) DEFAULT NULL,
|
||||||
|
ddtext VARCHAR(50) NOT NULL,
|
||||||
|
ddshort VARCHAR(4) DEFAULT NULL,
|
||||||
|
color CHAR(6) DEFAULT NULL,
|
||||||
|
flags ENUM('locked', 'fixed') DEFAULT NULL,
|
||||||
|
PRIMARY KEY (ddid, ddval)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE vessel (
|
||||||
|
vid SMALLINT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
vtype ENUM('mono','cat','tri') NOT NULL DEFAULT 'mono',
|
||||||
|
vesselname VARCHAR(40) NOT NULL,
|
||||||
|
model VARCHAR(20) DEFAULT NULL,
|
||||||
|
loa FLOAT(4,2) UNSIGNED DEFAULT NULL,
|
||||||
|
lwl FLOAT(4,2) UNSIGNED DEFAULT NULL,
|
||||||
|
beam FLOAT(4,2) UNSIGNED DEFAULT NULL,
|
||||||
|
draught FLOAT(3,2) UNSIGNED DEFAULT NULL,
|
||||||
|
draught_min FLOAT(3,2) UNSIGNED DEFAULT NULL,
|
||||||
|
displacement SMALLINT(6) UNSIGNED DEFAULT NULL,
|
||||||
|
ballast SMALLINT(6) UNSIGNED DEFAULT NULL,
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (vid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE storage (
|
||||||
|
sid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
vid SMALLINT(6) NOT NULL DEFAULT 1,
|
||||||
|
sname VARCHAR(40) NOT NULL,
|
||||||
|
stype TINYINT(3) NOT NULL DEFAULT 0,
|
||||||
|
capacity SMALLINT(6) DEFAULT NULL,
|
||||||
|
capaunit ENUM('kg', 'l') DEFAULT NULL,
|
||||||
|
x SMALLINT(6) NOT NULL DEFAULT 0,
|
||||||
|
y SMALLINT(6) NOT NULL DEFAULT 0,
|
||||||
|
z SMALLINT(6) NOT NULL DEFAULT 0,
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (sid)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* TODO define cabins? CREATE TABLE cabin ... */
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE tag (
|
||||||
|
tagid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
tagname VARCHAR(20) NOT NULL,
|
||||||
|
color CHAR(6) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (tagid),
|
||||||
|
UNIQUE INDEX ix_tagname (tagname)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE tagref (
|
||||||
|
tagid SMALLINT(6) NOT NULL,
|
||||||
|
objid SMALLINT(6) NOT NULL,
|
||||||
|
objtype ENUM('equip','inv','prov','doc') NOT NULL,
|
||||||
|
PRIMARY KEY (tagid, objid, objtype)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* TODO Boxes can be nested via parent
|
||||||
|
TODO boxsize: (LxWxH) in cm? */
|
||||||
|
CREATE TABLE box (
|
||||||
|
boxid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
sid SMALLINT(6) NOT NULL,
|
||||||
|
parent INT(10) DEFAULT NULL,
|
||||||
|
label VARCHAR(20) DEFAULT NULL,
|
||||||
|
color CHAR(6) DEFAULT NULL,
|
||||||
|
content VARCHAR(60) DEFAULT NULL,
|
||||||
|
weight FLOAT(5,2) UNSIGNED DEFAULT NULL,
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (boxid),
|
||||||
|
INDEX ix_label (label)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE equipment (
|
||||||
|
eid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
vid SMALLINT(6) NOT NULL DEFAULT 1,
|
||||||
|
ename VARCHAR(80) NOT NULL,
|
||||||
|
make VARCHAR(40),
|
||||||
|
model VARCHAR(40),
|
||||||
|
ecat TINYINT(3) DEFAULT NULL,
|
||||||
|
serial VARCHAR(30),
|
||||||
|
supplier SMALLINT(6) DEFAULT NULL,
|
||||||
|
manufacturer SMALLINT(6) DEFAULT NULL,
|
||||||
|
purchdate DATE DEFAULT NULL,
|
||||||
|
price DECIMAL(12,2) DEFAULT NULL,
|
||||||
|
weight FLOAT(5,2) UNSIGNED DEFAULT NULL,
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
PRIMARY KEY(eid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE inventory (
|
||||||
|
invid INT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
invname VARCHAR(80) NOT NULL,
|
||||||
|
boxtype ENUM('storage','box') NOT NULL DEFAULT 'storage',
|
||||||
|
sid SMALLINT(6) NOT NULL DEFAULT 1,
|
||||||
|
boxid SMALLINT(6) NOT NULL DEFAULT 1,
|
||||||
|
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',
|
||||||
|
PRIMARY KEY (invid),
|
||||||
|
INDEX ix_invname (invname)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE measurement (
|
||||||
|
mid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
mname VARCHAR(80) NOT NULL,
|
||||||
|
nval TINYINT(1) UNSIGNED NOT NULL DEFAULT 1,
|
||||||
|
val1 INT(10) NOT NULL,
|
||||||
|
val2 INT(10) NOT NULL,
|
||||||
|
val3 INT(10) NOT NULL,
|
||||||
|
unit TINYINT(3) NOT NULL DEFAULT 1,
|
||||||
|
accuracy ENUM('unknown', 'precise', 'normal', 'rough', 'estimated') NOT NULL DEFAULT 'unknown',
|
||||||
|
mdate DATE DEFAULT NULL,
|
||||||
|
note VARCHAR(80) DEFAULT NULL,
|
||||||
|
eid SMALLINT(6) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (mid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE provisions (
|
||||||
|
provid INT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
provname VARCHAR(40) NOT NULL,
|
||||||
|
sid SMALLINT(6) DEFAULT NULL,
|
||||||
|
number SMALLINT(6) UNSIGNED NOT NULL DEFAULT 1,
|
||||||
|
unit TINYINT(3) DEFAULT NULL,
|
||||||
|
storedate DATE DEFAULT CURRENT_DATE,
|
||||||
|
shelflife DATE DEFAULT NULL,
|
||||||
|
PRIMARY KEY (provid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE document (
|
||||||
|
docid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
doctype ENUM('generic', 'manual', 'invoice', 'drawing', 'picture') NOT NULL DEFAULT 'generic',
|
||||||
|
mimetype VARCHAR(80) NOT NULL DEFAULT 'application/octet-stream',
|
||||||
|
filename VARCHAR(200) NOT NULL,
|
||||||
|
extension CHAR(3) NOT NULL,
|
||||||
|
hash VARCHAR(32) NOT NULL,
|
||||||
|
docsize INT(10) unsigned NOT NULL,
|
||||||
|
doctime DATETIME DEFAULT NULL,
|
||||||
|
title VARCHAR(40) DEFAULT NULL,
|
||||||
|
pages SMALLINT(6) unsigned NOT NULL DEFAULT 1,
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (docid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE docref (
|
||||||
|
drid INT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
reftype ENUM('vessel', 'box', 'equipment', 'project', 'task') NOT NULL DEFAULT 'vessel',
|
||||||
|
docid SMALLINT(6) NOT NULL,
|
||||||
|
refid SMALLINT(6) NOT NULL,
|
||||||
|
PRIMARY KEY (drid),
|
||||||
|
UNIQUE INDEX ix_docref (docid, refid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE company (
|
||||||
|
compid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
compname VARCHAR(40) NOT NULL,
|
||||||
|
comptype TINYINT(3) NOT NULL DEFAULT 1,
|
||||||
|
street VARCHAR(30),
|
||||||
|
zip VARCHAR(10),
|
||||||
|
city VARCHAR(30),
|
||||||
|
country VARCHAR(30),
|
||||||
|
contact VARCHAR(30),
|
||||||
|
phone VARCHAR(30),
|
||||||
|
email VARCHAR(50),
|
||||||
|
web VARCHAR(40),
|
||||||
|
customerno VARCHAR(20),
|
||||||
|
contractno VARCHAR(20),
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (compid),
|
||||||
|
UNIQUE INDEX ix_compname (compname)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO optional field: plan date, target date, completion date */
|
||||||
|
CREATE TABLE maintenance (
|
||||||
|
maintid INT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
vid SMALLINT(6) NOT NULL DEFAULT 1,
|
||||||
|
eid SMALLINT(6) DEFAULT NULL,
|
||||||
|
series SMALLINT(6) DEFAULT NULL,
|
||||||
|
activities VARCHAR(40) NOT NULL,
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
maintstate ENUM('new','planned','ongoing','done') NOT NULL DEFAULT 'new',
|
||||||
|
PRIMARY KEY (maintid)
|
||||||
|
);
|
||||||
|
|
||||||
|
/* TODO? time recording */
|
||||||
|
|
||||||
|
CREATE TABLE project (
|
||||||
|
projid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
projname VARCHAR(40) NOT NULL,
|
||||||
|
vid SMALLINT(6) NOT NULL DEFAULT 1,
|
||||||
|
responsible SMALLINT(6) NOT NULL,
|
||||||
|
startdate date DEFAULT NULL,
|
||||||
|
duration SMALLINT(6) UNSIGNED DEFAULT NULL,
|
||||||
|
costs_plan DECIMAL(12,2) DEFAULT NULL,
|
||||||
|
costs_final DECIMAL(12,2) DEFAULT NULL,
|
||||||
|
remarks VARCHAR(150) DEFAULT NULL,
|
||||||
|
projstate ENUM('new','plan','ongoing','finished') NOT NULL DEFAULT 'new',
|
||||||
|
PRIMARY KEY (projid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE task (
|
||||||
|
taskid INT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
projid SMALLINT(6) DEFAULT NULL,
|
||||||
|
taskname VARCHAR(60) NOT NULL,
|
||||||
|
taskstate ENUM('new','finished') NOT NULL DEFAULT 'new',
|
||||||
|
PRIMARY KEY (taskid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE checklist (
|
||||||
|
clid SMALLINT(6) NOT NULL AUTO_INCREMENT,
|
||||||
|
title VARCHAR(30) NOT NULL,
|
||||||
|
clstate ENUM('new','open','closed') NOT NULL DEFAULT 'new',
|
||||||
|
PRIMARY KEY (clid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE checkitem (
|
||||||
|
checkid INT(10) NOT NULL AUTO_INCREMENT,
|
||||||
|
checkname VARCHAR(60) NOT NULL,
|
||||||
|
groupid TINYINT(3) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (checkid)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE checkref (
|
||||||
|
clid SMALLINT(6) NOT NULL,
|
||||||
|
checkid INT(10) NOT NULL,
|
||||||
|
sort SMALLINT(6) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (clid, checkid)
|
||||||
|
);
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* Generic data suitable for all kind of boats
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* absolutely minimal data set */
|
||||||
|
|
||||||
|
-- Trick to get pk value 0 for autoincrement
|
||||||
|
INSERT INTO user (userid, login, pass, displayname, role) VALUES (0, '', '', 'SYSTEM', 'vessel');
|
||||||
|
UPDATE user SET userid=0 WHERE userid=1;
|
||||||
|
|
||||||
|
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
|
||||||
|
(1, 1, 0); -- Keine Bootszuordnung für Benutzer "captain"
|
||||||
|
|
||||||
|
/* Liste der Listen wird immer benötigt */
|
||||||
|
INSERT INTO dropdown (ddid, ddval, ddtext) VALUES
|
||||||
|
(0, 0, 'Liste der Listen'),
|
||||||
|
(0, 1, 'Rumpftypen'),
|
||||||
|
(0, 2, 'Firmentypen'),
|
||||||
|
(0, 3, 'Stauraumtypen'),
|
||||||
|
(0, 4, 'Ausrüstungskategorien'),
|
||||||
|
(0, 5, 'Proviantkategorien'),
|
||||||
|
(0, 6, 'Provianteinheiten'),
|
||||||
|
(0, 7, 'Sicherungstypen'),
|
||||||
|
(0, 8 , 'Einheiten');
|
||||||
|
|
||||||
|
INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
|
||||||
|
(2, 1, 'Lieferant', 'fixed'),
|
||||||
|
(2, 2, 'Hersteller', 'fixed'),
|
||||||
|
(2, 9, 'Sonstiges', 'fixed');
|
||||||
|
|
||||||
|
INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
|
||||||
|
(3, 0, 'Stauraum allgemein', 'fixed'),
|
||||||
|
(3, 1, 'Tank', 'fixed');
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* Generic data suitable for all kind of boats
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* absolutely minimal data set */
|
||||||
|
|
||||||
|
-- Trick to get pk value 0 for autoincrement
|
||||||
|
INSERT INTO user (userid, login, pass, displayname, role) VALUES (0, '', '', 'SYSTEM', 'vessel');
|
||||||
|
UPDATE user SET userid=0 WHERE userid=1;
|
||||||
|
|
||||||
|
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), -- Database schema version
|
||||||
|
(1, 1, 0); -- No vessel for captain
|
||||||
|
|
||||||
|
/* list of lists needed */
|
||||||
|
INSERT INTO dropdown (ddid, ddval, ddtext) VALUES
|
||||||
|
(0, 0, 'list of lists'),
|
||||||
|
(0, 1, 'hull type'),
|
||||||
|
(0, 2, 'company type'),
|
||||||
|
(0, 3, 'storage type'),
|
||||||
|
(0, 4, 'equipment category'),
|
||||||
|
(0, 5, 'provision category'),
|
||||||
|
(0, 6, 'provision unit'),
|
||||||
|
(0, 7, 'fuse type'),
|
||||||
|
(0, 8 , 'unit');
|
||||||
|
|
||||||
|
INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
|
||||||
|
(2, 1, 'Supplier', 'fixed'),
|
||||||
|
(2, 2, 'Manufacturer', 'fixed'),
|
||||||
|
(2, 9, 'Generic', 'fixed');
|
||||||
|
|
||||||
|
INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
|
||||||
|
(3, 0, 'Generic', 'fixed'),
|
||||||
|
(3, 1, 'Tank', 'fixed');
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
from getpass import getpass
|
||||||
|
import bcrypt
|
||||||
|
|
||||||
|
newpass = getpass('New Password: ')
|
||||||
|
cryptpass = bcrypt.hashpw(newpass.encode(), bcrypt.gensalt())
|
||||||
|
print("UPDATE user SET pass='{}' WHERE userid=1".format(cryptpass.decode()))
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<FilesMatch "\.inc$">
|
||||||
|
Require all denied
|
||||||
|
</FilesMatch>
|
||||||
+5
File diff suppressed because one or more lines are too long
+6
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
+7
File diff suppressed because one or more lines are too long
+253
@@ -0,0 +1,253 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Boxes');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
// Storage options
|
||||||
|
$sql = "SELECT sid, sname FROM storage WHERE vid=? ORDER BY sname";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
$opt_storage = array();
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
$opt_storage[$row['sid']] = $row['sname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$p[':label'] = gpc_get_string($_POST, 'label');
|
||||||
|
$p[':sid'] = gpc_get_int($_POST, 'sid');
|
||||||
|
$p[':content'] = gpc_get_string($_POST, 'content');
|
||||||
|
$p[':remarks'] = gpc_get_string($_POST, 'remarks');
|
||||||
|
$keys = array_keys($p);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':'); }, $keys));
|
||||||
|
$pnames = join(',', $keys);
|
||||||
|
$sth = $pdo->prepare("INSERT INTO box ($fields) VALUES ($pnames)");
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$id = $pdo->LastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$p[':label'] = gpc_get_string($_POST, 'label');
|
||||||
|
$p[':content'] = gpc_get_string($_POST, 'content');
|
||||||
|
$p[':color'] = gpc_get_color($_POST, 'color');
|
||||||
|
$p[':weight'] = min(gpc_get_float($_POST, 'weight'), 99.99);
|
||||||
|
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':') . '=' . $s; }, array_keys($p)));
|
||||||
|
$sth = $pdo->prepare("UPDATE box SET $fields WHERE boxid=:boxid");
|
||||||
|
$p[':boxid'] = $id;
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_("Unknown function '%s'!"), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT boxid, sid, label, color, content, weight, remarks "
|
||||||
|
. "FROM box "
|
||||||
|
. "ORDER BY label";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<th>" . _('Label') . "</th>";
|
||||||
|
echo "<th>" . _('Color') . "</th>";
|
||||||
|
echo "<th>" . _('Content') . "</th>";
|
||||||
|
echo '<th class="text-end">', _('Weight'), "</th>";
|
||||||
|
echo "<td></td>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>". $row['label'] ."</td>\n";
|
||||||
|
$style = 'background-color:#' . $row['color'];
|
||||||
|
if (get_color_brightness($row['color']) < 0.4) {
|
||||||
|
$style .= ';color:white';
|
||||||
|
}
|
||||||
|
echo '<td><span style="', $style,'">#'. $row['color'] ."</span></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']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
// Table summary
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="4">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button('box.php');
|
||||||
|
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Box'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="sid" class="form-label"><?=_('Storage')?></label>
|
||||||
|
<select name="sid" id="sid" class="form-control">
|
||||||
|
<?php
|
||||||
|
foreach ($opt_storage as $k => $v) {
|
||||||
|
echo '<option value="', $k, '">', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="content" class="form-label"><?=_('Content')?></label>
|
||||||
|
<input type="text" maxlength="60" class="form-control" id="content" name="content">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT label, content, color, weight, remarks "
|
||||||
|
. "FROM box "
|
||||||
|
. "WHERE boxid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$box = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', $box->label, "</h2>\n";
|
||||||
|
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th style="width:20%">', _('Content'),"</th><td>", $box->content, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Color'), '</th><td style="background-color:#', $box->color, '">#', $box->color, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Weight'), '</th><td>', format_float($box->weight, 2, 'kg'), "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Remarks'),"</th><td>", $box->remarks, "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
// Inventory in box
|
||||||
|
// WIP
|
||||||
|
$sql = "SELECT invid, invname FROM inventory WHERE boxtype='box' AND boxid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
|
||||||
|
echo '<h3>', _('Inventory in box'), "</h3>\n";
|
||||||
|
if ($res) {
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo '<th>', _('Inventory'), "</th>";
|
||||||
|
echo "<td></td>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>", $row['invname'], "</td>\n";
|
||||||
|
form_action_buttons('inventory.php', $row['invid']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "</table>\n";
|
||||||
|
} else {
|
||||||
|
echo '<p>', _('Box is empty'), "</p>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT label, content, color, weight, remarks "
|
||||||
|
. "FROM box "
|
||||||
|
. "WHERE boxid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$box = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit Box'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="label" class="form-label"><?=_('Label')?></label>
|
||||||
|
<input type="text" class="form-control" id="label" name="label" value="<?=$box->label ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="content" class="form-label"><?=_('Content')?></label>
|
||||||
|
<input type="text" class="form-control" id="content" name="content" value="<?=$box->content ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="color"><?=_('Color')?></label>
|
||||||
|
<input type="color" class="form-control" id="color" name="color" value="#<?=$box->color ?>">
|
||||||
|
</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($box->weight); ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$box->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
form_edit_buttons($g_scriptname, $id);
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Checklists');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<p>Search will be implemented later.
|
||||||
|
This page is currently just a placeholder.</p>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,338 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle=_('Company');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
$opt_comptype = db_get_options(2);
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$compname = gpc_get_string($_POST, 'compname');
|
||||||
|
$comptype = gpc_get_int($_POST, 'comptype');
|
||||||
|
$sql = "INSERT INTO company "
|
||||||
|
. " (compname, comptype) "
|
||||||
|
. "VALUES "
|
||||||
|
. " (:compname, :comptype)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':compname', $compname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':comptype', $comptype, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
$id = $pdo->lastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$compname = gpc_get_string($_POST, 'compname');
|
||||||
|
$comptype = gpc_get_int($_POST, 'comptype');
|
||||||
|
$street = gpc_get_string($_POST, 'street', 30);
|
||||||
|
$zip = gpc_get_string($_POST, 'zip', 10);
|
||||||
|
$city = gpc_get_string($_POST, 'city', 30);
|
||||||
|
$country = gpc_get_string($_POST, 'country', 30);
|
||||||
|
$contact = gpc_get_string($_POST, 'contact', 30);
|
||||||
|
$phone = gpc_get_string($_POST, 'phone', 30);
|
||||||
|
$email = gpc_get_string($_POST, 'email', 50);
|
||||||
|
$web = gpc_get_string($_POST, 'web', 40);
|
||||||
|
$customerno = gpc_get_string($_POST, 'customerno', 20);
|
||||||
|
$contractno = gpc_get_string($_POST, 'contractno', 20);
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "UPDATE company "
|
||||||
|
. "SET compname=:compname,"
|
||||||
|
. " comptype=:comptype,"
|
||||||
|
. " street=:street,"
|
||||||
|
. " zip=:zip,"
|
||||||
|
. " city=:city,"
|
||||||
|
. " country=:country,"
|
||||||
|
. " contact=:contact,"
|
||||||
|
. " phone=:phone,"
|
||||||
|
. " email=:email,"
|
||||||
|
. " web=:web,"
|
||||||
|
. " customerno=:customerno,"
|
||||||
|
. " contractno=:contractno,"
|
||||||
|
. " remarks=:remarks "
|
||||||
|
. "WHERE compid=:compid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':compid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':compname', $compname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':comptype', $comptype, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':street', $street, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':zip', $zip, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':city', $city, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':country', $country, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':contact', $contact, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':phone', $phone, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':email', $email, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':web', $web, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':customerno', $customerno, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':contractno', $contractno, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
$sth->execute();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// 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']);
|
||||||
|
$sth = $pdo->prepare("DELETE FROM company WHERE compid=?");
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$g_message->Add(sprintf(_('Deleted company no. %d'), $id));
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_('Unknown function!'), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
echo '<h1>', $pagetitle , "</h1>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT compid, compname, comptype, remarks "
|
||||||
|
. "FROM company "
|
||||||
|
. "ORDER BY comptype, compname";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<th>" . _('Name') . "</th>";
|
||||||
|
echo "<th>" . _('Type') . "</th>";
|
||||||
|
echo "<th>" . _('Remarks') . "</th>";
|
||||||
|
echo "<th> </th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
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>";
|
||||||
|
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'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Company'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="compname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="compname" name="compname">
|
||||||
|
</div>
|
||||||
|
<?php form_create_select('comptype', _('Company type'), $opt_comptype); ?>
|
||||||
|
<button type="submit" name="submit[insert]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT compname, comptype, street, zip, city, country,"
|
||||||
|
. " contact, phone, email, web, customerno, contractno, remarks "
|
||||||
|
. "FROM company "
|
||||||
|
. "WHERE compid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$company = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo "<h2>", $company->compname, "</h2>\n";
|
||||||
|
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th scope="row">', _('Name'),"</th><td>", $company->compname, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Type'),"</th><td>", $opt_comptype[$company->comptype], "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Street'),"</th><td>", $company->street, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Zip, City'),"</th><td>", $company->zip, ' ', $company->city, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Country'),"</th><td>", $company->country, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Contact'),"</th><td>", $company->contact, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Phone'),"</th><td>", $company->phone, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Email'),"</th><td>", $company->email, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Web'),"</th><td>", $company->web, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Customer no.'),"</th><td>", $company->customerno, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Contract no.'),"</th><td>", $company->contractno, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Remarks'),"</th><td>", $company->remarks, "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
// show referenced equipment
|
||||||
|
$sql = "SELECT ename FROM equipment WHERE supplier=:id OR manufacturer=:id";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':id', $id, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
if ($sth->rowCount > 0) {
|
||||||
|
echo "<p>Referenced in equipment:</p>\n";
|
||||||
|
echo "<ul>\n";
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
echo "<li>", $row['ename'], "</li>\n";
|
||||||
|
}
|
||||||
|
echo "</ul>\n";
|
||||||
|
} else {
|
||||||
|
echo '<p>', _('Not referenced in any equipment'), "<p>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit Company'), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT compname, comptype, street, zip, city, country,"
|
||||||
|
. " contact, phone, email, web, customerno, contractno, remarks "
|
||||||
|
. "FROM company "
|
||||||
|
. "WHERE compid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$company = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="compname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="compname" name="compname" value="<?=$company->compname ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="comptype" class="form-label"><?=_('Company type')?></label>
|
||||||
|
<select name="comptype" class="form-control">
|
||||||
|
<?php
|
||||||
|
foreach ($opt_comptype as $k => $v) {
|
||||||
|
echo '<option value="', $k ,'"';
|
||||||
|
if ($company->comptype == $k) {
|
||||||
|
echo ' selected';
|
||||||
|
}
|
||||||
|
echo '>', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="street" class="form-label"><?=_('Street')?></label>
|
||||||
|
<input type="text" class="form-control" id="street" name="street" value="<?=$company->street ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="zip" class="form-label"><?=_('Zip')?></label>
|
||||||
|
<input type="text" class="form-control" id="zip" name="zip" value="<?=$company->zip ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="city" class="form-label"><?=_('City')?></label>
|
||||||
|
<input type="text" class="form-control" id="city" name="city" value="<?=$company->city ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="country" class="form-label"><?=_('Country')?></label>
|
||||||
|
<input type="text" class="form-control" id="country" name="country" value="<?=$company->country ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="contact" class="form-label"><?=_('Contact')?></label>
|
||||||
|
<input type="text" class="form-control" id="contact" name="contact" value="<?=$company->contact ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="phone" class="form-label"><?=_('Phone')?></label>
|
||||||
|
<input type="text" class="form-control" id="phone" name="phone" value="<?=$company->phone ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label"><?=_('Email')?></label>
|
||||||
|
<input type="text" class="form-control" id="email" name="email" value="<?=$company->email ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="web" class="form-label"><?=_('Web')?></label>
|
||||||
|
<input type="text" class="form-control" id="web" name="web" value="<?=$company->web ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="customerno" class="form-label"><?=_('Customer no.')?></label>
|
||||||
|
<input type="text" class="form-control" id="customerno" name="customerno" value="<?=$company->customerno ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="contractno" class="form-label"><?=_('Contract no.')?></label>
|
||||||
|
<input type="text" class="form-control" id="contractno" name="contractno" value="<?=$company->contractno ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$company->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit[update]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>?f=view&id=<?=$id?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
$sql = "SELECT compname, remarks FROM company WHERE compid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$company = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete Company'), "</h2>\n";
|
||||||
|
echo '<p>', sprintf(_('Record no. %d'), $id), "</p>\n";
|
||||||
|
echo '<p>Name: ', $company->compname, "</p>";
|
||||||
|
echo '<p>Remarks: ', $company->remarks, "</p>";
|
||||||
|
|
||||||
|
// Still used as a supplier or manufacturer for equipment?
|
||||||
|
$sql = "SELECT COUNT(*) FROM equipment WHERE supplier=:id OR manufacturer=:id";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':id', $id, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
$usecount = $sth->fetchColumn();
|
||||||
|
|
||||||
|
if ($usecount > 0) {
|
||||||
|
echo '<p class="alert alert-warning">', _('Company can not be deleted as there are equipment-references!'), "<p>\n";
|
||||||
|
echo '<a href="', $g_scriptname, '?f=view&id=', $id, '" class="btn btn-secondary">', _('Back'), "</a>\n";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
echo '<p>', _('Deleting a company is final. There is no way back. Only delete if you are absolute sure.'), "</p>\n";
|
||||||
|
$_SESSION['token'] = bin2hex(random_bytes(8));
|
||||||
|
form_delete_buttons($g_scriptname, $id, $_SESSION['token']);
|
||||||
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// ========== GLOBAL CONSTANTS ================================================
|
||||||
|
|
||||||
|
define('APP_TITLE', 'Yacht Management Software');
|
||||||
|
define('APP_TITLE_SHORT', 'YMS');
|
||||||
|
define('APP_SESSION', 'yms');
|
||||||
|
|
||||||
|
// ========== GLOBAL VARIABLES ================================================
|
||||||
|
|
||||||
|
// database connection
|
||||||
|
$g_db_host = 'localhost';
|
||||||
|
$g_db_username = 'yms';
|
||||||
|
$g_db_password = 'changeme!';
|
||||||
|
$g_db_schema = 'yms';
|
||||||
|
|
||||||
|
// mail settings
|
||||||
|
$g_mailto = 'captain@example.com';
|
||||||
|
$g_mailto_webmaster = 'webmaster@example.com';
|
||||||
|
|
||||||
|
// localization
|
||||||
|
$g_timezone = 'Europe/Berlin';
|
||||||
|
$g_locale = 'de_DE.UTF-8';
|
||||||
|
|
||||||
|
// documents and images
|
||||||
|
$g_doc_basepath = '/var/local/yms';
|
||||||
|
$g_doc_maxsize = 1024*1024*16; // 16 MB
|
||||||
|
|
||||||
|
$g_storage_limit = 1024; // MB
|
||||||
|
|
||||||
|
$g_thumb_size = 120;
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
body {
|
||||||
|
font-family: "Noto Sans", "Bitstream Vera Sans", Arial, sans;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
footer {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
.noPrint {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* Document Downloader
|
||||||
|
Doucuments are not directly accessible via filesystem
|
||||||
|
dl.php must be used with docid as parameter:
|
||||||
|
e,g, dl.php?id=23 */
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
|
||||||
|
$docid = gpc_get_int($_GET, 'id');
|
||||||
|
|
||||||
|
$sql = "SELECT doctype, docsize, mimetype, hash, extension, filename FROM document WHERE docid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$docid]);
|
||||||
|
$row = $sth->fetch();
|
||||||
|
$dtmap = array(
|
||||||
|
'generic' => 'doc',
|
||||||
|
'manual' => 'man',
|
||||||
|
'invoice' => 'inv',
|
||||||
|
'picture' => 'pic',
|
||||||
|
'drawing' => 'drw');
|
||||||
|
$file = sprintf("%s/%s-%s.%s", $g_doc_basepath, $dtmap[$row['doctype']], $row['hash'], $row['extension']);
|
||||||
|
|
||||||
|
if (file_exists($file)) {
|
||||||
|
header('Content-Description: File Transfer');
|
||||||
|
header('Content-Type: ' . $row['mimetype']);
|
||||||
|
header('Content-Disposition: attachment; filename="' . $row['filename'] . '"');
|
||||||
|
header('Expires: 0');
|
||||||
|
header('Cache-Control: must-revalidate');
|
||||||
|
header('Pragma: public');
|
||||||
|
if ($row['docsize'] == 0) {
|
||||||
|
header('Content-Length: ' . filesize($file));
|
||||||
|
} else {
|
||||||
|
header('Content-Length: ' . $row['docsize']);
|
||||||
|
}
|
||||||
|
readfile($file);
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
// dynamically create error image
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
@@ -0,0 +1,405 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Documents');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
// WIP New standalone document
|
||||||
|
$title = gpc_get_string($_POST, 'title');
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks');
|
||||||
|
$g_message->Add(print_r($_FILES, true));
|
||||||
|
if (empty($_FILES['files']['tmp_name']) ) {
|
||||||
|
$g_warning->Add(_('No file for upload submitted. Try again by selecting a file first.'));
|
||||||
|
$action = ACT_ADD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$mimetypes = ['image/png', 'image/jpeg', 'image/svg+xml', 'application/pdf'];
|
||||||
|
$nerr = 0;
|
||||||
|
$file_name = $_FILES['files']['name'];
|
||||||
|
$file_tmp = $_FILES['files']['tmp_name'];
|
||||||
|
$file_type = $_FILES['files']['type'];
|
||||||
|
$file_size = $_FILES['files']['size'];
|
||||||
|
$file_ext = strtolower(end(explode('.', $_FILES['files']['name'])));
|
||||||
|
$file_mimetype = mime_content_type($file_tmp);
|
||||||
|
if (!in_array($file_mimetype, $mimetypes)) {
|
||||||
|
$g_error->Add(sprintf(_("Mimetype '%s' not allowed for upload."), $file_mimetype));
|
||||||
|
$action = ACT_ADD;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if ($file_type != $file_mimetype) {
|
||||||
|
$g_warning->Add(sprintf(_("Mimetype mismatch: '%s'."), $file_type));
|
||||||
|
}
|
||||||
|
// ok let's go
|
||||||
|
$file_hash = md5_file($file_tmp);
|
||||||
|
$file_timestamp = date('Y-m-d H:i:s', filemtime($file_tmp));
|
||||||
|
|
||||||
|
// check if the file already exists, in which case issue
|
||||||
|
// a notice and display the existing document
|
||||||
|
$sth = $pdo->prepare("SELECT docid FROM document WHERE hash=?");
|
||||||
|
$sth->execute([$file_hash]);
|
||||||
|
$id = $sth->fetchColumn();
|
||||||
|
if ($id) {
|
||||||
|
$g_warning->Add(_('Document already exists!'));
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch ($file_mimetype) {
|
||||||
|
case 'application/pdf':
|
||||||
|
$file_techname = $g_doc_basepath . '/doc-'.$file_hash.'.'.$file_ext;
|
||||||
|
$doctype = 'generic';
|
||||||
|
break;
|
||||||
|
case 'image/svg+xml':
|
||||||
|
$file_techname = $g_doc_basepath . '/drw-'.$file_hash.'.'.$file_ext;
|
||||||
|
$doctype = 'drawing';
|
||||||
|
break;
|
||||||
|
case 'image/png':
|
||||||
|
case 'image/jpeg':
|
||||||
|
$file_techname = $g_doc_basepath . '/pic-'.$file_hash.'.'.$file_ext;
|
||||||
|
$doctype = 'picture';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$sql = "INSERT INTO document"
|
||||||
|
. " (doctype, filename, extension, hash, doctime, docsize, mimetype) "
|
||||||
|
. "VALUES"
|
||||||
|
. " (?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
try {
|
||||||
|
$sth->execute([$doctype, $file_name, $file_ext, $file_hash, $file_timestamp, $file_size, $file_mimetype]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$id = $pdo->lastInsertId();
|
||||||
|
move_uploaded_file($file_tmp, $file_techname);
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$filename = gpc_get_string($_POST, 'filename');
|
||||||
|
$title = gpc_get_string($_POST, 'title', 40);
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "UPDATE document "
|
||||||
|
. "SET filename=:filename,"
|
||||||
|
. " title=:title,"
|
||||||
|
. " remarks=:remarks "
|
||||||
|
. "WHERE docid=:docid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':docid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':filename', $filename, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':title', $title, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
try {
|
||||||
|
$sth->execute();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// Security token needed!
|
||||||
|
if (gpc_get_string($_POST, 'token', 16) != $_SESSION['token']) {
|
||||||
|
$g_error->Add(_('Delete prohibited, invalid security token!'));
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'addref':
|
||||||
|
$eid = gpc_get_int($_POST, 'eid');
|
||||||
|
$sql = "INSERT INTO docref "
|
||||||
|
. " (docid, refid, reftype) "
|
||||||
|
. "VALUES "
|
||||||
|
. " (:docid, :refid, 'equipment')";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':docid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':refid', $eid, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delref':
|
||||||
|
// remove only link, not critical so get without token is ok
|
||||||
|
$drid = gpc_get_int($_GET, 'drid');
|
||||||
|
$sql = "DELETE FROM docref WHERE drid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$drid]);
|
||||||
|
$g_message->Add(_('Removed document reference'));
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_('Unknown function!'), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
// All documents
|
||||||
|
|
||||||
|
/* TODO show all documents which
|
||||||
|
- are completely unbound: no docref available
|
||||||
|
- assigned to the current boat: docref with doctype vessel
|
||||||
|
- are assigned to an equipment or project of current vesseö
|
||||||
|
There can be multiple docref entries for a document,
|
||||||
|
behavior still needs to be clarified. */
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
|
||||||
|
$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) "
|
||||||
|
. "GROUP BY d.docid, d.doctype, d.filename, d.title";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<th>" . _('ID') . "</th>";
|
||||||
|
echo "<th>" . _('Type') . "</th>";
|
||||||
|
echo "<th>" . _('Filename') . "</th>";
|
||||||
|
echo "<th>" . _('Title') . "</th>";
|
||||||
|
echo "<th>" . _('Links') . "</th>";
|
||||||
|
echo "<th> </th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>". $row['docid'] ."</td>\n";
|
||||||
|
echo "<td>". $row['doctype'] ."</td>\n";
|
||||||
|
echo "<td>". $row['filename'] ."</td>\n";
|
||||||
|
echo "<td>". $row['title'] ."</td>\n";
|
||||||
|
echo "<td>". $row['refcount'] ."</td>\n";
|
||||||
|
// Action buttons
|
||||||
|
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 "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Document'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post" enctype="multipart/form-data" action="<?=$g_scriptname?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="title" class="form-label"><?=_('Title')?></label>
|
||||||
|
<input type="text" class="form-control" id="title" name="title" value="<?=$title?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$remarks?></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="files" class="form-label"><?=_('Document')?></label>
|
||||||
|
<input class="form-control" type="file" id="files" name="files" onchange="preview()">
|
||||||
|
<img id="frame" src="" class="img-fluid">
|
||||||
|
<button class="btn btn-secondary" onclick="clearimg();return false;"><?=_('Clear')?></button>
|
||||||
|
<script>
|
||||||
|
function preview() {
|
||||||
|
var images = ["image/png", "image/jpeg", "image/svg+xml"];
|
||||||
|
console.log(event.target.files[0].type);
|
||||||
|
if (images.indexOf(event.target.files[0].type) > -1) {
|
||||||
|
frame.src = URL.createObjectURL(event.target.files[0]);
|
||||||
|
} else {
|
||||||
|
frame.src = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function clearimg() {
|
||||||
|
document.getElementById('file').value = null;
|
||||||
|
frame.src = "";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
/* mutool: preview of page thumbs */
|
||||||
|
|
||||||
|
$sql = "SELECT docid, doctype, mimetype, filename, extension, hash,"
|
||||||
|
. " docsize, doctime, title, remarks "
|
||||||
|
. "FROM document "
|
||||||
|
. "WHERE docid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$document = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('View Document'), "</h2>\n";
|
||||||
|
|
||||||
|
echo '<table class="table table-borderless">', "\n";
|
||||||
|
echo '<tr><th scope="row" style="width:20%">', _('Document type'),"</th><td>", $document->doctype, "</td></tr>\n";
|
||||||
|
if ($document->doctype == 'picture') {
|
||||||
|
$techname = 'pic-' . $document->hash . '.' . $document->extension;
|
||||||
|
echo '<tr><th scope="row">', _('Preview'), '</th><td>';
|
||||||
|
// echo '<a href="doc/', $techname, '" target="_blank"><img width="', $g_thumb_size, '" src="doc/', $techname, '" alt="', $document->title, '"></a>';
|
||||||
|
echo '<a href="dl.php?id=', $document->docid, '" target="_blank">';
|
||||||
|
echo '<img width="', $g_thumb_size, '" src="dl.php?id=', $document->docid, '" alt="', $document->title, '">';
|
||||||
|
echo '</a>';
|
||||||
|
echo "</td></tr>\n";
|
||||||
|
} elseif (($document->doctype == 'drawing')) {
|
||||||
|
echo '<tr><th scope="row">', _('Drawing'), '</th>';
|
||||||
|
echo '<td><img src="dl.php?id=', $document->docid, '" alt="', $document->title, '"></td></tr>', "\n";
|
||||||
|
} elseif (($document->doctype == 'generic')) {
|
||||||
|
$techname = 'doc-' . $document->hash . '.' . $document->extension;
|
||||||
|
if ($document->mimetype == 'application/pdf') {
|
||||||
|
// TODO show preview of previewpage, ctrate thumbnail if needed
|
||||||
|
|
||||||
|
// Download link
|
||||||
|
echo '<tr><th scope="row">', _('PDF'), '</th><td><a href="dl.php?id=', $document->docid, '">', $document->title ?? _('Download'), "</a></td></tr>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo '<tr><th scope="row">', _('Mimetype'),"</th><td>", $document->mimetype, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Filename'),"</th><td>", $document->filename, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('File size'),"</th><td>", $document->docsize, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Upload date'),"</th><td>", $document->doctime, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Title'),"</th><td>", $document->title, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Remarks'),"</th><td>", $document->remarks, "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
|
||||||
|
echo '<h3>', _('Document references'), "</h3>\n";
|
||||||
|
$sql = "SELECT drid, reftype, ename AS name, eid "
|
||||||
|
. "FROM docref INNER JOIN equipment ON (docref.reftype='equipment' AND docref.refid=equipment.eid) "
|
||||||
|
. "WHERE docid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
echo '<table class="table table-sm">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo '<th style="width:20%">' . _('Type') . "</th>";
|
||||||
|
echo "<th>" . _('Used by') . "</th>";
|
||||||
|
echo "<td></td>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
$eids = array();
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
$eids[] = $row['eid'];
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<td>", $row['reftype'], "</td>";
|
||||||
|
echo "<td>", $row['name'], "</td>";
|
||||||
|
echo "<td>";
|
||||||
|
echo '<a title="', _('Remove'), '" href="', $script, '?f=delref&id=', $id, '&drid=', $row['drid'], '"><i class="bi-trash"></i></a>';
|
||||||
|
echo "</td>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
// Equipment options
|
||||||
|
// Do not include equipment that has already been referenced in the list!
|
||||||
|
$opt_equipment = array();
|
||||||
|
$sql = "SELECT eid, ename FROM equipment WHERE vid=? ORDER BY ename";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
if (!in_array($row['eid'], $eids)) {
|
||||||
|
$opt_equipment[$row['eid']] = $row['ename'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<select name="eid">
|
||||||
|
<?php
|
||||||
|
foreach ($opt_equipment as $k => $v) {
|
||||||
|
echo '<option value="', $k, '">', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-secondary" name="submit[addref]">Referenzieren</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit Document'), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT docid, doctype, filename, extension, hash, title, remarks "
|
||||||
|
. "FROM document "
|
||||||
|
. "WHERE docid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$document = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
if ($document->doctype == 'picture') {
|
||||||
|
echo '<img width="', $g_thumb_size, '" src="doc/pic-', $document->hash, '.', $document->extension, '">';
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="title" class="form-label"><?=_('Filename')?></label>
|
||||||
|
<input type="text" class="form-control" id="filename" name="filename" value="<?=$document->filename ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="title" class="form-label"><?=_('Title')?></label>
|
||||||
|
<input type="text" class="form-control" id="title" name="title" value="<?=$document->title ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$storage->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit[update]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>?f=view&id=<?=$id?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete Document'), "</h2>\n";
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Lists');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0); // list id
|
||||||
|
$v = gpc_get_int($_REQUEST, 'v', -1); // list value id
|
||||||
|
|
||||||
|
function create_ddval_form($script, $ddid, $formtype, $row=NULL) {
|
||||||
|
|
||||||
|
// formtype: insert or update
|
||||||
|
$update = ($formtype == 'update');
|
||||||
|
echo '<form method="post" action="', $script, '">';
|
||||||
|
echo '<input type="hidden" name="id" value="', $ddid, '">';
|
||||||
|
if ($update) {
|
||||||
|
echo '<input type="hidden" name="v" value="', $row['ddval'], '">';
|
||||||
|
}
|
||||||
|
|
||||||
|
// text in one row
|
||||||
|
echo '<div class="form-floating">';
|
||||||
|
echo '<input type="text" name="ddtext" id="ddtext" class="form-control"';
|
||||||
|
if ($update) echo ' value="', $row['ddtext'],'"';
|
||||||
|
echo '><label for="ddtext">Description</label></div>', "\n";
|
||||||
|
|
||||||
|
// all other fields in secondary row
|
||||||
|
echo '<div class="row my-3">';
|
||||||
|
|
||||||
|
echo '<div class="col"><div class="form-floating">';
|
||||||
|
echo '<input type="text" name="ddshort" id="ddshort"class="form-control"';
|
||||||
|
if ($update) echo ' value="', $row['ddshort'],'"';
|
||||||
|
echo '><label for="ddshort">Short description</label></div></div>', "\n";
|
||||||
|
|
||||||
|
echo '<div class="col"><div class="form-floating">';
|
||||||
|
echo '<input type="color" name="color" id="color" class="form-control"';
|
||||||
|
if ($update) echo ' value="', $row['color'],'"';
|
||||||
|
echo '><label for="color">Color</label></div></div>', "\n";
|
||||||
|
|
||||||
|
echo '<div class="col"><div class="form-floating">';
|
||||||
|
echo '<input type="text" name="sort" id="sort" class="form-control"';
|
||||||
|
if ($update) echo ' value="', $row['sort'],'"';
|
||||||
|
echo '><label for="sort">Sort</label></div></div>', "\n";
|
||||||
|
|
||||||
|
echo '</div>'; // finish row
|
||||||
|
|
||||||
|
// buttons
|
||||||
|
echo '<button name="submit" value="', $formtype, '" class="btn btn-primary btn-sm" title="Save"><i class="bi-save"></i> Save</button>';
|
||||||
|
echo ' ';
|
||||||
|
echo '<a href="', $script, '?f=edit&id=', $ddid, '" class="btn btn-secondary btn-sm" title="Cancel"><i class="bi-x-square"></i> Cancel</a>';
|
||||||
|
|
||||||
|
echo "</form>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $v = -2; $action = ACT_EDIT; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$p[':ddid'] = gpc_get_int($_POST, 'id');
|
||||||
|
$sth = $pdo->prepare("SELECT MAX(ddval)+1 FROM dropdown WHERE ddid=?");
|
||||||
|
$sth->execute([$p[':ddid']]);
|
||||||
|
$p[':ddval'] = $sth->fetchColumn() ?? 1;
|
||||||
|
$p[':ddtext'] = gpc_get_string($_POST, 'ddtext');
|
||||||
|
$p[':ddshort'] = gpc_get_string($_POST, 'ddshort');
|
||||||
|
$p[':color'] = gpc_get_color($_POST, 'color');
|
||||||
|
$p[':sort'] = gpc_get_string($_POST, 'sort');
|
||||||
|
$keys = array_keys($p);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':'); }, $keys));
|
||||||
|
$pnames = join(',', $keys);
|
||||||
|
$sth = $pdo->prepare("INSERT INTO dropdown ($fields) VALUES ($pnames)");
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_EDIT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$p[':ddtext'] = gpc_get_string($_POST, 'ddtext');
|
||||||
|
$p[':ddshort'] = gpc_get_string($_POST, 'ddshort');
|
||||||
|
$p[':color'] = gpc_get_color($_POST, 'color');
|
||||||
|
$p[':sort'] = gpc_get_string($_POST, 'sort');
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':') . '=' . $s; }, array_keys($p)));
|
||||||
|
$sth = $pdo->prepare("UPDATE dropdown SET $fields WHERE ddid=:ddid AND ddval=:ddval");
|
||||||
|
$p[':ddid'] = gpc_get_int($_POST, 'id');
|
||||||
|
$p[':ddval'] = gpc_get_int($_POST, 'v');
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
unset($v);
|
||||||
|
$action = ACT_EDIT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_('Unknown function!'), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
// record counts
|
||||||
|
$num = array();
|
||||||
|
$sql = "SELECT ddid, COUNT(*) AS n FROM dropdown WHERE ddid>0 GROUP BY ddid";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
|
||||||
|
$num[$row[0]] = $row[1];
|
||||||
|
}
|
||||||
|
$sql = "SELECT ddval, ddtext FROM dropdown WHERE ddid=0 AND ddval>0";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
|
||||||
|
echo '<p>', _('Danger! Only adjust if it is clear what impact this will have!'), "<br>\n";
|
||||||
|
// <p>Achtung! Nur anpassen wenn klar ist was das für Auswirkungen hat!</p>
|
||||||
|
|
||||||
|
echo _('Adding values is usually not critical.'), "</p>\n";
|
||||||
|
// <p>Hinzufügen von Werten ist in der Regel unkritisch.</p>
|
||||||
|
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<thead>';
|
||||||
|
echo '<tr>';
|
||||||
|
echo '<th>#</th>';
|
||||||
|
echo '<th>', _('Description'),'</th>';
|
||||||
|
echo '<th>', _('Number'),'</th>';
|
||||||
|
echo '<td></td>';
|
||||||
|
echo '</tr>';
|
||||||
|
echo '</thead>';
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
echo '<tr><td>', $row['ddval'],'</td>';
|
||||||
|
echo '<td>', $row['ddtext'], '</td>';
|
||||||
|
echo '<td>', $num[$row['ddval']] ?? 0, '</td>';
|
||||||
|
form_action_buttons($g_scriptname, $row['ddval']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sth = $pdo->prepare("SELECT ddtext FROM dropdown WHERE ddid=0 AND ddval=?");
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$listname = $sth->fetchColumn();
|
||||||
|
|
||||||
|
echo '<h2>', sprintf(_('View List: %s'), $listname), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT ddval, ddtext, ddshort, color, sort FROM dropdown WHERE ddid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
|
||||||
|
echo '<table class="table">';
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo '<th>#</th>';
|
||||||
|
echo '<th>', _('Name'), "</th>";
|
||||||
|
echo '<th>', _('Short'), "</th>";
|
||||||
|
echo '<th>', _('Color'), "</th>";
|
||||||
|
echo '<th>', _('Sort'), "</th>";
|
||||||
|
echo "<th></th>\n";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
echo '<tr>';
|
||||||
|
echo '<td>', $row['ddval'],'</td>';
|
||||||
|
echo '<td>', $row['ddtext'], '</td>';
|
||||||
|
echo '<td>', $row['ddshort'], '</td>';
|
||||||
|
echo '<td>', $row['color'], '</td>';
|
||||||
|
echo '<td>', $row['sort'], '</td>';
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
echo '<a href="', $g_scriptname, '" class="btn btn-secondary">', _('Back'), "</a>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sth = $pdo->prepare("SELECT ddtext FROM dropdown WHERE ddid=0 AND ddval=?");
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$listname = $sth->fetchColumn();
|
||||||
|
|
||||||
|
echo '<h2>', sprintf(_('Edit List: %s'), $listname), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT ddval, ddtext, ddshort, color, sort FROM dropdown WHERE ddid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
|
||||||
|
echo '<table class="table">';
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo '<th>#</th>';
|
||||||
|
echo '<th>', _('Name'), "</th>";
|
||||||
|
echo '<th>', _('Short'), "</th>";
|
||||||
|
echo '<th>', _('Color'), "</th>";
|
||||||
|
echo '<th>', _('Sort'), "</th>";
|
||||||
|
echo "<th></th>\n";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
echo '<tr>';
|
||||||
|
if ($row['ddval'] == $v) {
|
||||||
|
echo '<td>', $row['ddval'], '</td>';
|
||||||
|
echo '<td colspan="4">';
|
||||||
|
create_ddval_form($g_scriptname, $id, 'update', $row);
|
||||||
|
echo '</td>';
|
||||||
|
echo "<td></td>\n";
|
||||||
|
} else {
|
||||||
|
echo '<td>', $row['ddval'],'</td>';
|
||||||
|
echo '<td>', $row['ddtext'], '</td>';
|
||||||
|
echo '<td>', $row['ddshort'], '</td>';
|
||||||
|
echo '<td>', $row['color'], '</td>';
|
||||||
|
echo '<td>', $row['sort'], '</td>';
|
||||||
|
// Action links
|
||||||
|
echo '<td>';
|
||||||
|
echo '<a href="', $g_scriptname, '?f=edit&id=', $id, '&v=', $row['ddval'], '"><i class="bi-pencil"></i></a>';
|
||||||
|
echo ' ';
|
||||||
|
echo '<i class="bi-trash"></i>';
|
||||||
|
echo '</td>', "\n";
|
||||||
|
// TODO extend function to accept additional parameters
|
||||||
|
// form_action_buttons($g_scriptname, $row['ddid'];
|
||||||
|
}
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
if ($v == -2) {
|
||||||
|
echo '<tr>';
|
||||||
|
echo '<td>(+)</td>';
|
||||||
|
echo '<td colspan="4">';
|
||||||
|
create_ddval_form($g_scriptname, $id, 'insert');
|
||||||
|
echo '</td>';
|
||||||
|
echo "<td></td>\n";
|
||||||
|
echo "</tr>";
|
||||||
|
}
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
echo '<a href="', $g_scriptname, '?f=add&id=', $id, '" class="btn btn-primary">', _('Add'), "</a>\n";
|
||||||
|
echo '<a href="', $g_scriptname, '" class="btn btn-secondary">', _('Back'), "</a>\n";
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,474 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Equipment');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
$opt_supplier = db_get_opt_supp(array(-1 => _('unknown')));
|
||||||
|
$opt_manufacturer = db_get_opt_manuf(array(-1 => _('unknown')));
|
||||||
|
$opt_ecat = db_get_options(4); // Equipment categories
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$ename = gpc_get_string($_POST, 'ename');
|
||||||
|
$ecat = gpc_get_int($_POST, 'category');
|
||||||
|
$manufacturer = gpc_get_int($_POST, 'manufacturer');
|
||||||
|
$model = gpc_get_string($_POST, 'model');
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "INSERT INTO equipment "
|
||||||
|
. " (vid, ename, manufacturer, model, ecat, remarks) "
|
||||||
|
. "VALUES "
|
||||||
|
. " (:vid, :ename, :manufacturer, :model, :ecat, :remarks)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':vid', $user->vid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':ename', $ename, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':model', $model, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':ecat', $ecat, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':manufacturer', $manufacturer, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
try {
|
||||||
|
$sth->execute();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$id = $pdo->lastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$ename = gpc_get_string($_POST, 'ename');
|
||||||
|
$model = gpc_get_string($_POST, 'model');
|
||||||
|
$serial = gpc_get_string($_POST, 'serial');
|
||||||
|
$weight = min(gpc_get_float($_POST, 'weight'), 999.99); // limit max value
|
||||||
|
$price = gpc_get_currency($_POST, 'price');
|
||||||
|
$purchdate = gpc_get_date($_POST, 'purchdate');
|
||||||
|
$supplier = gpc_get_int($_POST, 'supplier');
|
||||||
|
$manufacturer = gpc_get_int($_POST, 'manufacturer');
|
||||||
|
$ecat = gpc_get_int($_POST, 'category');
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "UPDATE equipment "
|
||||||
|
. "SET ename=:ename,"
|
||||||
|
. " model=:model,"
|
||||||
|
. " serial=:serial,"
|
||||||
|
. " weight=:weight,"
|
||||||
|
. " price=:price,"
|
||||||
|
. " purchdate=:purchdate,"
|
||||||
|
. " supplier=:supplier,"
|
||||||
|
. " manufacturer=:manufacturer,"
|
||||||
|
. " ecat=:ecat,"
|
||||||
|
. " remarks=:remarks "
|
||||||
|
. "WHERE eid=:eid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':eid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':ename', $ename, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':model', $model, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':serial', $serial, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':weight', $weight);
|
||||||
|
$sth->bindValue(':price', $price);
|
||||||
|
$sth->bindValue(':purchdate', $purchdate, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':supplier', $supplier, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':manufacturer', $manufacturer, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':ecat', $ecat, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
try {
|
||||||
|
$sth->execute();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// 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']);
|
||||||
|
$sth = $pdo->prepare("DELETE FROM docref WHERE reftype='equipment' AND refid=?");
|
||||||
|
try {
|
||||||
|
$sth->execute([$id]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$refcount = $sth->rowCount();
|
||||||
|
$sth = $pdo->prepare("DELETE FROM equipment WHERE eid=?");
|
||||||
|
try {
|
||||||
|
$sth->execute([$id]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$g_message->Add(sprintf(_('Deleted equipment no. %d'), $id));
|
||||||
|
if ($refcount > 0) {
|
||||||
|
$g_message->Add(sprintf(_('%d document links were removed'), $refcount));
|
||||||
|
}
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'upload':
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
if (!isset($_FILES['files'])) {
|
||||||
|
$g_warning->Add(_('No files for upload submitted'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$extensions = ['jpg', 'png'];
|
||||||
|
$mimetypes = ['image/png', 'image/jpeg', 'image/svg+xml', 'application/pdf'];
|
||||||
|
$all_files = count($_FILES ["files"]["tmp_name"]);
|
||||||
|
$nerr = 0;
|
||||||
|
for ($i = 0; $i < $all_files; $i++) {
|
||||||
|
$file_name = $_FILES['files']['name'][$i];
|
||||||
|
$file_tmp = $_FILES['files']['tmp_name'][$i];
|
||||||
|
$file_type = $_FILES['files']['type'][$i];
|
||||||
|
$file_size = $_FILES['files']['size'][$i];
|
||||||
|
$file_ext = strtolower(end(explode('.', $_FILES['files']['name'][$i])));
|
||||||
|
// $file = $g_doc_basepath . '/' . $file_name;
|
||||||
|
$file_mimetype = mime_content_type($file_tmp);
|
||||||
|
if (!in_array($file_mimetype, $mimetypes)) {
|
||||||
|
$g_error->Add(sprintf(_("Mimetype '%s' not allowed for upload."), $file_mimetype));
|
||||||
|
$nerr += 1;
|
||||||
|
}
|
||||||
|
if (!in_array($file_ext, $extensions)) {
|
||||||
|
$g_error->Add(_('Filetype not allowed for upload:') . ' ' . $file_type);
|
||||||
|
$nerr += 1;
|
||||||
|
}
|
||||||
|
if ($file_size > 2097152) {
|
||||||
|
$g_error->Add(sprintf(_('File to big: %s.%s'), $file_name, $file_type));
|
||||||
|
$nerr += 1;
|
||||||
|
}
|
||||||
|
if ($nerr > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$file_hash = md5_file($file_tmp);
|
||||||
|
$file_timestamp = date('Y-m-d H:i:s', filemtime($file_tmp));
|
||||||
|
|
||||||
|
// check whether the file already exists, in this case issue
|
||||||
|
// a message and just create a link to the already known file
|
||||||
|
$sql = "SELECT docid FROM document WHERE hash=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$file_hash]);
|
||||||
|
$row = $sth->fetch();
|
||||||
|
if (!$row) {
|
||||||
|
$sql = "INSERT INTO document"
|
||||||
|
. " (doctype, filename, extension, hash, doctime, docsize, mimetype) "
|
||||||
|
. "VALUES"
|
||||||
|
. " (?, ?, ?, ?, ?, ?, ?)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute(['picture', $file_name, $file_ext, $file_hash, $file_timestamp, $file_size, $file_mimetype]);
|
||||||
|
$docid = $pdo->lastInsertId();
|
||||||
|
$file_techname = $g_doc_basepath . '/pic-'.$file_hash.'.'.$file_ext;
|
||||||
|
move_uploaded_file($file_tmp, $file_techname);
|
||||||
|
} else {
|
||||||
|
// A document record definitely exists here, now just
|
||||||
|
// connect it to the selected equipment
|
||||||
|
$docid = $row['docid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "INSERT INTO docref (docid, refid) VALUES (?, ?)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
// Reference may already exist!
|
||||||
|
try {
|
||||||
|
$sth->execute([$docid, $id]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // for
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_('Unknown function!'), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
$sql = "SELECT eid, ename, manufacturer, model, serial, remarks,"
|
||||||
|
. " TIMESTAMPDIFF(MONTH, purchdate, NOW()) AS age_mon "
|
||||||
|
. "FROM equipment WHERE vid=? "
|
||||||
|
. "ORDER BY eid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
?>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<div id="filter" class="card">
|
||||||
|
<div class="card-header">Filter</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<label>Category</label>
|
||||||
|
<select>
|
||||||
|
<?php
|
||||||
|
foreach ($opt_ecat as $k => $v) {
|
||||||
|
echo '<option value="', $k,'">', $v, '</option>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
<button class="btn btn-sm btn-primary" title="<?=_('Apply')?>">Go</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// Data
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<th>" . _('Description') . "</th>";
|
||||||
|
echo "<th>" . _('Manufacturer') . "</th>";
|
||||||
|
echo "<th>" . _('Model') . "</th>";
|
||||||
|
echo "<th>" . _('Serial') . "</th>";
|
||||||
|
echo "<th>" . _('Age') . "</th>";
|
||||||
|
echo "<th>" . _('Remarks') . "</th>";
|
||||||
|
echo "<th> </th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
// calc nice age display
|
||||||
|
if (!isset($row['age_mon'])) {
|
||||||
|
$age = '';
|
||||||
|
} elseif ($row['age_mon'] < 12) {
|
||||||
|
$age = sprintf(_('%dm'), $row['age_mon']);
|
||||||
|
} else {
|
||||||
|
$age = sprintf(_('%dy'), intdiv($row['age_mon'], 12));
|
||||||
|
}
|
||||||
|
echo "<tr>\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']);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<tfoot>
|
||||||
|
<tr><td colspan="6"><?php printf(_('%d records'), count($res)); ?></td></tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
<nav>
|
||||||
|
<ul class="pagination justify-content-center">
|
||||||
|
<li class="page-item"><a class="page-link" href="#">Previous</a></li>
|
||||||
|
<li class="page-item"><a class="page-link" href="#">1</a></li>
|
||||||
|
<li class="page-item"><a class="page-link" href="#">2</a></li>
|
||||||
|
<li class="page-item"><a class="page-link" href="#">Next</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
?>
|
||||||
|
<h2><?=_('Add Equipment')?></h2>
|
||||||
|
<form method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="ename" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="ename" name="ename">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('category', _('Category'), $opt_ecat);
|
||||||
|
form_create_select('manufacturer', _('Manufacturer'), $opt_manufacturer);
|
||||||
|
?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="model" class="form-label"><?=_('Model')?></label>
|
||||||
|
<input type="text" class="form-control" id="model" name="model">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT eid, ename, model, serial, purchdate, price, weight, "
|
||||||
|
. " supplier, manufacturer, ecat, remarks "
|
||||||
|
. "FROM equipment "
|
||||||
|
. "WHERE eid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$equipment = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
echo "<h2>", $equipment->ename, "</h2>\n";
|
||||||
|
|
||||||
|
// Bootstrap grid
|
||||||
|
echo '<div class="container">';
|
||||||
|
echo '<div class="row">';
|
||||||
|
echo '<div class="col">';
|
||||||
|
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th>', _('Manufacturer'),"</th><td>", $opt_manufacturer[$equipment->manufacturer], "</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";
|
||||||
|
echo '<tr><th>', _('Price'),"</th><td>", format_currency($equipment->price), "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Purchase date'),"</th><td>", $equipment->purchdate, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Supplier'),"</th><td>", $opt_supplier[$equipment->supplier], "</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 "</table>\n";
|
||||||
|
|
||||||
|
echo '</div>'; // Column break
|
||||||
|
echo '<div class="col">';
|
||||||
|
?>
|
||||||
|
<p>Images and documents go here</p>
|
||||||
|
<?php
|
||||||
|
$sql = "SELECT d.docid, d.doctype, d.title "
|
||||||
|
. "FROM docref AS r INNER JOIN document AS d using (docid) "
|
||||||
|
. "WHERE r.refid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
foreach ($res as $row) {
|
||||||
|
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'] == 'generic') {
|
||||||
|
echo '<a href="dl.php?id=', $row['docid'], '">';
|
||||||
|
echo $row['title'];
|
||||||
|
echo "</a>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<form method="post" enctype="multipart/form-data" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<input type="file" name="files[]" multiple accept="image/*" capture="camera">
|
||||||
|
<input type="submit" name="submit[upload]" value="Upload">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
echo '</div>'; // col
|
||||||
|
echo '</div>'; // row
|
||||||
|
echo '</div>'; // container
|
||||||
|
|
||||||
|
// Buttons at bottom of data area
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT compid, compname FROM company WHERE comptype=1 ORDER BY compname";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$supplier = array();
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
$supplier[$row['compid']] = $row['compname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "SELECT eid, ename, model, serial, weight, price, purchdate,"
|
||||||
|
. " supplier, manufacturer, ecat, remarks "
|
||||||
|
. "FROM equipment "
|
||||||
|
. "WHERE eid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$equipment = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
?>
|
||||||
|
<h2><?=_('Edit Equipment')?></h2>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="ename" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="ename" name="ename" value="<?=$equipment->ename ?>">
|
||||||
|
</div>
|
||||||
|
<?php form_create_select('manufacturer', _('Manufacturer'), $opt_manufacturer, $equipment->manufacturer); ?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="model" class="form-label"><?=_('Model')?></label>
|
||||||
|
<input type="text" class="form-control" id="model" name="model" value="<?=$equipment->model ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="serial" class="form-label"><?=_('Serial')?></label>
|
||||||
|
<input type="text" class="form-control" id="serial" name="serial" value="<?=$equipment->serial ?>">
|
||||||
|
</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($equipment->weight); ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="price" class="form-label"><?=sprintf(_('Price, %s'), $g_lconv['currency_symbol']); ?></label>
|
||||||
|
<input type="text" class="form-control" id="price" name="price" value="<?=format_float($equipment->price) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="purchdate"><?=_('Purchase date')?></label>
|
||||||
|
<input type="date" class="form-control" id="startdate" name="purchdate" value="<?=$equipment->purchdate ?>">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('supplier', _('Supplier'), $opt_supplier, $equipment->supplier);
|
||||||
|
form_create_select('category', _('Category'), $opt_ecat, $equipment->ecat);
|
||||||
|
?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$equipment->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit[update]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>?f=view&id=<?=$id?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
$_SESSION['token'] = bin2hex(random_bytes(8));
|
||||||
|
$sql = "SELECT ename, remarks FROM equipment WHERE eid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$equipment = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete equipment'),"</h2>\n";
|
||||||
|
|
||||||
|
echo '<p>', sprintf(_('Record no. %d'), $id), "</p>\n";
|
||||||
|
echo '<p>Name: ', $equipment->ename, "</p>";
|
||||||
|
echo '<p>Remarks: ', $equipment->remarks, "</p>";
|
||||||
|
|
||||||
|
echo '<p>', _('Deleting an equipment item is final. There is no way back. Only delete if you are absolute sure.'), "</p>\n";
|
||||||
|
|
||||||
|
form_delete_buttons($g_scriptname, $id, $_SESSION['token']);
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<footer class="bg-body-tertiary text-center">
|
||||||
|
<p>Prototyp YMS v0.1</p>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div><?php /* Main container */?>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,709 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************
|
||||||
|
|
||||||
|
******************
|
||||||
|
* Edition History
|
||||||
|
*
|
||||||
|
* # Date Changes by
|
||||||
|
* ------ ------------ ---------------------------------------------- -----
|
||||||
|
* 0.1.0 2024-03-12 Started development tho
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ========== CONSTANT DEFINITIONS ============================================
|
||||||
|
|
||||||
|
define ('E_NONE', 0);
|
||||||
|
|
||||||
|
define ('OPTIONAL', 0);
|
||||||
|
define ('REQUIRED', 1);
|
||||||
|
define ('ENABLED', 1);
|
||||||
|
define ('DISABLED', 0);
|
||||||
|
|
||||||
|
define ('ACT_DEFAULT', 0);
|
||||||
|
define ('ACT_ADD', 1);
|
||||||
|
define ('ACT_VIEW', 2);
|
||||||
|
define ('ACT_EDIT', 3);
|
||||||
|
define ('ACT_DELETE', 4);
|
||||||
|
define ('ACT_COPY', 5);
|
||||||
|
define ('ACT_JOIN', 6);
|
||||||
|
define ('ACT_LEAVE', 7);
|
||||||
|
define ('ACT_EDIT_DETAIL', 8);
|
||||||
|
define ('ACT_DEL_DETAIL', 9);
|
||||||
|
define ('ACT_LINK', 10);
|
||||||
|
define ('ACT_UNLINK', 11);
|
||||||
|
define ('ACT_MAIL', 12);
|
||||||
|
define ('ACT_VIEW_LIST', 13);
|
||||||
|
|
||||||
|
// ========== PAGE START CODE =================================================
|
||||||
|
|
||||||
|
$g_scriptname = basename($_SERVER['SCRIPT_NAME']);
|
||||||
|
|
||||||
|
require 'config.inc';
|
||||||
|
|
||||||
|
// Localization
|
||||||
|
setlocale(LC_ALL, $g_locale);
|
||||||
|
$g_lconv = localeconv();
|
||||||
|
$g_lang = substr($g_locale, 0, 2); // short language identifier
|
||||||
|
|
||||||
|
bindtextdomain('yms', 'locale');
|
||||||
|
bind_textdomain_codeset('yms', 'UTF-8');
|
||||||
|
textdomain('yms');
|
||||||
|
|
||||||
|
date_default_timezone_set($g_timezone);
|
||||||
|
|
||||||
|
if ($g_scriptname != 'login.php') {
|
||||||
|
session_name(APP_SESSION);
|
||||||
|
session_start();
|
||||||
|
if (!isset($_SESSION['userid'])) {
|
||||||
|
$_SESSION['prelogin'] = $_SERVER['REQUEST_URI'];
|
||||||
|
header_location('login.php');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = new PDO("mysql:host=$g_db_host;dbname=$g_db_schema;charset=utf8mb4", $g_db_username, $g_db_password);
|
||||||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||||
|
# $pdo->query("SET lc_time_names='de_DE'");
|
||||||
|
$sth = $pdo->query("SELECT valint FROM settings WHERE userid=0 AND sno=0");
|
||||||
|
$g_db_scheme_version = $sth->fetchColumn();
|
||||||
|
|
||||||
|
$user = User::GetInstance(); // There can be only one
|
||||||
|
if ($g_scriptname != 'login.php') {
|
||||||
|
$user->init_from_session();
|
||||||
|
$user->load_vessel();
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = NULL;
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
// Initialize message system
|
||||||
|
$g_message = new Message;
|
||||||
|
$g_success = new MessageSuccess;
|
||||||
|
$g_warning = new MessageWarning;
|
||||||
|
$g_error = new MessageError;
|
||||||
|
|
||||||
|
// ========== MESSAGE FUNCTIONS ===============================================
|
||||||
|
|
||||||
|
class Message {
|
||||||
|
|
||||||
|
var $count = 0;
|
||||||
|
var $text = array();
|
||||||
|
var $caption;
|
||||||
|
var $alertclass;
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
$this->caption = _('Information');
|
||||||
|
$this->alertclass = 'alert-info';
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetCaption($str) {
|
||||||
|
$this->caption = $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add($msg) {
|
||||||
|
$this->count++;
|
||||||
|
$this->text[$this->count] = $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetCount() {
|
||||||
|
return $this->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
function PrintOut() {
|
||||||
|
if ($this->count > 0) {
|
||||||
|
echo '<div class="alert ', $this->alertclass, ' alert-dismissible fade show" role="alert">', "\n";
|
||||||
|
echo '<h4 class="alert-heading">', $this->caption, "</h4>\n";
|
||||||
|
echo "<ul>\n";
|
||||||
|
for ($i=1; $i<=$this->count; $i++) {
|
||||||
|
echo "\t<li>", $this->text[$i],"</li>\n";
|
||||||
|
}
|
||||||
|
echo "</ul>\n";
|
||||||
|
echo '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>', "\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageSuccess extends Message {
|
||||||
|
function __construct() {
|
||||||
|
$this->caption = _('Success');
|
||||||
|
$this->alertclass = 'alert-success';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageWarning extends Message {
|
||||||
|
function __construct() {
|
||||||
|
$this->caption = _('Warning');
|
||||||
|
$this->alertclass = 'alert-warning';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageError extends Message {
|
||||||
|
function __construct() {
|
||||||
|
$this->caption = _('Error');
|
||||||
|
$this->alertclass = 'alert-danger';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== USER FUNCTIONS ==================================================
|
||||||
|
|
||||||
|
class User {
|
||||||
|
|
||||||
|
private static $instance = NULL;
|
||||||
|
|
||||||
|
private $loggedin;
|
||||||
|
private $errormessage;
|
||||||
|
|
||||||
|
public $id;
|
||||||
|
public $login;
|
||||||
|
public $displayname;
|
||||||
|
public $role;
|
||||||
|
public $flags;
|
||||||
|
public $vid; // current selected vessel
|
||||||
|
public $vessel; // name of current vessel
|
||||||
|
|
||||||
|
private function __construct() {
|
||||||
|
$this->loggedin = FALSE;
|
||||||
|
$this->errormessage = NULL;
|
||||||
|
$this->flags = [];
|
||||||
|
$this->vid = 1;
|
||||||
|
$this->vessel = 'Yacht';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getInstance() {
|
||||||
|
if (self::$instance == NULL) {
|
||||||
|
self::$instance = new User();
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
function login($user_name, $user_pass) {
|
||||||
|
global $pdo;
|
||||||
|
if ($user_name == '' or $user_pass == '') {
|
||||||
|
$this->loggedin = FALSE;
|
||||||
|
$this->errormessage = _('Username or password was empty');
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
$sql = "SELECT userid, pass, displayname, role, flags FROM user WHERE login=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$user_name]);
|
||||||
|
$row = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
$this->role = $row->role;
|
||||||
|
$this->flags = array_filter(explode(',', $row->flags));
|
||||||
|
if ($row->flags != 0 ) {
|
||||||
|
// deleted or locked, intentionally not return detailed reason
|
||||||
|
$this->errormessage = _('User account does not exist');
|
||||||
|
} elseif (password_verify($user_pass, $row->pass)) {
|
||||||
|
// password check successful
|
||||||
|
$_SESSION['userid'] = $row->userid;
|
||||||
|
$this->loggedin = TRUE;
|
||||||
|
header_location($_SESSION['prelogin'] ?? 'index.php');
|
||||||
|
} else {
|
||||||
|
$this->errormessage = _('Username or password invalid');
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function logout() {
|
||||||
|
global $pdo;
|
||||||
|
// remove session completely
|
||||||
|
$_SESSION = array();
|
||||||
|
if (ini_get("session.use_cookies")) {
|
||||||
|
$params = session_get_cookie_params();
|
||||||
|
setcookie(session_name(), '', time() - 42000,
|
||||||
|
$params["path"], $params["domain"],
|
||||||
|
$params["secure"], $params["httponly"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_from_session() {
|
||||||
|
global $pdo;
|
||||||
|
if (!isset($_SESSION['userid'])) {
|
||||||
|
$this->loggedin = FALSE;
|
||||||
|
$this->errormessage = _('User not logged in');
|
||||||
|
$this->id = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->id = $_SESSION['userid'];
|
||||||
|
$sql = "SELECT displayname, role FROM user WHERE userid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$this->id]);
|
||||||
|
$row = $sth->fetch();
|
||||||
|
$this->displayname = $row['displayname'];
|
||||||
|
$this->role = $row['role'];
|
||||||
|
//$this->displayname = $sth->fetchColumn();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_vessel() {
|
||||||
|
global $pdo;
|
||||||
|
$sql = "SELECT v.vid, v.vesselname "
|
||||||
|
. "FROM settings AS s INNER JOIN vessel AS v ON s.valint=v.vid "
|
||||||
|
. "WHERE s.userid=? and s.sno=1";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$this->id]);
|
||||||
|
$row = $sth->fetch();
|
||||||
|
$this->vid = $row['vid'];
|
||||||
|
$this->vessel = $row['vesselname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_last_error() {
|
||||||
|
return $this->errormessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_userlist() {
|
||||||
|
// Get list of all users for fast name lookup
|
||||||
|
global $pdo;
|
||||||
|
$ulist = array(-1 => ['-', 0]); // unknown
|
||||||
|
$sql = "SELECT userid, displayname, role, flags FROM user ORDER BY displayname";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
foreach ($res as $row) {
|
||||||
|
$flags = array_filter(explode(',', $row['flags']));
|
||||||
|
$deleted = in_array('deleted', $flags);
|
||||||
|
$locked = in_array('locked', $flags);
|
||||||
|
$ulist[$row['userid']] = [$row['displayname'], $deleted, $locked];
|
||||||
|
}
|
||||||
|
return $ulist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== DATABASE FUNCTIONS ==============================================
|
||||||
|
|
||||||
|
function db_load_enum($table, $column) {
|
||||||
|
// returns array of enum-values as defined in database
|
||||||
|
global $pdo;
|
||||||
|
$sql = "SELECT TRIM(TRAILING ')' FROM SUBSTRING(column_type,6)) "
|
||||||
|
. "FROM information_schema.columns "
|
||||||
|
. "WHERE table_name=? AND column_name=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$table, $column]);
|
||||||
|
// for PHP < 7.4
|
||||||
|
// return array_map(function($x) { return trim($x, "'"); }, explode(',', $sth->fetchColumn()));
|
||||||
|
// for PHP => 7.4
|
||||||
|
return array_map(fn($x) => trim($x, "'"), explode(',', $sth->fetchColumn()));
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_ddtext($ddid, $ddval) {
|
||||||
|
// returns single value for dropdown
|
||||||
|
global $pdo;
|
||||||
|
global $g_error;
|
||||||
|
$sql = "SELECT ddtext FROM dropdown WHERE ddid=? AND ddval=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
try {
|
||||||
|
$sth->execute([$ddid, $ddval]);
|
||||||
|
} catch(PDOException $e) {
|
||||||
|
$g_error->Add($e->getMessage());
|
||||||
|
return '#err';
|
||||||
|
}
|
||||||
|
return $sth->fetchColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_options($ddid, $orderby = '', $default = NULL) {
|
||||||
|
// returns list for dropdown
|
||||||
|
global $pdo;
|
||||||
|
$list = array();
|
||||||
|
if ($default != NULL) {
|
||||||
|
$list[0] = $default;
|
||||||
|
}
|
||||||
|
$sql = "SELECT ddval, ddtext FROM dropdown WHERE ddid=?";
|
||||||
|
if ($orderby == 'ddtext') {
|
||||||
|
$sql .= ' ORDER BY ddtext';
|
||||||
|
} elseif ($orderby == 'sort') {
|
||||||
|
$sql .= ' ORDER BY sort';
|
||||||
|
} else {
|
||||||
|
$sql .= ' ORDER BY ddval';
|
||||||
|
}
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$ddid]);
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
|
||||||
|
$list[$rec[0]] = $rec[1];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_opt_vessel() {
|
||||||
|
global $pdo;
|
||||||
|
$list = array();
|
||||||
|
$sth = $pdo->query("SELECT vid, vesselname, model FROM vessel ORDER BY vid");
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
|
||||||
|
$list[$rec[0]] = $rec[1];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions to get option lists (key/value)
|
||||||
|
|
||||||
|
function db_get_opt_storage($vid) {
|
||||||
|
global $pdo;
|
||||||
|
global $g_error;
|
||||||
|
$list = array();
|
||||||
|
$sql = "SELECT sid, sname FROM storage WHERE vid=? ORDER BY sname";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
try {
|
||||||
|
$sth->execute([$vid]);
|
||||||
|
} catch(PDOException $e) {
|
||||||
|
$g_error->Add($e->getMessage());
|
||||||
|
}
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
|
||||||
|
$list[$rec[0]] = $rec[1];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_opt_box($vid) {
|
||||||
|
global $pdo;
|
||||||
|
global $g_error;
|
||||||
|
$list = array();
|
||||||
|
$sql = "SELECT boxid, label, content "
|
||||||
|
. "FROM box INNER JOIN storage USING (sid) "
|
||||||
|
. "WHERE vid=? "
|
||||||
|
. "ORDER BY label";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
try {
|
||||||
|
$sth->execute([$vid]);
|
||||||
|
} catch(PDOException $e) {
|
||||||
|
$g_error->Add($e->getMessage());
|
||||||
|
}
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
|
||||||
|
$list[$rec[0]] = $rec[1] . ' - '. $rec[2];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_opt_equip($vid) {
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_opt_manuf($default=NULL) {
|
||||||
|
global $pdo;
|
||||||
|
if (isset($default)) {
|
||||||
|
$list = $default;
|
||||||
|
} else {
|
||||||
|
$list = array();
|
||||||
|
}
|
||||||
|
$sql = "SELECT compid, compname FROM company WHERE comptype=2 ORDER BY compname";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
|
||||||
|
$list[$row[0]] = $row[1];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_opt_supp($default=NULL) {
|
||||||
|
global $pdo;
|
||||||
|
if (isset($default)) {
|
||||||
|
$list = $default;
|
||||||
|
} else {
|
||||||
|
$list = array();
|
||||||
|
}
|
||||||
|
$sql = "SELECT compid, compname FROM company WHERE comptype=1 ORDER BY compname";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $row) {
|
||||||
|
$list[$row[0]] = $row[1];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function db_get_opt_proj($vid, $default=NULL) {
|
||||||
|
global $pdo;
|
||||||
|
global $g_error;
|
||||||
|
if (isset($default)) {
|
||||||
|
$list = $default;
|
||||||
|
} else {
|
||||||
|
$list = array();
|
||||||
|
}
|
||||||
|
$sql = "SELECT projid, projname FROM project WHERE vid=? ORDER BY projname";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
try {
|
||||||
|
$sth->execute([$vid]);
|
||||||
|
} catch(PDOException $e) {
|
||||||
|
$g_error->Add($e->getMessage());
|
||||||
|
}
|
||||||
|
foreach ($sth->fetchAll(PDO::FETCH_NUM) as $rec) {
|
||||||
|
$list[$rec[0]] = $rec[1];
|
||||||
|
}
|
||||||
|
return $list;
|
||||||
|
}
|
||||||
|
|
||||||
|
function date_to_sql($var) {
|
||||||
|
if (!isset($var) || $var == '') {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
list($d, $m, $y) = explode('.', $var);
|
||||||
|
return sprintf("%04d-%02d-%02d", $y, $m, $d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function float_to_sql($var) {
|
||||||
|
global $g_lconv;
|
||||||
|
if (!isset($var) || $var == '') {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
// remove thousands separator
|
||||||
|
$var = str_replace($g_lconv['thousands_sep'], '', $var);
|
||||||
|
// force decimal point
|
||||||
|
if ($g_lconv['decimal_point'] != '.') {
|
||||||
|
$var = str_replace($g_lconv['decimal_point'], '.', $var);
|
||||||
|
}
|
||||||
|
return $var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== FORM FUNCTIONS ==================================================
|
||||||
|
|
||||||
|
function form_create_select($fieldname, $label, $optlist, $selval=NULL) {
|
||||||
|
//if (
|
||||||
|
echo '<div class="mb-3">', "\n";
|
||||||
|
echo '<label for="', $fieldname, '">', $label, "</label>\n";
|
||||||
|
echo '<select class="form-select" name="', $fieldname,'" id="', $fieldname,'">';
|
||||||
|
foreach ($optlist as $k => $v) {
|
||||||
|
echo '<option value="', $k, '"';
|
||||||
|
if (isset($selval) and ($k == $selval)) {
|
||||||
|
echo ' selected';
|
||||||
|
}
|
||||||
|
echo '>', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
echo "</select>\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function form_action_buttons($script, $id) {
|
||||||
|
echo "<td>";
|
||||||
|
echo '<a title="', _('View'), '" href="', $script, '?f=view&id=', $id, '"><i class="bi-eye"></i></a>', "\n";
|
||||||
|
echo '<a title="', _('Edit'), '" href="', $script, '?f=edit&id=', $id, '"><i class="bi-pencil"></i></a>', "\n";
|
||||||
|
echo "</td>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function form_add_button($script, $id=NULL, $idname='id') {
|
||||||
|
echo '<div class="container-fluid px-0 my-3">', "\n";
|
||||||
|
echo '<a href="', $script, '?f=add';
|
||||||
|
if (isset($id)) {
|
||||||
|
echo '&'.$idname.'='.$id;
|
||||||
|
}
|
||||||
|
echo '" class="btn btn-primary" role="button">', _('Add'), "</a>\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function form_view_buttons($script, $id) {
|
||||||
|
echo '<div class="container-fluid px-0 my-3">', "\n";
|
||||||
|
echo '<a href="', $script, '?f=edit&id=', $id, '" class="btn btn-primary" role="button">', _('Edit'), "</a>\n";
|
||||||
|
echo ' ';
|
||||||
|
echo '<a href="', $script, '?f=del&id=', $id, '" class="btn btn-secondary" role="button">', _('Delete'), "</a>\n";
|
||||||
|
echo ' ';
|
||||||
|
echo '<a href="', $script, '" class="btn btn-secondary">', _('Back'), "</a>\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function form_edit_buttons($script, $id) {
|
||||||
|
echo '<div class="container-fluid px-0 my-3">', "\n";
|
||||||
|
echo '<button type="submit" name="submit[update]" class="btn btn-primary">', _('Save'), "</button>\n";
|
||||||
|
echo '<a href="', $script, '?f=view&id=', $id, '" class="btn btn-secondary">', _('Back'), "</a>\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function form_delete_buttons($script, $id, $token) {
|
||||||
|
echo '<div class="container-fluid px-0 my-3">', "\n";
|
||||||
|
echo '<form method="post" action="', $script, '">', "\n";
|
||||||
|
echo '<input type="hidden" name="id" value="', $id .'">', "\n";
|
||||||
|
echo '<input type="hidden" name="token" value="', $token, '">', "\n";
|
||||||
|
echo '<button type="submit" name="submit[delete]" class="btn btn-primary">', _('Delete'), "</button>\n";
|
||||||
|
echo '<a href="', $script, '?f=view&id=', $id, '" class="btn btn-secondary">', _('Back'), "</a>\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
echo "</form>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== COMMON FUNCTIONS ================================================
|
||||||
|
|
||||||
|
function header_location($location) {
|
||||||
|
header("Location: $location");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function form_get_action() {
|
||||||
|
if (!isset($_POST['submit'])) {
|
||||||
|
if (isset($_GET['f'])) {
|
||||||
|
$submit = $_GET['f'];
|
||||||
|
// strip parameters
|
||||||
|
/* $pos = strpos($submit, '?');
|
||||||
|
if ($pos > 2) {
|
||||||
|
$submit = substr($submit, 0, $pos);
|
||||||
|
} */
|
||||||
|
} else {
|
||||||
|
$submit = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$submit = $_POST['submit'];
|
||||||
|
}
|
||||||
|
if (is_array($submit)) {
|
||||||
|
$submit = key($submit);
|
||||||
|
}
|
||||||
|
return strtolower($submit);
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_color_brightness($color) {
|
||||||
|
// returns a value between 0 and 1
|
||||||
|
// color is a 6 char hex string
|
||||||
|
list($red, $green, $blue) = array_map('hexdec', str_split($color, 2));
|
||||||
|
$red = $red / 255 * 0.2126;
|
||||||
|
$green = $green / 255 * 0.7152;
|
||||||
|
$blue = $blue / 255 * 0.0722;
|
||||||
|
return $red + $green + $blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpc_get_string(&$GPC, $varname, $maxlen = NULL, $default = NULL) {
|
||||||
|
if (!isset($GPC[$varname]) or (strlen(trim($GPC[$varname])) == 0)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
$s = trim($GPC[$varname]);
|
||||||
|
if (isset($maxlen)) {
|
||||||
|
return substr($s, 0, $maxlen);
|
||||||
|
}
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpc_get_int(&$GPC, $varname, $default = NULL) {
|
||||||
|
if (!isset($GPC[$varname])) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
return (int)$GPC[$varname];
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpc_get_float(&$GPC, $varname, $default = NULL) {
|
||||||
|
global $g_lconv;
|
||||||
|
if (!isset($GPC[$varname]) or (strlen(trim($GPC[$varname])) == 0)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
$var = str_replace($g_lconv['thousands_sep'], '', $GPC[$varname]);
|
||||||
|
if ($g_lconv['decimal_point'] != '.') {
|
||||||
|
$var = str_replace($g_lconv['decimal_point'], '.', $var);
|
||||||
|
}
|
||||||
|
return (double)$var;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpc_get_currency(&$GPC, $varname, $default = NULL) {
|
||||||
|
global $g_lconv;
|
||||||
|
if (!isset($GPC[$varname]) or (strlen(trim($GPC[$varname])) == 0)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
$var = str_replace($g_lconv['thousands_sep'], '', $GPC[$varname]);
|
||||||
|
if ($g_lconv['decimal_point'] != '.') {
|
||||||
|
$var = str_replace($g_lconv['decimal_point'], '.', $var);
|
||||||
|
}
|
||||||
|
return (double)$var;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpc_get_bool(&$GPC, $varname, $default = FALSE) {
|
||||||
|
if (!isset($GPC[$varname])) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
$gpcvar = trim($GPC[$varname]);
|
||||||
|
if (strcasecmp('off', $gpcvar) == 0 ||
|
||||||
|
strcasecmp('no', $gpcvar) == 0 ||
|
||||||
|
strcasecmp('false', $gpcvar) == 0 ||
|
||||||
|
strcasecmp('no', $gpcvar) == 0 ||
|
||||||
|
strcasecmp('0', $gpcvar) == 0 ||
|
||||||
|
strcasecmp('nein', $gpcvar) == 0)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpc_get_date(&$GPC, $varname, $default = NULL) {
|
||||||
|
if (!isset($GPC[$varname]) || $GPC[$varname] == '') {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
return $GPC[$varname];
|
||||||
|
}
|
||||||
|
|
||||||
|
function gpc_get_color(&$GPC, $varname, $default = NULL) {
|
||||||
|
if (!isset($GPC[$varname]) or (strlen(trim($GPC[$varname])) == 0)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
$color = $GPC[$varname];
|
||||||
|
if ((strlen($color) == 7) and (substr($color, 0, 1) == '#')) {
|
||||||
|
$color = substr($color, 1);
|
||||||
|
}
|
||||||
|
if ((strlen($color) != 6) or (! ctype_xdigit($color))) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
return strtoupper($color);
|
||||||
|
}
|
||||||
|
|
||||||
|
function format_float($val, $decimals = 2, $suffix = '') {
|
||||||
|
global $g_lconv;
|
||||||
|
if (!isset($val) || $val == '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return number_format($val, $decimals, $g_lconv['decimal_point'], $g_lconv['thousands_sep']) . ($suffix ? " $suffix" : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function format_currency($val) {
|
||||||
|
global $g_lconv;
|
||||||
|
if (!isset($val) || $val == '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if ($g_lconv['currency_symbol'] == '$') {
|
||||||
|
return '$'.number_format($val, 2, $g_lconv['decimal_point'], $g_lconv['thousands_sep']);
|
||||||
|
} else {
|
||||||
|
return number_format($val, 2, $g_lconv['decimal_point'], $g_lconv['thousands_sep']) . ' ' . $g_lconv['currency_symbol'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function format_filesize($size, $format=2) {
|
||||||
|
switch ($format) {
|
||||||
|
case 1: // short
|
||||||
|
if ($size < 1024) {
|
||||||
|
$size_string = sprintf(_('%d&tinysp;B'), $size);
|
||||||
|
} elseif ($size < 1048576) {
|
||||||
|
$size_string = sprintf(_('%.1f&tinysp;kB'), $size/1024);
|
||||||
|
} else {
|
||||||
|
$size_string = sprintf(_('%.1f&tinysp;MB'), $size/1048576);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: // medium
|
||||||
|
if ($size < 1024) {
|
||||||
|
$size_string = sprintf(_('%d&tinysp;Byte'), $size);
|
||||||
|
} elseif ($size < 1048576) {
|
||||||
|
$size_string = sprintf(_('%.1f&tinysp;kByte'), $size/1024);
|
||||||
|
} else {
|
||||||
|
$size_string = sprintf(_('%.1f&tinysp;MByte'), $size/1048576);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: // long
|
||||||
|
if ($size < 1024) {
|
||||||
|
$size_string = sprintf(_('%d Byte'), $size);
|
||||||
|
} elseif ($size < 1048576) {
|
||||||
|
$size_string = sprintf(_('approx. %.1f kByte'), $size/1024);
|
||||||
|
} else {
|
||||||
|
$size_string = sprintf(_('approx. %.1f MByte'), $size/1048576);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$size_string = trim($size);
|
||||||
|
}
|
||||||
|
return $size_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== MENU FUNCTIONS ==================================================
|
||||||
|
|
||||||
|
$g_menu = Array (
|
||||||
|
'equipment.php' => [_('Equipment')],
|
||||||
|
'inventory.php' => [_('Inventory')],
|
||||||
|
'provisions.php' => [_('Provisions')],
|
||||||
|
'maintenance.php' => [_('Maintenance')],
|
||||||
|
'projects.php' => [_('Projects')],
|
||||||
|
'documents.php' => [_('Documents')],
|
||||||
|
'manual.php' => ['<i class="bi-book"></i>'],
|
||||||
|
'logout.php' => ['<i class="bi-door-open"></i>']
|
||||||
|
);
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="<?=$g_lang?>">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="robots" content="noindex,nofollow">
|
||||||
|
<title><?=APP_TITLE_SHORT?> - <?=$pagetitle?></title>
|
||||||
|
<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>
|
||||||
|
<link rel="stylesheet" href="default.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container-xxl">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="index.php"><?php echo $user->vessel ?? _('Ghost'); ?></a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<?php
|
||||||
|
foreach ($g_menu as $key => $value) {
|
||||||
|
echo str_repeat(' ', 4);
|
||||||
|
echo '<li class="nav-item">';
|
||||||
|
$active = ($g_scriptname == $key) ? ' active' : '';
|
||||||
|
echo '<a class="nav-link', $active,'" href="', $key, '">', $value[0], "</a>";
|
||||||
|
echo "</li>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// ========== SYSTEM FEEDBACK =================================================
|
||||||
|
|
||||||
|
$g_error->PrintOut();
|
||||||
|
$g_warning->PrintOut();
|
||||||
|
$g_message->PrintOut();
|
||||||
|
$g_success->PrintOut();
|
||||||
@@ -0,0 +1,392 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Start');
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_DEFAULT; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
|
||||||
|
case 'select':
|
||||||
|
$vid = gpc_get_int($_POST, 'vid', 1);
|
||||||
|
$sql = "UPDATE settings SET valint=? WHERE userid=? AND sno=1";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
try {
|
||||||
|
$sth->execute([$vid, $user->id]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$g_message->Add(sprintf(_('Selected vessel %d'), $vid));
|
||||||
|
$user->load_vessel();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
if ($user->role != 'captain') {
|
||||||
|
$g_error->Add(_('Access denied. You are not the captain.'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$p[':vesselname'] = gpc_get_string($_POST, 'vesselname');
|
||||||
|
$p[':model'] = gpc_get_string($_POST, 'model');
|
||||||
|
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$keys = array_keys($p);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':'); }, $keys));
|
||||||
|
$pnames = join(',', $keys);
|
||||||
|
$sth = $pdo->prepare("INSERT INTO vessel ($fields) VALUES ($pnames)");
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$id = $pdo->LastInsertId();
|
||||||
|
// autoselect newly created vessel
|
||||||
|
$sql = "UPDATE settings SET valint=? WHERE userid=? AND sno=1";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
try {
|
||||||
|
$sth->execute([$id, $user->id]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$g_message->Add(sprintf(_('Selected new vessel %d'), $vid));
|
||||||
|
$user->load_vessel();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
if ($user->role != 'captain') {
|
||||||
|
$g_error->Add(_('Access denied. You are not the captain.'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// $p[':vtype'] = gpc_get_string($_POST, 'vtype');
|
||||||
|
$p[':vesselname'] = gpc_get_string($_POST, 'vesselname');
|
||||||
|
$p[':model'] = gpc_get_string($_POST, 'model');
|
||||||
|
$p[':loa'] = gpc_get_float($_POST, 'loa');
|
||||||
|
$p[':lwl'] = gpc_get_float($_POST, 'lwl');
|
||||||
|
$p[':beam'] = gpc_get_float($_POST, 'beam');
|
||||||
|
$p[':draught'] = gpc_get_float($_POST, 'draught');
|
||||||
|
$p[':draught_min'] = gpc_get_float($_POST, 'draught_min');
|
||||||
|
$p[':displacement'] = gpc_get_int($_POST, 'displacement');
|
||||||
|
$p[':ballast'] = gpc_get_int($_POST, 'ballast');
|
||||||
|
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':') . '=' . $s; }, array_keys($p)));
|
||||||
|
$sth = $pdo->prepare("UPDATE vessel SET $fields WHERE vid=:vid");
|
||||||
|
$p[':vid'] = gpc_get_int($_POST, 'id');
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(_('Unknown function!'));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
|
||||||
|
echo '<h1>', _('Yacht data'), "</h1>\n";
|
||||||
|
|
||||||
|
echo '<p>', _('User'), ': ', $user->displayname, ' (', $user->role, ')', "</p>\n";
|
||||||
|
|
||||||
|
// Fetch current selected vessel number
|
||||||
|
$sql = "SELECT valint FROM settings WHERE userid=? AND sno=1";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$user->id]);
|
||||||
|
$res = $sth->fetch(PDO::FETCH_NUM);
|
||||||
|
$vid = ($res[0]);
|
||||||
|
|
||||||
|
// Switch between vessels
|
||||||
|
$sth = $pdo->query("SELECT vid, vesselname, model FROM vessel ORDER BY vid");
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<form class="row" method="post">', "\n";
|
||||||
|
echo '<div class="col-1">', "\n";
|
||||||
|
echo '<label class="form-label" for="vid">Yacht:</label>';
|
||||||
|
echo "</div>\n";
|
||||||
|
echo '<div class="col-4">', "\n";
|
||||||
|
echo '<select class="form-select" name="vid" id="vid">', "\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo '<option value="', $row['vid'], '"', ($row['vid'] == $vid ? ' selected>' : '>');
|
||||||
|
echo $row['vesselname'], ' - ', $row['model'];
|
||||||
|
echo "</option>\n";
|
||||||
|
}
|
||||||
|
echo "</select>\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
echo '<div class="col">', "\n";
|
||||||
|
echo '<button type="submit" class="btn btn-secondary" name="submit[select]">', _('Select'), '</button>', "\n";
|
||||||
|
echo '<button type="submit" class="btn btn-secondary" name="submit[add]">', _('Add yacht'), '</button>', "\n";
|
||||||
|
echo "</div>\n";
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
// Get current vessel data
|
||||||
|
$sql = "SELECT vesselname, model, loa, lwl, beam, draught, draught_min,"
|
||||||
|
. " displacement, ballast, remarks "
|
||||||
|
. "FROM vessel "
|
||||||
|
. "WHERE vid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$vid]);
|
||||||
|
$vessel = $sth->fetch();
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php /* <svg viewbox="0 0 1024 768">
|
||||||
|
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
|
||||||
|
<rect x="0" y="0" width="1024" height="768" stroke="black" fill="none" />
|
||||||
|
<text x="0" y="20" font-size="12" fill="#ccc" text-anchor="start">Elizabethan 29</text>
|
||||||
|
<line x1="0" y1="0" x2="100" y2="100" />
|
||||||
|
</svg> */ ?>
|
||||||
|
<br>
|
||||||
|
<svg
|
||||||
|
width="680.8349"
|
||||||
|
height="205.42085"
|
||||||
|
viewBox="0 0 180.13756 54.350934"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-18.454117,-34.670903)">
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 18.719809,61.846371 18.587517,51.734929 c 0,0 14.698452,-6.829606 22.491781,-8.894215 18.280597,-4.842895 36.646466,-7.606499 56.167649,-7.993756 29.649633,-0.588182 48.780143,4.813228 71.891193,12.372959 10.39946,3.401709 29.38622,14.626454 29.38622,14.626454"
|
||||||
|
id="path245" />
|
||||||
|
<use
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
xlink:href="#path245"
|
||||||
|
id="use461"
|
||||||
|
transform="matrix(1,0,0,-1,-4.9118388e-8,123.69274)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row my-4">
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><?=_('Boat data') ?></h5>
|
||||||
|
<table class="table table-sm">
|
||||||
|
<tr><td><?=_('Loa')?></td><td><?=format_float($vessel['loa'], 2, 'm')?></td></tr>
|
||||||
|
<tr><td><?=_('Lwl')?></td><td><?=format_float($vessel['lwl'], 2, 'm')?></td></tr>
|
||||||
|
<tr><td><?=_('Beam')?></td><td><?=format_float($vessel['beam'], 2, 'm')?></td></tr>
|
||||||
|
<tr><td><?=_('Draught')?></td><td><?=format_float($vessel['draught'], 2, 'm')?></td></tr>
|
||||||
|
<tr><td><?=_('Draught, min.')?></td><td><?=format_float($vessel['draught_min'], 2, 'm')?></td></tr>
|
||||||
|
<tr><td><?=_('Displacement')?></td><td><?=$vessel['displacement']?> kg</td></tr>
|
||||||
|
<tr><td><?=_('Ballast')?></td><td><?=$vessel['ballast']?> kg</td></tr>
|
||||||
|
</table>
|
||||||
|
<?php
|
||||||
|
// Edit vessel only for captain
|
||||||
|
if ($user->role == 'captain') {
|
||||||
|
echo '<a href="', $script, '?f=edit&id=', $user->vid, '" class="btn btn-primary" role="button">', _('Edit'), "</a>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div><?php /* card */ ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><?=_('Statistics') ?></h5>
|
||||||
|
<?php
|
||||||
|
// Statistics
|
||||||
|
|
||||||
|
// Storage: 0 - default, 1 - tank
|
||||||
|
$stype = [ 0 => _('Default'), 1 => _('Tank')];
|
||||||
|
$sql = "SELECT stype, COUNT(stype) "
|
||||||
|
. "FROM storage "
|
||||||
|
. "WHERE vid=? "
|
||||||
|
. "GROUP BY stype "
|
||||||
|
. "ORDER BY stype";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$vid]);
|
||||||
|
$res = $sth->fetchAll(PDO::FETCH_NUM);
|
||||||
|
echo '<table class="table table-sm">', "\n";
|
||||||
|
echo '<tr><td colspan="2">', _('Storage type') , "</td>";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr><td>", $stype[$row[0]], "</td><td>", $row[1], "</td></tr>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boxes
|
||||||
|
$sth = $pdo->prepare("SELECT COUNT(*) FROM box INNER JOIN storage USING (sid) WHERE vid=?");
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
echo '<tr><td>', _('Boxes'), '</td><td>', $sth->fetchColumn(), "</td></tr>\n";
|
||||||
|
|
||||||
|
// Equipment
|
||||||
|
$sth = $pdo->prepare("SELECT COUNT(*) FROM equipment WHERE vid=?");
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
echo '<tr><td colspan="2">', _('Equipment') , "</td>";
|
||||||
|
echo '<tr><td>', _('Count'), '</td><td>', $sth->fetchColumn(), "</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 boxtype='storage' AND vid=:vid "
|
||||||
|
. "UNION "
|
||||||
|
. "SELECT COUNT(*) AS n FROM inventory JOIN box USING (boxid) JOIN storage ON (box.sid=storage.sid) WHERE boxtype='box' AND vid=:vid"
|
||||||
|
. ") AS x";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':vid', $user->vid, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
|
||||||
|
// Tasks
|
||||||
|
echo '<tr><td colspan="2">', _('Inventory') , "</td>";
|
||||||
|
echo '<tr><td>', _('Count'), '</td><td>', $sth->fetchColumn(), "</td></tr>\n";
|
||||||
|
|
||||||
|
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div><?php /* card */ ?>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><?=_('Base data')?></h5>
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
<li class="list-group-item"><a href="dropdown.php"><?=_('Selection lists')?></a></li>
|
||||||
|
<li class="list-group-item"><a href="storage.php"><?=_('Storage')?></a></li>
|
||||||
|
<li class="list-group-item"><a href="company.php"><?=_('Companies')?></a></li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
<h5 class="card-title"><?=_('Additional modules')?></h5>
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
<li class="list-group-item"><a href="measurement.php"><?=_('Measurements')?></a></li>
|
||||||
|
<li class="list-group-item"><a href="checklist.php"><?=_('Checklists')?></a></li>
|
||||||
|
<li class="list-group-item"><a href="search.php"><?=_('Search')?></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div><?php /* col */ ?>
|
||||||
|
</div><?php /* row */ ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add additional yacht'), "</h2>\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="vesselname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="vesselname" name="vesselname" required autofocus>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="model" class="form-label"><?=_('Model')?></label>
|
||||||
|
<input type="text" class="form-control" id="model" name="model">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$project->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT vesselname, vtype, model, loa, lwl, beam, draught, draught_min,"
|
||||||
|
. " displacement, ballast, remarks "
|
||||||
|
. "FROM vessel "
|
||||||
|
. "WHERE vid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
$vessel = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
?>
|
||||||
|
<h2><?=_('Edit Yacht')?></h2>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$user->vid?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="vesselname" class="form-label"><?=_('Vesselname')?></label>
|
||||||
|
<input type="text" class="form-control" id="vesselname" name="vesselname" value="<?=$vessel->vesselname ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="model" class="form-label"><?=_('Model')?></label>
|
||||||
|
<input type="text" class="form-control" id="model" name="model" value="<?=$vessel->model ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="loa" class="form-label"><?=_('LoA')?></label>
|
||||||
|
<input type="text" class="form-control" id="loa" name="loa" value="<?=format_float($vessel->loa, 2) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="lwl" class="form-label"><?=_('LwL')?></label>
|
||||||
|
<input type="text" class="form-control" id="lwl" name="lwl" value="<?=format_float($vessel->lwl, 2) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="beam" class="form-label"><?=_('Beam')?></label>
|
||||||
|
<input type="text" class="form-control" id="beam" name="beam" value="<?=format_float($vessel->beam, 2) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="draught" class="form-label"><?=_('Draught')?></label>
|
||||||
|
<input type="text" class="form-control" id="draught" name="draught" value="<?=format_float($vessel->draught, 2) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="draught_min" class="form-label"><?=_('Draught, min.')?></label>
|
||||||
|
<input type="text" class="form-control" id="draught_min" name="draught_min" value="<?=format_float($vessel->draught_min, 2) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="displacement" class="form-label"><?=_('Displacement')?></label>
|
||||||
|
<input type="number" input-mode="decimal" min="0" max="100000" step="1" class="form-control" id="displacement" name="displacement" value="<?=$vessel->displacement ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="ballast" class="form-label"><?=_('Ballast')?></label>
|
||||||
|
<input type="number" input-mode="decimal" min="0" max="100000" step="1" class="form-control" id="ballast" name="ballast" value="<?=$vessel->ballast ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$vessel->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
form_edit_buttons($g_scriptname, $user->vid);
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,353 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle=_('Inventory');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
$opt_storage = db_get_opt_storage($user->vid);
|
||||||
|
$opt_box = db_get_opt_box($user->vid);
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$invname = gpc_get_string($_POST, 'invname');
|
||||||
|
$number = gpc_get_int($_POST, 'number');
|
||||||
|
$boxtype = gpc_get_string($_POST, 'boxtype');
|
||||||
|
$sid = gpc_get_int($_POST, 'sid');
|
||||||
|
$boxid = gpc_get_int($_POST, 'boxid');
|
||||||
|
$sql = "INSERT INTO inventory "
|
||||||
|
. " (invname, invcond, number, boxtype, sid, boxid) "
|
||||||
|
. "VALUES "
|
||||||
|
. " (:invname, 'good', :number, :boxtype, :sid, :boxid)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':invname', $invname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':number', $number, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':boxtype', $boxtype, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':sid', $sid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':boxid', $boxid, PDO::PARAM_INT);
|
||||||
|
try {
|
||||||
|
$sth->execute();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$id = $pdo->LastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$invname = gpc_get_string($_POST, 'invname');
|
||||||
|
$number = gpc_get_int($_POST, 'number');
|
||||||
|
$boxtype = gpc_get_string($_POST, 'boxtype');
|
||||||
|
$sid = gpc_get_int($_POST, 'sid');
|
||||||
|
$boxid = gpc_get_int($_POST, 'boxid');
|
||||||
|
$weight = min(gpc_get_float($_POST, 'weight'), 999.99); // limit max value
|
||||||
|
$price = gpc_get_currency($_POST, 'price');
|
||||||
|
$purchdate = gpc_get_date($_POST, 'purchdate');
|
||||||
|
$invcond = gpc_get_string($_POST, 'invcond');
|
||||||
|
$sql = "UPDATE inventory "
|
||||||
|
. "SET invname=:invname,"
|
||||||
|
. " number=:number,"
|
||||||
|
. " boxtype=:boxtype,"
|
||||||
|
. " sid=:sid,"
|
||||||
|
. " boxid=:boxid,"
|
||||||
|
. " weight=:weight,"
|
||||||
|
. " price=:price,"
|
||||||
|
. " purchdate=:purchdate,"
|
||||||
|
. " invcond=:invcond "
|
||||||
|
. "WHERE invid=:invid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':invid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':invname', $invname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':number', $number, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':boxtype', $boxtype, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':sid', $sid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':boxid', $boxid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':weight', $weight);
|
||||||
|
$sth->bindValue(':price', $price);
|
||||||
|
$sth->bindValue(':purchdate', $purchdate);
|
||||||
|
$sth->bindValue(':invcond', $invcond, PDO::PARAM_STR);
|
||||||
|
try {
|
||||||
|
$sth->execute();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// 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']);
|
||||||
|
$sth = $pdo->prepare("DELETE FROM inventory WHERE invid=?");
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$g_message->Add(sprintf(_('Deleted inventory no. %d'), $id));
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_('Unknown function!'), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 "<h1>$pagetitle</h1>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT i.invid, i.invname, i.number, i.invcond, s.sname AS container "
|
||||||
|
. "FROM inventory AS i JOIN storage AS s ON (i.boxtype='storage' AND i.sid=s.sid)"
|
||||||
|
. "WHERE s.vid=:vid "
|
||||||
|
. "UNION "
|
||||||
|
. "SELECT i.invid, i.invname, i.number, i.invcond, b.label AS container "
|
||||||
|
. "FROM inventory AS i JOIN box AS b ON (i.boxtype='box' AND i.boxid=b.boxid) "
|
||||||
|
. " JOIN storage AS s ON (b.sid=s.sid) "
|
||||||
|
. "WHERE s.vid=:vid "
|
||||||
|
. "ORDER BY invname";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':vid', $user->vid, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<th>" . _('Name') . "</th>\n";
|
||||||
|
echo "<th>" . _('Container') . "</th>";
|
||||||
|
echo "<th>" . _('Number') . "</th>";
|
||||||
|
echo "<th>" . _('Condition') . "</th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo '<td>', $row['invname'], "</td>\n";
|
||||||
|
echo "<td>". $row['container'] ."</td>\n";
|
||||||
|
echo "<td>". $row['number'] ."</td>\n";
|
||||||
|
echo "<td>". $row['invcond'] ."</td>\n";
|
||||||
|
form_action_buttons($g_scriptname, $row['invid']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
// Table summary
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="6">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Inventory'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="invname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="invname" name="invname">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="number" class="form-label"><?=_('Number')?></label>
|
||||||
|
<input type="number" class="form-control" id="number" name="number" value="1">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="boxtype" class="form-label"><?=_('Boxtype')?></label>
|
||||||
|
<select class="form-select" name="boxtype" id="boxtype">
|
||||||
|
<option value="box"><?=_('Box')?></option>
|
||||||
|
<option value="storage"><?=_('Storage')?></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('sid', _('Storage'), $opt_storage);
|
||||||
|
form_create_select('boxid', _('Box'), $opt_box);
|
||||||
|
?>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT invname, boxtype, sid, boxid, number, weight, price, purchdate, invcond "
|
||||||
|
. "FROM inventory "
|
||||||
|
. "WHERE invid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$inventory = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
// boxtype can be storage or box
|
||||||
|
switch ($inventory->boxtype) {
|
||||||
|
case 'storage':
|
||||||
|
$sql = "SELECT sname, vid FROM storage WHERE sid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$inventory->sid]);
|
||||||
|
$row = $sth->fetch();
|
||||||
|
$storagename = $row['sname'];
|
||||||
|
$vid = $row['vid'];
|
||||||
|
break;
|
||||||
|
case 'box':
|
||||||
|
// Future: Boxes can also be nested!
|
||||||
|
// Recursive Function "get_storage_for_box()"
|
||||||
|
$sql = "SELECT sid, label FROM box WHERE boxid=?";
|
||||||
|
// TODO Load additional box data
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$inventory->boxid]);
|
||||||
|
$box = $sth->fetch();
|
||||||
|
$sql = "SELECT sname, vid FROM storage WHERE sid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$box['sid']]);
|
||||||
|
$row = $sth->fetch();
|
||||||
|
$storagename = $row['sname'];
|
||||||
|
$vid = $row['vid'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<h2>', $inventory->invname, "</h2>\n";
|
||||||
|
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th style="width:20%">', _('Box type'),"</th><td>", $inventory->boxtype, "</td></tr>\n";
|
||||||
|
|
||||||
|
// Container with link
|
||||||
|
echo "<tr><th>", _('Container'),"</th><td>", sprintf(_('%s in %s'), $box['label'], $storagename);
|
||||||
|
echo "</td></tr>\n";
|
||||||
|
|
||||||
|
echo "<tr><th>", _('Location ID'), "</th><td>", $inventory->locationid, "</td></tr>\n";
|
||||||
|
echo "<tr><th>", _('Number'), "</th><td>", $inventory->number, "</td></tr>\n";
|
||||||
|
echo "<tr><th>", _('Weight'), "</th><td>", format_float($inventory->weight, 2, 'kg'), "</td></tr>\n";
|
||||||
|
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>", $inventory->invcond, "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT invname, boxtype, sid, boxid, number, weight, price, purchdate, invcond "
|
||||||
|
. "FROM inventory "
|
||||||
|
. "WHERE invid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$inventory = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<h2><?=_('Edit Inventory')?></h2>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="invname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="invname" name="invname" value="<?=$inventory->invname ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="number" class="form-label"><?=_('Number')?></label>
|
||||||
|
<input type="number" class="form-control" id="number" name="number" value="<?=$inventory->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($inventory->weight); ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="boxtype" class="form-label"><?=_('Boxtype')?></label>
|
||||||
|
<select class="form-select" name="boxtype" id="boxtype">
|
||||||
|
<option value="box"><?=_('Box')?></option>
|
||||||
|
<option value="storage"><?=_('Storage')?></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('sid', _('Storage'), $opt_storage);
|
||||||
|
form_create_select('boxid', _('Box'), $opt_box);
|
||||||
|
?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="price" class="form-label"><?=sprintf(_('Price, %s'), $g_lconv['currency_symbol']); ?></label>
|
||||||
|
<input type="text" class="form-control" id="price" name="price" value="<?=format_float($inventory->price) ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="purchdate"><?=_('Purchase date')?></label>
|
||||||
|
<input type="date" class="form-control" id="purchdate" name="purchdate" value="<?=$inventory->purchdate ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="invcond" class="form-label"><?=_('Condition')?></label>
|
||||||
|
<select name="invcond" id="invcond" class="form-control">
|
||||||
|
<?php
|
||||||
|
$cond = array(
|
||||||
|
'good' => _('Good'),
|
||||||
|
'normal' => _('Normal'),
|
||||||
|
'bad' => _('Bad'),
|
||||||
|
'repairable' => _('Repairable'),
|
||||||
|
'defect' => _('Defect'),
|
||||||
|
'unknown' => _('Unknown')
|
||||||
|
);
|
||||||
|
foreach ($cond as $k => $v) {
|
||||||
|
echo '<option value="', $k, '"';
|
||||||
|
if ($k == $inventory->invcond) {
|
||||||
|
echo ' selected';
|
||||||
|
}
|
||||||
|
echo '>', $v. "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
form_edit_buttons($g_scriptname, $id);
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
$sql = "SELECT invname FROM inventory WHERE invid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$inventory = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete Inventory'), "</h2>\n";
|
||||||
|
echo '<p>', sprintf(_('Record no. %d'), $id), "</p>\n";
|
||||||
|
echo '<p>Name: ', $inventory->invname, "</p>";
|
||||||
|
|
||||||
|
echo '<p>', _('Deleting an inventory item is final. There is no way back. Only delete if you are absolute sure.'), "</p>\n";
|
||||||
|
$_SESSION['token'] = bin2hex(random_bytes(8));
|
||||||
|
form_delete_buttons($g_scriptname, $id, $_SESSION['token']);
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// TODO Code to handle page call with already logged on user
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
session_name(APP_SESSION);
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if (isset($_POST['login'])) {
|
||||||
|
$username = substr($_POST['username'], 0, 20);
|
||||||
|
$password = substr($_POST['password'], 0, 32);
|
||||||
|
if (!$user->login($username, $password)) {
|
||||||
|
$err = $user->get_last_error();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$username = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="robots" content="noindex,nofollow">
|
||||||
|
<title><?=APP_TITLE_SHORT?> - Login</title>
|
||||||
|
<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>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<section class="mx-auto my-5" style="max-width:32rem;">
|
||||||
|
<div class="card card-form mt-2 mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<?=APP_TITLE?>
|
||||||
|
</div>
|
||||||
|
<div class="row my-3">
|
||||||
|
<div class="col">
|
||||||
|
<img src="sailboat.svg" class="img-fluid rounded-start" alt="sailboat">
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><?=sprintf(_('Login to %s'), APP_TITLE_SHORT)?></h5>
|
||||||
|
<form id="login" action="login.php" method="post">
|
||||||
|
<div class="mb-3 mt-3">
|
||||||
|
<label for="username" class="form-label"><?=_('Username:')?></label>
|
||||||
|
<input type="text" class="form-control" required autofocus size="20" maxlength="20" name="username" id="username" value="<?=$username?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3 mt-3">
|
||||||
|
<label for="password" class="form-label"><?=_('Password:')?></label>
|
||||||
|
<input type="password" class="form-control" required size="20" maxlength="32" name="password" id="password">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
if (isset($err)) {
|
||||||
|
echo '<div class="alert alert-danger alert-dismissible fade show role="alert"">';
|
||||||
|
echo '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>';
|
||||||
|
echo '<b>', _('Error'), ':</b> ', $err;
|
||||||
|
echo "</div>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<button type="submit" class="btn btn-primary" title="<?php printf(_('Logon to %s'), APP_TITLE_SHORT); ?>" name="login" value="1">
|
||||||
|
<span class="bi bi-caret-right"></span>
|
||||||
|
<?=_('Login')?>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div> <!-- card body -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$user->logout();
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="robots" content="noindex,nofollow">
|
||||||
|
<title><?=APP_TITLE_SHORT?> - Login</title>
|
||||||
|
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<script src="bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<section class="mx-auto my-5" style="max-width:23rem;">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<?=_('Logout')?>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title"><?=sprintf(_('<b>%s</b> is now logged out'), $user->displayname)?></h5>
|
||||||
|
<p class="card-text"><?=sprintf(_('Thank you for using %s.'), APP_TITLE_SHORT)?></p>
|
||||||
|
<p class="card-text"><?=sprintf(_('Always feel free to send improvements, suggestions, error messages or anything else to %s.'), $g_mailto_webmaster)?></p>
|
||||||
|
<a class="btn btn-primary" href="login.php"><?=_('New login')?></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Maintenance');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
// Equipment options
|
||||||
|
$opt_equipment = array( 0 => _('*** unassigned ***'));
|
||||||
|
$sql = "SELECT eid, ename FROM equipment WHERE vid=? ORDER BY ename";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
$opt_equipment[$row['eid']] = $row['ename'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$eid = gpc_get_int($_POST, 'eid');
|
||||||
|
$activities = gpc_get_string($_POST, 'activities', 80);
|
||||||
|
$sql = "INSERT INTO maintenance "
|
||||||
|
. " (vid, eid, activities) "
|
||||||
|
. "VALUES "
|
||||||
|
. " (:vid, :eid, :activities)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':vid', $user->vid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':eid', $eid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':activities', $activities, PDO::PARAM_STR);
|
||||||
|
$sth->execute();
|
||||||
|
$id = $pdo->LastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$eid = gpc_get_int($_POST, 'eid');
|
||||||
|
$activities = gpc_get_string($_POST, 'activities', 80);
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "UPDATE maintenance "
|
||||||
|
. "SET activities=:activities,"
|
||||||
|
. " eid=:eid,"
|
||||||
|
. " remarks=:remarks "
|
||||||
|
. "WHERE maintid=:maintid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':maintid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':eid', $eid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':activities', $activities, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
$sth->execute();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_("Unknown function '%s'!"), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
echo '<h1>', $pagetitle, "</h1>\n";
|
||||||
|
|
||||||
|
$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";
|
||||||
|
$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>" . _('Activities') . "</th>";
|
||||||
|
echo "<th>" . _('Equipment') . "</th>";
|
||||||
|
echo "<th>" . _('Remarks') . "</th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\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 '<a title="', _('Edit'), '" href="', $g_scriptname, '?f=edit&id=', $row['maintid'], '"><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 "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Maintenance'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="activities" class="form-label"><?=_('Activities')?></label>
|
||||||
|
<input type="text" class="form-control" id="activities" name="activities">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
// TODO
|
||||||
|
// Add link to equipment, perhaps later with modal dialog?
|
||||||
|
?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="eid" class="form-label"><?=_('Equipment')?></label>
|
||||||
|
<select name="eid" id="eid" class="form-control">
|
||||||
|
<?php
|
||||||
|
foreach ($opt_equipment as $k => $v) {
|
||||||
|
echo '<option value="', $k, '">', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
echo '<h2>', _('View Maintenance'), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT m.activities, m.eid, m.remarks, e.ename "
|
||||||
|
. "FROM maintenance AS m LEFT OUTER JOIN equipment AS e USING (eid) "
|
||||||
|
. "WHERE m.maintid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$maint = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
if (isset($maint->eid)) {
|
||||||
|
$sql = "SELECT r.docid, d.filename, d.title, d.hash, d.extension "
|
||||||
|
. "FROM docref AS r INNER JOIN document AS d USING (docid) "
|
||||||
|
. "WHERE r.reftype='equipment' AND r.refid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$maint->eid]);
|
||||||
|
$docs = $sth->fetchAll();
|
||||||
|
} else {
|
||||||
|
$maint->ename = _('n/a');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bootstrap grid
|
||||||
|
echo '<div class="container">';
|
||||||
|
echo '<div class="row">';
|
||||||
|
echo '<div class="col">';
|
||||||
|
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th>', _('Activities'),"</th><td>", $maint->activities, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Equipment'),"</th><td>", $maint->ename, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Remarks'),"</th><td>", $maint->remarks, "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
echo '</div>'; // Column break
|
||||||
|
echo '<div class="col">';
|
||||||
|
|
||||||
|
// TODO Show documents for equipment
|
||||||
|
?>
|
||||||
|
<p>Documents</p>
|
||||||
|
<?php
|
||||||
|
echo '<ul>', "\n";
|
||||||
|
foreach ($docs as $d) {
|
||||||
|
echo '<li>', $d['title'] ?? $d['filename'], ' (', $d['docid'], ")</li>\n";
|
||||||
|
}
|
||||||
|
echo "</ul>\n";
|
||||||
|
|
||||||
|
|
||||||
|
echo '</div>'; // col
|
||||||
|
echo '</div>'; // row
|
||||||
|
echo '</div>'; // container
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT activities, eid, remarks "
|
||||||
|
. "FROM maintenance "
|
||||||
|
. "WHERE maintid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$maint = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit Maintenance'), "</h2>\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="activities" class="form-label"><?=_('Activities')?></label>
|
||||||
|
<input type="text" class="form-control" id="activities" name="activities" value="<?=$maint->activities ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="eid" class="form-label"><?=_('Equipment')?></label>
|
||||||
|
<select name="eid" id="eid" class="form-control">
|
||||||
|
<?php
|
||||||
|
foreach ($opt_equipment as $k => $v) {
|
||||||
|
echo '<option value="', $k;
|
||||||
|
if ($maint->eid == $k) {
|
||||||
|
echo ' selected';
|
||||||
|
}
|
||||||
|
echo '">', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$maint->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
form_edit_buttons($g_scriptname, $id);
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete Maintenance'), "</h2>\n";
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle=_('Manual');
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<h1>Yacht Management System</h1>
|
||||||
|
<h2>Integriertes Handbuch</h2>
|
||||||
|
|
||||||
|
<p>Es können mehrere Yachten mit dem Programm verwaltet werden.
|
||||||
|
Die Umschaltung erfolgt über eine Auswahlliste auf der Übersichtsseite.</p>
|
||||||
|
<p>Die Yachtdaten können nur mit de Berechtigungsebene <em>captain</em>
|
||||||
|
verändert werden.</p>
|
||||||
|
|
||||||
|
<p>Bei Neuanlage eines Datensatzes werden nur die wichtigsten Felder
|
||||||
|
angezeigt. Weitere Felder können im Anschluß über die Bearbeiten-Funktion
|
||||||
|
ausgefüllt werden.</p>
|
||||||
|
|
||||||
|
<h3>Stauraum</h3>
|
||||||
|
<p>Der Stauraum teilt sich in verschiedene Bereiche auf.
|
||||||
|
Diese sind über eine fixe Position an Bord einstellbar.</p>
|
||||||
|
|
||||||
|
<p>Zusätzlich zum festen Stauraum können auch Kisten definiert werden.
|
||||||
|
Eine Kiste kann in einen Stauraum gelegt werden. Da sie beweglich ist,
|
||||||
|
kann sie auch als Ganzes auf eine andere Yacht übergeben werden.</p>
|
||||||
|
|
||||||
|
<p>Es existiert ein Koordinatensystem. Die Einheit ist Millimeter (mm).
|
||||||
|
Der Ursprung ist achtern Mittschiffs. Die X-Achse verläuft in Längsrichtung
|
||||||
|
der Yacht. Die Y-Achse verläuft zur Querrichtung, Koorinaten auf der Backbordseite
|
||||||
|
sind negativ, auf der Steuerbordseite positiv.
|
||||||
|
Die Z-Achse geht in Richtung Mastspitze. Der Nullpunkt liegt auf Höhe der
|
||||||
|
Wasserlinie.</p>
|
||||||
|
|
||||||
|
<h3>Ausrüstung</h3>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<h3>Inventar</h3>
|
||||||
|
<p>Unter Inventar sind bewegliche Dinge zusammengefaßt.
|
||||||
|
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>
|
||||||
|
|
||||||
|
<h3>Proviant</h3>
|
||||||
|
<p>Proviant ist verderblich.
|
||||||
|
Es wird das Einlagerungsdatum erfaßt und das Haltbarkeitsdatum</p>
|
||||||
|
|
||||||
|
<h3>Wartung</h3>
|
||||||
|
<p>Es können einmalige und wiederkehrende Wartungen erfaßt werden</p>
|
||||||
|
<p>Eine wiederkehrende Wartung kann aufgrund Zeit, z.B. 1x jährlich,
|
||||||
|
oder nach Betriebsstunden definiert werden.</p>
|
||||||
|
|
||||||
|
<h3>Projekte</h3>
|
||||||
|
<p>Einem Projekt werden Aufgaben zugeordnet, es hat einen Status wie
|
||||||
|
z.B. <em>neu</em>, <em>laufend</em> oder <em>erledigt</em>.</p>
|
||||||
|
|
||||||
|
<h3>Firmen</h3>
|
||||||
|
<p>Es können verschiedene Arten von Firmen hinterlegt werden, wie
|
||||||
|
beispielsweise Hersteller, Lieferanten oder Dienstleister.</p>
|
||||||
|
|
||||||
|
<h3>Dokumente</h3>
|
||||||
|
<p>Ein Dokument kann mehrfach zugeordnet werden. Z.B. einem
|
||||||
|
Ausrüstungsgegenstand und gleichzeitig einem Projekt oder einer Aufgabe.</p>
|
||||||
|
<p>Es stehen verschiedene Dokumentarten zur Verfügung:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Fotos bzw. Bilder als png- oder jpg-Dateien</li>
|
||||||
|
<li>Zeichnungen als svg-Dateien</li>
|
||||||
|
<li>Dokumente als pdf-Dateien</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Checklisten</h3>
|
||||||
|
<p>Es ist eine Historie vorgesehen.</p>
|
||||||
|
|
||||||
|
<h3>Ersatzteile</h3>
|
||||||
|
<p>Die Verwaltung von Ersatzteilen erfolgt normalerweise über das Inventar.</p>
|
||||||
|
|
||||||
|
<h3>Maße / Messungen</h3>
|
||||||
|
<p>Messungen können hier dokumentiert werden. Eine Zuordnung zur Ausrüstung
|
||||||
|
ist vorgesehen.</p>
|
||||||
|
<p>In einer Messung können ein bis drei Werte gespeichert werden. Damit
|
||||||
|
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>Benutzer</h3>
|
||||||
|
<p>Benutzer können nicht über die Web-GUI eingerichtet werden.</p>
|
||||||
|
<p>Es gibt die Berechtigungsebenen <em>Kapitän (captain)</em>,
|
||||||
|
<em>Steuermann (helmsman)</em> und <em>Matrose (sailor)</em>.
|
||||||
|
|
||||||
|
<h3>Stammdaten</h3>
|
||||||
|
<p>Diese Daten ändern sich nicht sehr häufig, sind aber für den Betrieb
|
||||||
|
essentiell. Stanndaten sind beispielsweise Firmen, Auswahllisten oder
|
||||||
|
auch der Stauraum.</p>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,284 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Measurements');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
$opt_unit = db_get_options(8);
|
||||||
|
$opt_accuracy = array(
|
||||||
|
'unknown' => _('Unknown'),
|
||||||
|
'precise' => _('Precise'),
|
||||||
|
'normal' => _('Normal'),
|
||||||
|
'rough' => _('Rough'),
|
||||||
|
'estimated' => _('Estimated')
|
||||||
|
);
|
||||||
|
$opt_dimensions = array(
|
||||||
|
1 => _('1D'),
|
||||||
|
2 => _('2D'),
|
||||||
|
3 => _('3D')
|
||||||
|
);
|
||||||
|
$opt_equipment = array(-1 => _('unassigned'));
|
||||||
|
$sth = $pdo->prepare("SELECT eid, ename FROM equipment WHERE vid=? ORDER BY ename");
|
||||||
|
$sth->execute([$user->vid]);
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
$opt_equipment[$row['eid']] = $row['ename'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$p[':mname'] = gpc_get_string($_POST, 'mname');
|
||||||
|
$p[':note'] = gpc_get_string($_POST, 'note');
|
||||||
|
$p[':nval'] = gpc_get_int($_POST, 'nval'); // 1 to 3 dimensions
|
||||||
|
$p[':val1'] = gpc_get_int($_POST, 'val1');
|
||||||
|
$p[':val2'] = NULL;
|
||||||
|
$p[':val3'] = NULL;
|
||||||
|
if ($p[':nval'] > 1) {
|
||||||
|
$p[':val2'] = gpc_get_int($_POST, 'val2');
|
||||||
|
}
|
||||||
|
if ($p[':nval'] > 2) {
|
||||||
|
$p[':val3'] = gpc_get_int($_POST, 'val3');
|
||||||
|
}
|
||||||
|
$p[':unit'] = gpc_get_int($_POST, 'unit');
|
||||||
|
$p[':accuracy'] = gpc_get_string($_POST, 'accuracy');
|
||||||
|
$p[':eid'] = gpc_get_int($_POST, 'eid');
|
||||||
|
if ($p[':eid'] == -1) {
|
||||||
|
$p[':eid'] = NULL;
|
||||||
|
}
|
||||||
|
$keys = array_keys($p);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':'); }, $keys));
|
||||||
|
$pnames = join(',', $keys);
|
||||||
|
$sth = $pdo->prepare("INSERT INTO measurement ($fields) VALUES ($pnames)");
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$id = $pdo->LastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$p[':mname'] = gpc_get_string($_POST, 'mname');
|
||||||
|
$p[':nval'] = gpc_get_int($_POST, 'nval'); // 1 to 3 dimensions
|
||||||
|
$p[':val1'] = gpc_get_int($_POST, 'val1');
|
||||||
|
$p[':val2'] = NULL;
|
||||||
|
$p[':val3'] = NULL;
|
||||||
|
if ($p[':nval'] > 1) {
|
||||||
|
$p[':val2'] = gpc_get_int($_POST, 'val2');
|
||||||
|
}
|
||||||
|
if ($p[':nval'] > 2) {
|
||||||
|
$p[':val3'] = gpc_get_int($_POST, 'val3');
|
||||||
|
}
|
||||||
|
$p[':unit'] = gpc_get_int($_POST, 'unit');
|
||||||
|
$p[':accuracy'] = gpc_get_string($_POST, 'accuracy');
|
||||||
|
$p[':mdate'] = gpc_get_date($_POST, 'mdate');
|
||||||
|
$p[':note'] = gpc_get_string($_POST, 'note');
|
||||||
|
$p[':eid'] = gpc_get_int($_POST, 'eid');
|
||||||
|
if ($p[':eid'] == -1) {
|
||||||
|
$p[':eid'] = NULL;
|
||||||
|
}
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':') . '=' . $s; }, array_keys($p)));
|
||||||
|
$sth = $pdo->prepare("UPDATE measurement SET $fields WHERE mid=:mid");
|
||||||
|
$p[':mid'] = $id;
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// Security token needed!
|
||||||
|
if (gpc_get_string($_POST, 'token', 16) != $_SESSION['token']) {
|
||||||
|
$g_error->Add(_('Delete prohibited, invalid security token!'));
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_('Unknown function!'), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
function format_vals($n, $v1, $v2, $v3) {
|
||||||
|
if ($n == 1) {
|
||||||
|
return $v1;
|
||||||
|
} elseif ($n == 2) {
|
||||||
|
return $v1 . 'x'. $v2;
|
||||||
|
} else {
|
||||||
|
return $v1 . 'x'. $v2 . 'x' . $v3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT mid, mname, nval, val1, val2, val3, unit, accuracy, mdate, note, eid "
|
||||||
|
. "FROM measurement "
|
||||||
|
. "ORDER BY mname";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo '<th>', _('Measurement'), "</th>";
|
||||||
|
echo '<th>', _('Note'), "</th>";
|
||||||
|
echo '<th class="text-end">', _('Measured'), "</th>";
|
||||||
|
echo '<th>', _('Unit'), "</th>";
|
||||||
|
echo '<th>', _('Accuracy'), "</th>";
|
||||||
|
echo "<th></th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>", $row['mname'], "</td>\n";
|
||||||
|
echo "<td>", $row['note'], "</td>\n";
|
||||||
|
echo '<td class="text-end">', format_vals($row['nval'], $row['val1'], $row['val2'], $row['val3']), "</td>\n";
|
||||||
|
echo "<td>", $opt_unit[$row['unit']], "</td>\n";
|
||||||
|
echo "<td>", $opt_accuracy[$row['accuracy']], "</td>\n";
|
||||||
|
echo "<td>";
|
||||||
|
// Action buttons
|
||||||
|
form_action_buttons($g_scriptname, $row['mid']);
|
||||||
|
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 "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add measurement'), "</h2>\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="mname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="mname" name="mname" required autofocus>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="note" class="form-label"><?=_('Note')?></label>
|
||||||
|
<input type="text" class="form-control" id="note" name="note">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('nval', _('Dimensions'), $opt_dimensions);
|
||||||
|
?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="val1" class="form-label"><?=_('Value 1')?></label>
|
||||||
|
<input type="text" class="form-control" id="val1" name="val1">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="val2" class="form-label"><?=_('Value 2')?></label>
|
||||||
|
<input type="text" class="form-control" id="val1" name="val2">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="val3" class="form-label"><?=_('Value 3')?></label>
|
||||||
|
<input type="text" class="form-control" id="val3" name="val3">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('unit', _('Unit'), $opt_unit);
|
||||||
|
form_create_select('accuracy', _('Accuracy'), $opt_accuracy);
|
||||||
|
form_create_select('eid', _('Equipment'), $opt_equipment);
|
||||||
|
?>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT mname, nval, val1, val2, val3, unit, accuracy, note "
|
||||||
|
. "FROM measurement "
|
||||||
|
. "WHERE mid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$measurement = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit measurement'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="mname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="name" name="mname" value="<?=$measurement->mname ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="note" class="form-label"><?=_('Note')?></label>
|
||||||
|
<input type="text" class="form-control" id="note" name="note" value="<?=$measurement->note ?>">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('nval', _('Dimensions'), $opt_dimensions, $measurement->nval);
|
||||||
|
?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="val1"><?=_('Value 1')?></label>
|
||||||
|
<input type="number" min="0" class="form-control" id="val1" name="val1" value="<?=$measurement->val1 ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="val2"><?=_('Value 2')?></label>
|
||||||
|
<input type="number" min="0" class="form-control" id="val2" name="val2" value="<?=$measurement->val2 ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="val3"><?=_('Value 3')?></label>
|
||||||
|
<input type="number" min="0" class="form-control" id="val3" name="val3" value="<?=$measurement->val3 ?>">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('unit', _('Unit'), $opt_unit, $measurement->unit);
|
||||||
|
form_create_select('accuracy', _('Accuracy'), $opt_accuracy, $measurement->accuracy);
|
||||||
|
form_create_select('eid', _('Equipment'), $opt_equipment, $measurement->eid);
|
||||||
|
|
||||||
|
form_edit_buttons($g_scriptname, $id);
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Projects');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
$sql = "SELECT userid, displayname FROM user WHERE userid>0";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$opt_user = array();
|
||||||
|
foreach ($sth->fetchAll() as $row) {
|
||||||
|
$opt_user[$row['userid']] = $row['displayname'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$projname = gpc_get_string($_POST, 'projname');
|
||||||
|
$responsible = gpc_get_int($_POST, 'responsible');
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "INSERT INTO project "
|
||||||
|
. " (vid, projname, responsible, remarks) "
|
||||||
|
. "VALUES "
|
||||||
|
. " (:vid, :projname, :responsible, :remarks)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':vid', $user->vid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':projname', $projname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':responsible', $responsible, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
$sth->execute();
|
||||||
|
$id = $pdo->lastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$projname = gpc_get_string($_POST, 'projname');
|
||||||
|
$startdate = gpc_get_date($_POST, 'startdate');
|
||||||
|
$duration = gpc_get_int($_POST, 'duration');
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "UPDATE project "
|
||||||
|
. "SET projname=:projname,"
|
||||||
|
. " startdate=:startdate,"
|
||||||
|
. " duration=:duration,"
|
||||||
|
. " remarks=:remarks "
|
||||||
|
. "WHERE projid=:projid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':projid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':projname', $projname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':startdate', $startdate, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':duration', $duration, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
$sth->execute();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_("Unknown function '%s'!"), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
echo '<h1>', $pagetitle, "</h1>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT projid, projname, startdate, duration, 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>" . _('Name') . "</th>";
|
||||||
|
echo "<th>" . _('Start date') . "</th>";
|
||||||
|
echo "<th>" . _('Duration') . "</th>";
|
||||||
|
echo "<th>" . _('Remarks') . "</th>";
|
||||||
|
echo "<th> </th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>". $row['projname'] ."</td>\n";
|
||||||
|
echo "<td>". $row['startdate'] ."</td>\n";
|
||||||
|
echo "<td>". $row['duration'] ."</td>\n";
|
||||||
|
echo "<td>". $row['remarks'] ."</td>\n";
|
||||||
|
// Action buttons
|
||||||
|
form_action_buttons($g_scriptname, $row['projid']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="5">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
echo "<h1>", _('Generic Tasks'), "</h1>\n";
|
||||||
|
echo "<p>", _('Tasks not assigned to any project'), "</p>\n";
|
||||||
|
$sql = "SELECT taskid, taskname "
|
||||||
|
. "FROM task "
|
||||||
|
. "WHERE projid IS NULL "
|
||||||
|
. "ORDER BY taskid";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<th>" . _('Name') . "</th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>". $row['taskname'] ."</td>\n";
|
||||||
|
form_action_buttons('task.php', $row['taskid']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
// Table summary
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="2">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button('task.php');
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Project'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="projname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="projname" name="projname">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="responsible" class="form-label"><?=_('Responsible')?></label>
|
||||||
|
<select name="responsible" class="form-control">
|
||||||
|
<?php
|
||||||
|
foreach ($opt_user as $k => $v) {
|
||||||
|
echo '<option value="', $k ,'">', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit[insert]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT projname, startdate, duration, responsible, remarks "
|
||||||
|
. "FROM project "
|
||||||
|
. "WHERE projid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$project = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
echo "<h2>", $project->projname, "</h2>\n";
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th scope="row" style="width:20%">', _('Name'),"</th><td>", $project->projname, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Responsible'),"</th><td>", $opt_user[$project->responsible], "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Start date'),"</th><td>", $project->startdate, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Duration'),"</th><td>", $project->duration, "</td></tr>\n";
|
||||||
|
echo '<tr><th scope="row">', _('Remarks'),"</th><td>", $project->remarks, "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
// assigned tasks
|
||||||
|
echo "<h2>", _('Assigned tasks'), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT taskid, taskname FROM task WHERE projid=? ORDER BY taskname";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
?>
|
||||||
|
<table class="table table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><?=_('Task')?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<?php foreach ($sth->fetchAll() as $row):?>
|
||||||
|
<tr>
|
||||||
|
<td><?=$row['taskname']?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</table>
|
||||||
|
<?php
|
||||||
|
form_add_button('task.php', $id, 'projid');
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit Project'), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT projname, responsible, startdate, duration, remarks "
|
||||||
|
. "FROM project "
|
||||||
|
. "WHERE projid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$project = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="projname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="projname" name="projname" value="<?=$project->projname ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="responsible" class="form-label"><?=_('Responsible')?></label>
|
||||||
|
<select name="responsible" class="form-control">
|
||||||
|
<?php
|
||||||
|
foreach ($opt_user as $k => $v) {
|
||||||
|
echo '<option value="', $k ,'"';
|
||||||
|
if ($project->responsible == $k) {
|
||||||
|
echo ' selected';
|
||||||
|
}
|
||||||
|
echo '>', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="startdate"><?=_('Startdate')?></label>
|
||||||
|
<input type="date" class="form-control" id="startdate" name="startdate" value="<?=$project->startdate ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="duration"><?=_('Duration, days')?></label>
|
||||||
|
<input type="number" class="form-control" id="duration" name="duration" min="1" value="<?=$project->duration ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$project->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit[update]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>?f=view&id=<?=$id?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete Project'), "</h2>\n";
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle=_('Provisions');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
$opt_storage = db_get_opt_storage($user->vid);
|
||||||
|
$opt_catgory = db_get_options(5);
|
||||||
|
$opt_unit = db_get_options(6);
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$p[':provname'] = gpc_get_string($_POST, 'provname');
|
||||||
|
$p[':number'] = gpc_get_int($_POST, 'number');
|
||||||
|
$p[':unit'] = gpc_get_int($_POST, 'unit');
|
||||||
|
$p[':storedate'] = gpc_get_string($_POST, 'storedate');
|
||||||
|
$p[':shelflife'] = gpc_get_string($_POST, 'shelflife');
|
||||||
|
$keys = array_keys($p);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':'); }, $keys));
|
||||||
|
$pnames = join(',', $keys);
|
||||||
|
$sth = $pdo->prepare("INSERT INTO provisions ($fields) VALUES ($pnames)");
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$id = $pdo->LastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$p[':provname'] = gpc_get_string($_POST, 'provname');
|
||||||
|
$p[':number'] = gpc_get_int($_POST, 'number');
|
||||||
|
$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');
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':') . '=' . $s; }, array_keys($p)));
|
||||||
|
$sth = $pdo->prepare("UPDATE provisions SET $fields WHERE provid=:provid");
|
||||||
|
$p[':provid'] = $id;
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// Security token needed!
|
||||||
|
if (gpc_get_string($_POST, 'token', 16) != $_SESSION['token']) {
|
||||||
|
$g_error->Add(_('Delete prohibited, invalid security token!'));
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_('Unknown function!'), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
echo "<h1>", $pagetitle, "</h1>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT provid, provname, number, unit, storedate, shelflife, "
|
||||||
|
. " DATEDIFF(shelflife, storedate) AS d0, DATEDIFF (CURDATE(), storedate) AS d1 "
|
||||||
|
. "FROM provisions "
|
||||||
|
. "ORDER BY provid";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>\n";
|
||||||
|
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 "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>". $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>\n";
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
// Table summary
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="6">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add provisions'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="provname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="provname" name="provname" required autofocus>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="number"><?=_('Number')?></label>
|
||||||
|
<input type="number" min="0" max="1000" class="form-control" id="number" name="number" value="1">
|
||||||
|
</div>
|
||||||
|
<?php form_create_select('unit', _('Unit'), $opt_unit); ?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="storedate"><?=_('Storedate')?></label>
|
||||||
|
<input type="date" class="form-control" id="storedate" name="storedate" value="<?php echo date('Y-m-d'); ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="shelflife"><?=_('Shelflife')?></label>
|
||||||
|
<input type="date" class="form-control" id="shelflife" name="shelflife">
|
||||||
|
</div>
|
||||||
|
<?php form_create_select('sid', _('Storage'), $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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT provname, number, unit, storedate, shelflife, sid "
|
||||||
|
. "FROM provisions "
|
||||||
|
. "WHERE provid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$prov = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
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>', _('Unit'),"</th><td>", $opt_unit[$prov->unit], "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Storedate'),"</th><td>", $prov->storedate, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Shelflife'),"</th><td>", $prov->shelflife, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Storage'),"</th><td>", $opt_storage[$prov->sid], "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT provname, number, unit, storedate, shelflife, sid "
|
||||||
|
. "FROM provisions "
|
||||||
|
. "WHERE provid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$prov = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit provision'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="provname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="provname" name="provname" value="<?=$prov->provname ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="number"><?=_('Number')?></label>
|
||||||
|
<input type="number" min="0" max="1000" class="form-control" id="number" name="number" value="<?=$prov->number ?>">
|
||||||
|
</div>
|
||||||
|
<?php form_create_select('unit', _('Unit'), $opt_unit, $prov->unit); ?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="storedate"><?=_('Storedate')?></label>
|
||||||
|
<input type="date" class="form-control" id="storedate" name="storedate" value="<?=$prov->storedate ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="shelflife"><?=_('Shelflife')?></label>
|
||||||
|
<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_edit_buttons($g_scriptname, $id);
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete provisions'), "</h2>\n";
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 122 KiB |
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Search');
|
||||||
|
|
||||||
|
$needle = gpc_get_string($_REQUEST, 'needle', 40);
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<p>Search will be implemented later.
|
||||||
|
This page is currently just a placeholder.</p>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<div>
|
||||||
|
<label for="needle">Suche nach:</label>
|
||||||
|
<input type="text" id="needle" name="needle" value="<?=$needle?>" autofocus>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" id="remarks" name="ck_remarks">
|
||||||
|
<label for="remarks">Bemerkungsfelder Berücksichtigen</label>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary" name="submit[search]"><?=_('Search')?></button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if (isset($needle)) {
|
||||||
|
$sqlneedle = '%'.$needle.'%';
|
||||||
|
}
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
@@ -0,0 +1,325 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Storage');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
$stype = db_get_options(3);
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$sname = gpc_get_string($_POST, 'sname');
|
||||||
|
$stype = gpc_get_int($_POST, 'stype');
|
||||||
|
$sql = "INSERT INTO storage "
|
||||||
|
. " (vid, sname, stype) "
|
||||||
|
. "VALUES "
|
||||||
|
. " (:vid, :sname, :stype)";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':vid', $user->vid, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':sname', $sname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':stype', $stype, PDO::PARAM_INT);
|
||||||
|
$sth->execute();
|
||||||
|
$id = $pdo->lastInsertId();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$sname = gpc_get_string($_POST, 'sname');
|
||||||
|
$x = gpc_get_int($_POST, 'x');
|
||||||
|
$y = gpc_get_int($_POST, 'y');
|
||||||
|
$z = gpc_get_int($_POST, 'z');
|
||||||
|
$remarks = gpc_get_string($_POST, 'remarks', 150);
|
||||||
|
$sql = "UPDATE storage "
|
||||||
|
. "SET sname=:sname,"
|
||||||
|
. " x=:x, y=:y, z=:z,"
|
||||||
|
. " remarks=:remarks "
|
||||||
|
. "WHERE sid=:sid";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->bindValue(':sid', $id, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':sname', $sname, PDO::PARAM_STR);
|
||||||
|
$sth->bindValue(':x', $x, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':y', $y, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':z', $z, PDO::PARAM_INT);
|
||||||
|
$sth->bindValue(':remarks', $remarks, PDO::PARAM_STR);
|
||||||
|
$sth->execute();
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete':
|
||||||
|
// 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']);
|
||||||
|
// check if storage is empty
|
||||||
|
// - no assigned boxes
|
||||||
|
$sth = $pdo->prepare("SELECT COUNT(*) FROM box WHERE sid=?");
|
||||||
|
$sth->execute([$id]);
|
||||||
|
if ($sth->fetchColumn() > 0) {
|
||||||
|
$g_error->Add(_('Delete failed, assigned boxes detected!'));
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// - no assigned equipment
|
||||||
|
$sth = $pdo->prepare("SELECT COUNT(*) FROM inventory WHERE boxtype='storage' AND sid=?");
|
||||||
|
$sth->execute([$id]);
|
||||||
|
if ($sth->fetchColumn() > 0) {
|
||||||
|
$g_error->Add(_('Delete failed, assigned equipment detected!'));
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$sth = $pdo->prepare("DELETE FROM storage WHERE sid=?");
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$g_message->Add(sprintf(_('Deleted storage no. %d'), $id));
|
||||||
|
$action = ACT_DEFAULT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_("Unknown function '%s'!"), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
echo '<h1>', $pagetitle, "</h1>\n";
|
||||||
|
|
||||||
|
// Storage
|
||||||
|
// stype from dropdown
|
||||||
|
$sql = "SELECT sid, sname, remarks "
|
||||||
|
. "FROM storage "
|
||||||
|
. "WHERE vid=? "
|
||||||
|
. "ORDER BY sid";
|
||||||
|
$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>" . _('Name') . "</th>";
|
||||||
|
echo "<th>" . _('Remarks') . "</th>";
|
||||||
|
echo "<th> </th>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>". $row['sname'] ."</td>\n";
|
||||||
|
echo "<td>". $row['remarks'] ."</td>\n";
|
||||||
|
form_action_buttons($g_scriptname, $row['sid']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="3">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button($g_scriptname);
|
||||||
|
|
||||||
|
// Boxes
|
||||||
|
echo "<h1>", _('Box'), "</h1>\n";
|
||||||
|
$sql = "SELECT boxid, sid, label, color, content, remarks "
|
||||||
|
. "FROM box "
|
||||||
|
. "ORDER BY label";
|
||||||
|
$sth = $pdo->query($sql);
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<th>" . _('Label') . "</th>";
|
||||||
|
echo "<th>" . _('Color') . "</th>";
|
||||||
|
echo "<th>" . _('Content') . "</th>";
|
||||||
|
echo "<td></td>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>". $row['label'] ."</td>\n";
|
||||||
|
echo '<td><span style="background-color:#', $row['color'],'">'. $row['color'] ."</span></td>\n";
|
||||||
|
echo "<td>". $row['content'] ."</td>\n";
|
||||||
|
form_action_buttons('box.php', $row['boxid']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
// Table summary
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="4">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_add_button('box.php');
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Storage'), "</h2>\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="sname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="sname" name="sname">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<select name="stype" class="form-control">
|
||||||
|
<?php
|
||||||
|
foreach ($stype as $k => $v) {
|
||||||
|
echo '<option value="', $k ,'">', $v, "</option>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit[insert]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$opt_unit = db_get_options(6);
|
||||||
|
$sql = "SELECT sid, sname, stype, capacity, capaunit, x, y, z, remarks "
|
||||||
|
. "FROM storage "
|
||||||
|
. "WHERE sid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$storage = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
echo '<h2>', $storage->sname, "</h2>\n";
|
||||||
|
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th style="width:20%">', _('Typ'),"</th><td>", $stype[$storage->stype], "</td></tr>\n";
|
||||||
|
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>', _('Remarks'),"</th><td>", $storage->remarks, "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
// Zugeordnete Kisten hier anzeigen
|
||||||
|
echo '<h3>', _('Boxes in storage'), "</h3>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT boxid, label, color FROM box WHERE sid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$res = $sth->fetchall();
|
||||||
|
if (count($res) > 0) {
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "$boxid $label $color";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '<p>', _('No boxes contained'), "</p>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<h3>', _('Provisions in storage'), "</h3>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT provid, provname, number, unit, storedate, shelflife FROM provisions WHERE sid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$res = $sth->fetchall();
|
||||||
|
if (count($res) > 0) {
|
||||||
|
echo '<table class="table table-sm">';
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>";
|
||||||
|
echo "<td>", $row['provname'], "</td>";
|
||||||
|
echo "<td>", $row['number'], ' ', $opt_unit[$row['unit']], "</td>";
|
||||||
|
echo "<td>", $row['storedate'], ' - ', $row['shelflife'], "</td>";
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "</table>\n";
|
||||||
|
} else {
|
||||||
|
echo '<p>', _('No provisions contained'), "</p>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit Storage'), "</h2>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT sid, sname, stype, remarks "
|
||||||
|
. "FROM storage "
|
||||||
|
. "WHERE sid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$storage = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post" action="<?=$g_scriptname?>">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="sname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="sname" name="sname" value="<?=$storage->sname ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="x" class="form-label"><?=_('Position x')?></label>
|
||||||
|
<input type="number" class="form-control" id="x" name="x" value="<?=$storage->x ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="y" class="form-label"><?=_('Position y')?></label>
|
||||||
|
<input type="number" class="form-control" id="y" name="y" value="<?=$storage->y ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="z" class="form-label"><?=_('Position z')?></label>
|
||||||
|
<input type="number" class="form-control" id="z" name="z" value="<?=$storage->z ?>">
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
|
||||||
|
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=$storage->remarks ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" name="submit[update]" class="btn btn-primary"><?=_('Save')?></button>
|
||||||
|
<a href="<?=$g_scriptname?>?f=view&id=<?=$id?>" class="btn btn-secondary"><?=_('Back')?></a>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
$_SESSION['token'] = bin2hex(random_bytes(8));
|
||||||
|
$sql = "SELECT sname, remarks FROM storage WHERE sid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$storage = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete Storage'), "</h2>\n";
|
||||||
|
|
||||||
|
echo '<p>', sprintf(_('Record no. %d'), $id), "</p>\n";
|
||||||
|
echo '<p>Name: ', $storage->sname, "</p>";
|
||||||
|
echo '<p>Remarks: ', $storage->remarks, "</p>";
|
||||||
|
|
||||||
|
echo '<p>', _('Deleting a storage is final. There is no way back. Only delete if you are absolute sure.'), "</p>\n";
|
||||||
|
|
||||||
|
form_delete_buttons($g_scriptname, $id, $_SESSION['token']);
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
+192
@@ -0,0 +1,192 @@
|
|||||||
|
<?php
|
||||||
|
/******************************************************************************
|
||||||
|
* YMS - Yacht Management Software
|
||||||
|
* Copyright (C) 2024 Thomas Hooge
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: WTFPL
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
require 'globals.inc';
|
||||||
|
$pagetitle = _('Task');
|
||||||
|
|
||||||
|
$id = gpc_get_int($_REQUEST, 'id', 0);
|
||||||
|
|
||||||
|
$opt_projects = db_get_opt_proj($user->vid, array(-1 => _('unassigned')));
|
||||||
|
|
||||||
|
// ========== ACTIONS START ===================================================
|
||||||
|
|
||||||
|
switch ($submit = form_get_action()) {
|
||||||
|
|
||||||
|
case NULL: break;
|
||||||
|
|
||||||
|
case 'add': $action = ACT_ADD; break;
|
||||||
|
case 'view': $action = ACT_VIEW; break;
|
||||||
|
case 'edit': $action = ACT_EDIT; break;
|
||||||
|
case 'del': $action = ACT_DELETE; break;
|
||||||
|
|
||||||
|
case 'insert':
|
||||||
|
$p[':projid'] = gpc_get_int($_POST, 'projid');
|
||||||
|
if ($p[':projid'] == -1) {
|
||||||
|
$p[':projid'] = NULL;
|
||||||
|
}
|
||||||
|
$p[':taskname'] = gpc_get_string($_POST, 'taskname');
|
||||||
|
$keys = array_keys($p);
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':'); }, $keys));
|
||||||
|
$pnames = join(',', $keys);
|
||||||
|
$sth = $pdo->prepare("INSERT INTO task ($fields) VALUES ($pnames)");
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'update':
|
||||||
|
$p[':taskname'] = gpc_get_string($_POST, 'taskname');
|
||||||
|
$p[':projid'] = gpc_get_int($_POST, 'projid');
|
||||||
|
if ($p[':projid'] == -1) {
|
||||||
|
$p[':projid'] = NULL;
|
||||||
|
}
|
||||||
|
$fields = join(',', array_map(function($s) { return ltrim($s, ':') . '=' . $s; }, array_keys($p)));
|
||||||
|
$sth = $pdo->prepare("UPDATE task SET $fields WHERE taskid=:taskid");
|
||||||
|
$p[':taskid'] = $id;
|
||||||
|
try {
|
||||||
|
$sth->execute($p);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$action = ACT_VIEW;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$g_error->Add(sprintf(_("Unknown function '%s'!"), $submit));
|
||||||
|
$valid = FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== ACTIONS END =====================================================
|
||||||
|
|
||||||
|
require 'header.php';
|
||||||
|
|
||||||
|
// ========== PAGE CONTENT ====================================================
|
||||||
|
|
||||||
|
if ($action == ACT_DEFAULT):
|
||||||
|
// ========== VARIANT: default behavior =======================================
|
||||||
|
|
||||||
|
echo "<h1>$pagetitle</h1>\n";
|
||||||
|
|
||||||
|
$sql = "SELECT t.taskid, t.projid, t.taskname, 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]);
|
||||||
|
} catch (PDOexception $e) {
|
||||||
|
$g_error->Add('SQL-Error: '. $e->getMessage());
|
||||||
|
}
|
||||||
|
$res = $sth->fetchAll();
|
||||||
|
|
||||||
|
echo '<table class="table table-striped">', "\n";
|
||||||
|
echo "<thead>\n";
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo '<th>#</th>';
|
||||||
|
echo '<th>', _('Task'), "</th>";
|
||||||
|
echo '<th>', _('Project'), "</th>";
|
||||||
|
echo "<th></th>";
|
||||||
|
echo "<th></th>\n";
|
||||||
|
echo "</tr>\n";
|
||||||
|
echo "</thead>\n";
|
||||||
|
foreach ($res as $row) {
|
||||||
|
echo "<tr>\n";
|
||||||
|
echo "<td>" . $row['taskid'] . "</td>\n";
|
||||||
|
echo "<td>" . $row['taskname'] . "</td>\n";
|
||||||
|
echo "<td>" . $row['projname'] . "</td>\n";
|
||||||
|
// Action buttons
|
||||||
|
form_action_buttons($g_scriptname, $row['taskid']);
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
// Table summary
|
||||||
|
echo "<tfoot>\n";
|
||||||
|
echo '<tr><td colspan="6">', sprintf(_('%d records'), count($res)), '</td></tr>', "\n";
|
||||||
|
echo "</tfoot>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_ADD):
|
||||||
|
// ========== VARIANT: add record =============================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Add Task'), "</h2>\n";
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<?php
|
||||||
|
// preselect project if parameter is set
|
||||||
|
$projid = gpc_get_int($_REQUEST, 'projid');
|
||||||
|
form_create_select('projid', _('Project'), $opt_projects, $projid);
|
||||||
|
?>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="taskname" class="form-label"><?=_('Task')?></label>
|
||||||
|
<input type="text" class="form-control" id="taskname" name="taskname" required autofocus>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
elseif ($action == ACT_VIEW):
|
||||||
|
// ========== VARIANT: view single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT t.taskname, p.projname "
|
||||||
|
. "FROM task AS t LEFT JOIN project AS p USING (projid) "
|
||||||
|
. "WHERE taskid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$task = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('View Task'), "</h2>\n";
|
||||||
|
echo '<table class="table">', "\n";
|
||||||
|
echo '<tr><th>', _('Task'),"</th><td>", $task->taskname, "</td></tr>\n";
|
||||||
|
echo '<tr><th>', _('Project'),"</th><td>", $task->projname ?? _('unassigned'), "</td></tr>\n";
|
||||||
|
echo "</table>\n";
|
||||||
|
|
||||||
|
form_view_buttons($g_scriptname, $id);
|
||||||
|
|
||||||
|
elseif ($action == ACT_EDIT):
|
||||||
|
// ========== VARIANT: edit single record =====================================
|
||||||
|
|
||||||
|
$sql = "SELECT taskname "
|
||||||
|
. "FROM task "
|
||||||
|
. "WHERE taskid=?";
|
||||||
|
$sth = $pdo->prepare($sql);
|
||||||
|
$sth->execute([$id]);
|
||||||
|
$task = $sth->fetch(PDO::FETCH_OBJ);
|
||||||
|
|
||||||
|
echo '<h2>', _('Edit Task'), "</h2>\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
<form method="post">
|
||||||
|
<input type="hidden" name="id" value="<?=$id?>">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="taskname" class="form-label"><?=_('Name')?></label>
|
||||||
|
<input type="text" class="form-control" id="taskname" name="taskname" value="<?=$task->taskname ?>">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
form_create_select('projid', _('Project'), $opt_projects);
|
||||||
|
form_edit_buttons($g_scriptname, $id);
|
||||||
|
echo "</form>\n";
|
||||||
|
|
||||||
|
elseif ($action == ACT_DELETE):
|
||||||
|
// ========== VARIANT: delete record ==========================================
|
||||||
|
|
||||||
|
echo '<h2>', _('Delete Task'), "</h2>\n";
|
||||||
|
|
||||||
|
else:
|
||||||
|
// ========== ERROR UNKNOWN VARIANT ===========================================
|
||||||
|
|
||||||
|
echo '<p>', _('Unknown function call: Please report to system development!'), "</p>\n";
|
||||||
|
|
||||||
|
endif; // $action == ...
|
||||||
|
// ========== END OF VARIANTS =================================================
|
||||||
|
|
||||||
|
include 'footer.php';
|
||||||
Reference in New Issue
Block a user