diff --git a/INSTALL b/INSTALL
index 930b82f..462719d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -15,6 +15,7 @@ Yacht Management Software (YMS) Installation
- Python GTK3
- python3-gi
- gir1.2-gtk-3.0
+ - gir-rsvg-2.0
1.3 Web GUI
- Webserver
@@ -69,7 +70,7 @@ Customize path and access rights to your needs
To grant access for the local gui the directory has to be writeable by a special
group (here as example 'yms'). The user which runs the local gui (here
'guiuser') has also to be a member of that group as well as the webserver user
-''www-data'.
+'www-data'.
groupadd yms
usermod -aG yms www-data
@@ -107,14 +108,20 @@ Configfile should be readable by webserver but not writeable.
Create a local database user with same name as your computer user and allow
database acces with current unix credentials:
mysql> CREATE USER 'ymsgui'@'localhost' IDENTIFIED VIA unix_socket;
+ mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON yms.* TO 'ymsgui'@'localhost';
+
+Copy ymsgui.py to /usr/local/bin
+Copy directory yms to /usr/local/share
Start ymsgui.py, default configuration file is automatically created
7. Start using YMS
Use webgui:
-Start your browser and login to YMS with the default username/password:
+Start your browser and login to YMS with the initial username/password:
captain/captain
Use local client:
Start ymsgui.py
+Change the password using the local GUI before normal use.
+
diff --git a/db/mariadb.sql b/db/mariadb.sql
index 129af98..4bbcb22 100644
--- a/db/mariadb.sql
+++ b/db/mariadb.sql
@@ -3,6 +3,12 @@
/* MariaDB Scheme
Version: 1 */
+/* TODO
+ - check all values if unsigned can be used or not
+ - implement foreign keys where possible
+ - rename provisions to provision(?)
+ */
+
/* User
userid is signed because nevative values are required for settings
The user table must not be writeable by the webgui user!
@@ -58,6 +64,28 @@ CREATE TABLE dropdown (
PRIMARY KEY (ddid, ddval)
) ENGINE=InnoDB;
+CREATE TABLE company (
+ compid smallint(6) NOT NULL AUTO_INCREMENT,
+ compname varchar(60) NOT NULL,
+ comptype tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
+ comptype2 tinyint(3) UNSIGNED DEFAULT NULL,
+ shortname varchar(20) DEFAULT NULL,
+ street varchar(40),
+ 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,
+ flags set('deleted','historic') DEFAULT NULL,
+ PRIMARY KEY (compid),
+ UNIQUE INDEX ix_compname (compname, comptype)
+) ENGINE=InnoDB;
+
CREATE TABLE vessel (
vid smallint(6) NOT NULL AUTO_INCREMENT,
vtype enum('mono','cat','tri') NOT NULL DEFAULT 'mono',
@@ -76,14 +104,16 @@ CREATE TABLE vessel (
shapefile varchar(40) DEFAULT NULL,
sid_default smallint(6) UNSIGNED DEFAULT NULL, -- default storage
remarks varchar(150) DEFAULT NULL,
- PRIMARY KEY (vid)
+ PRIMARY KEY (vid),
+ FOREIGN KEY fk_vessel_shipyard (shipyard)
+ REFERENCES company(compid)
) ENGINE=InnoDB;
CREATE TABLE storage (
sid smallint(6) UNSIGNED NOT NULL AUTO_INCREMENT,
vid smallint(6) NOT NULL DEFAULT 1,
sname varchar(40) NOT NULL,
- stype tinyint(3) NOT NULL DEFAULT 0,
+ stype tinyint(3) NOT NULL DEFAULT 0, -- ddid=3
capacity smallint(6) DEFAULT NULL,
capaunit enum('kg','l') DEFAULT NULL,
x smallint(6) UNSIGNED NOT NULL DEFAULT 0,
@@ -148,6 +178,16 @@ CREATE TABLE equipment (
PRIMARY KEY(eid)
) ENGINE=InnoDB;
+/*
+convert to
+sid SMALLINT UNSIGNED NULL,
+boxid SMALLINT UNSIGNED NULL,
+CHECK (
+ (sid IS NOT NULL AND boxid IS NULL)
+ OR
+ (sid IS NULL AND boxid IS NOT NULL)
+)
+*/
CREATE TABLE inventory (
invid int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
invname varchar(80) NOT NULL,
@@ -161,6 +201,7 @@ CREATE TABLE inventory (
purchdate date DEFAULT NULL,
invcond enum('unknown','excellent','good','fair','bad','repairable','defect') NOT NULL default 'unknown',
remarks varchar(150) DEFAULT NULL,
+ flags set('ordered','removed','deleted') DEFAULT NULL,
PRIMARY KEY (invid),
INDEX ix_invname (invname)
) ENGINE=InnoDB;
@@ -199,6 +240,7 @@ CREATE table fuse (
UNIQUE INDEX ix_fusenumber (vid, fnumber)
) ENGINE=InnoDB;
+-- change vals to decimal(12,4)?
CREATE TABLE measurement (
mid smallint(6) NOT NULL AUTO_INCREMENT,
mname varchar(80) NOT NULL,
@@ -226,8 +268,10 @@ CREATE TABLE provisions (
weight float(5,2) UNSIGNED DEFAULT NULL,
weight_net float(5,2) UNSIGNED DEFAULT NULL,
unit tinyint(3) DEFAULT NULL,
+ calories smallint(6) UNSIGNED DEFAULT NULL,
storedate date DEFAULT CURRENT_DATE,
shelflife date DEFAULT NULL,
+ price decimal(12,2) DEFAULT NULL,
remarks varchar(150) DEFAULT NULL,
PRIMARY KEY (provid)
) ENGINE=InnoDB;
@@ -259,38 +303,19 @@ CREATE TABLE docref (
drid int(10) NOT NULL AUTO_INCREMENT,
reftype enum('vessel','box','equipment','project','task','user','company') NOT NULL DEFAULT 'vessel',
docid smallint(6) NOT NULL,
- refid smallint(6) NOT NULL,
+ refid int(10) NOT NULL,
PRIMARY KEY (drid),
- UNIQUE INDEX ix_docref (docid, refid),
- FOREIGN KEY fx_docref_doc (docid)
+ UNIQUE INDEX ix_docref (docid, refid, reftype),
+ FOREIGN KEY fk_docref_doc (docid)
REFERENCES document (docid)
ON DELETE RESTRICT
ON UPDATE CASCADE
) ENGINE=InnoDB;
-CREATE TABLE company (
- compid smallint(6) NOT NULL AUTO_INCREMENT,
- compname varchar(60) NOT NULL,
- comptype tinyint(3) UNSIGNED NOT NULL DEFAULT 1,
- comptype2 tinyint(3) UNSIGNED DEFAULT NULL,
- shortname varchar(20) DEFAULT NULL,
- street varchar(40),
- 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,
- flags set('deleted','historic') DEFAULT NULL,
- PRIMARY KEY (compid),
- UNIQUE INDEX ix_compname (compname, comptype)
-) ENGINE=InnoDB;
-
-/* TODO optional field: plan date, target date, completion date */
+/* TODO optional fields: plan date, target date, completion date
+ interval_hours, last_hours
+ signalk: operating hours current vs maint every n operating hours in separate
+*/
CREATE TABLE maintenance (
maintid int(10) NOT NULL AUTO_INCREMENT,
vid smallint(6) NOT NULL DEFAULT 1,
@@ -332,14 +357,16 @@ CREATE TABLE task (
finished datetime DEFAULT NULL,
responsible smallint(6) NOT NULL,
/* TODO executed_by : company or user? or both? */
- PRIMARY KEY (taskid)
+ PRIMARY KEY (taskid),
+ FOREIGN KEY fk_task_user (responsible)
+ REFERENCES user(userid)
) ENGINE=InnoDB;
/* Notes can be assigned to tasks,maintenances and equipment */
CREATE TABLE note (
noteid int(10) NOT NULL AUTO_INCREMENT,
notetype enum('task','maint','equip') NOT NULL DEFAULT 'task',
- refid smallint(6) NOT NULL,
+ refid int(10) NOT NULL,
annotation text NOT NULL,
PRIMARY KEY (noteid)
) ENGINE=InnoDB;
@@ -372,3 +399,16 @@ CREATE TABLE checkgroup (
title varchar(30) NOT NULL,
PRIMARY KEY (groupid)
) ENGINE=InnoDB;
+
+/* Expansion for future use: signalk mapping (just an idea) */
+CREATE TABLE signalk (
+ skid int(10) NOT NULL AUTO_INCREMENT,
+ vid smallint(6) NOT NULL,
+ objtype enum('equipment','storage') NOT NULL,
+ objid int(10) NOT NULL,
+ datatype enum('engine_hours','tank_level') NOT NULL,
+ skpath varchar(255) NOT NULL,
+ PRIMARY KEY (skid),
+ UNIQUE KEY ix_signalk
+ (vid, objtype, objid, datatype)
+) ENGINE=InnoDB;
diff --git a/db/minimal.sql b/db/minimal.sql
index 0f020c5..80225f2 100644
--- a/db/minimal.sql
+++ b/db/minimal.sql
@@ -76,4 +76,5 @@ INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
(3, 0, 'Stauraum allgemein', 'fixed'),
-(3, 1, 'Tank', 'fixed');
+(3, 1, 'Tank', 'fixed'),
+(3, 2, 'Extern', 'fixed'); -- not on board
diff --git a/webgui/config.inc-sample b/webgui/config.inc-sample
index 5a8f172..3d19717 100644
--- a/webgui/config.inc-sample
+++ b/webgui/config.inc-sample
@@ -17,7 +17,7 @@ define('APP_ILLUSTRATION', 'sailboat.svg');
// database connection
$g_db_host = 'localhost';
-$g_db_username = 'yms';
+$g_db_username = 'ymsweb';
$g_db_password = 'changeme!';
$g_db_schema = 'yms';
diff --git a/webgui/css/choices.min.css b/webgui/css/choices.min.css
new file mode 100644
index 0000000..cf79ea9
--- /dev/null
+++ b/webgui/css/choices.min.css
@@ -0,0 +1 @@
+.choices{position:relative;overflow:hidden;margin-bottom:24px;font-size:16px}.choices:focus{outline:0}.choices:last-child{margin-bottom:0}.choices.is-open{overflow:visible}.choices.is-disabled .choices__inner,.choices.is-disabled .choices__input{background-color:#eaeaea;cursor:not-allowed;-webkit-user-select:none;user-select:none}.choices.is-disabled .choices__item{cursor:not-allowed}.choices [hidden]{display:none!important}.choices[data-type*=select-one]{cursor:pointer}.choices[data-type*=select-one] .choices__inner{padding-bottom:7.5px}.choices[data-type*=select-one] .choices__input{display:block;width:100%;padding:10px;border-bottom:1px solid #ddd;background-color:#fff;margin:0}.choices[data-type*=select-one] .choices__button{background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjMDAwIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);padding:0;background-size:8px;position:absolute;top:50%;right:0;margin-top:-10px;margin-right:25px;height:20px;width:20px;border-radius:10em;opacity:.25}.choices[data-type*=select-one] .choices__button:focus,.choices[data-type*=select-one] .choices__button:hover{opacity:1}.choices[data-type*=select-one] .choices__button:focus{box-shadow:0 0 0 2px #005f75}.choices[data-type*=select-one] .choices__item[data-placeholder] .choices__button{display:none}.choices[data-type*=select-one]::after{content:"";height:0;width:0;border-style:solid;border-color:#333 transparent transparent;border-width:5px;position:absolute;right:11.5px;top:50%;margin-top:-2.5px;pointer-events:none}.choices[data-type*=select-one].is-open::after{border-color:transparent transparent #333;margin-top:-7.5px}.choices[data-type*=select-one][dir=rtl]::after{left:11.5px;right:auto}.choices[data-type*=select-one][dir=rtl] .choices__button{right:auto;left:0;margin-left:25px;margin-right:0}.choices[data-type*=select-multiple] .choices__inner,.choices[data-type*=text] .choices__inner{cursor:text}.choices[data-type*=select-multiple] .choices__button,.choices[data-type*=text] .choices__button{position:relative;display:inline-block;margin:0-4px 0 8px;padding-left:16px;border-left:1px solid #003642;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjEiIHZpZXdCb3g9IjAgMCAyMSAyMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSIjRkZGIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxwYXRoIGQ9Ik0yLjU5Mi4wNDRsMTguMzY0IDE4LjM2NC0yLjU0OCAyLjU0OEwuMDQ0IDIuNTkyeiIvPjxwYXRoIGQ9Ik0wIDE4LjM2NEwxOC4zNjQgMGwyLjU0OCAyLjU0OEwyLjU0OCAyMC45MTJ6Ii8+PC9nPjwvc3ZnPg==);background-size:8px;width:8px;line-height:1;opacity:.75;border-radius:0}.choices[data-type*=select-multiple] .choices__button:focus,.choices[data-type*=select-multiple] .choices__button:hover,.choices[data-type*=text] .choices__button:focus,.choices[data-type*=text] .choices__button:hover{opacity:1}.choices__inner{display:inline-block;vertical-align:top;width:100%;background-color:#f9f9f9;padding:7.5px 7.5px 3.75px;border:1px solid #ddd;border-radius:2.5px;font-size:14px;min-height:44px;overflow:hidden}.is-focused .choices__inner,.is-open .choices__inner{border-color:#b7b7b7}.is-open .choices__inner{border-radius:2.5px 2.5px 0 0}.is-flipped.is-open .choices__inner{border-radius:0 0 2.5px 2.5px}.choices__list{margin:0;padding-left:0;list-style:none}.choices__list--single{display:inline-block;padding:4px 16px 4px 4px;width:100%}[dir=rtl] .choices__list--single{padding-right:4px;padding-left:16px}.choices__list--single .choices__item{width:100%}.choices__list--multiple{display:inline}.choices__list--multiple .choices__item{display:inline-block;vertical-align:middle;border-radius:20px;padding:4px 10px;font-size:12px;font-weight:500;margin-right:3.75px;margin-bottom:3.75px;background-color:#005f75;border:1px solid #004a5c;color:#fff;word-break:break-all;box-sizing:border-box}.choices__list--multiple .choices__item[data-deletable]{padding-right:5px}[dir=rtl] .choices__list--multiple .choices__item{margin-right:0;margin-left:3.75px}.choices__list--multiple .choices__item.is-highlighted{background-color:#004a5c;border:1px solid #003642}.is-disabled .choices__list--multiple .choices__item{background-color:#aaa;border:1px solid #919191}.choices__list--dropdown,.choices__list[aria-expanded]{display:none;z-index:1;position:absolute;width:100%;background-color:#fff;border:1px solid #ddd;top:100%;margin-top:-1px;border-bottom-left-radius:2.5px;border-bottom-right-radius:2.5px;overflow:hidden;word-break:break-all}.is-active.choices__list--dropdown,.is-active.choices__list[aria-expanded]{display:block}.is-open .choices__list--dropdown,.is-open .choices__list[aria-expanded]{border-color:#b7b7b7}.is-flipped .choices__list--dropdown,.is-flipped .choices__list[aria-expanded]{top:auto;bottom:100%;margin-top:0;margin-bottom:-1px;border-radius:.25rem .25rem 0 0}.choices__list--dropdown .choices__list,.choices__list[aria-expanded] .choices__list{position:relative;max-height:300px;overflow:auto;-webkit-overflow-scrolling:touch;will-change:scroll-position}.choices__list--dropdown .choices__item,.choices__list[aria-expanded] .choices__item{position:relative;padding:10px;font-size:14px}[dir=rtl] .choices__list--dropdown .choices__item,[dir=rtl] .choices__list[aria-expanded] .choices__item{text-align:right}@media (min-width:640px){.choices__list--dropdown .choices__item--selectable[data-select-text],.choices__list[aria-expanded] .choices__item--selectable[data-select-text]{padding-right:100px}.choices__list--dropdown .choices__item--selectable[data-select-text]::after,.choices__list[aria-expanded] .choices__item--selectable[data-select-text]::after{content:attr(data-select-text);font-size:12px;opacity:0;position:absolute;right:10px;top:50%;transform:translateY(-50%)}[dir=rtl] .choices__list--dropdown .choices__item--selectable[data-select-text],[dir=rtl] .choices__list[aria-expanded] .choices__item--selectable[data-select-text]{text-align:right;padding-left:100px;padding-right:10px}[dir=rtl] .choices__list--dropdown .choices__item--selectable[data-select-text]::after,[dir=rtl] .choices__list[aria-expanded] .choices__item--selectable[data-select-text]::after{right:auto;left:10px}}.choices__list--dropdown .choices__item--selectable.is-highlighted,.choices__list[aria-expanded] .choices__item--selectable.is-highlighted{background-color:#f2f2f2}.choices__list--dropdown .choices__item--selectable.is-highlighted::after,.choices__list[aria-expanded] .choices__item--selectable.is-highlighted::after{opacity:.5}.choices__item{cursor:default}.choices__item--selectable{cursor:pointer}.choices__item--disabled{cursor:not-allowed;-webkit-user-select:none;user-select:none;opacity:.5}.choices__heading{font-weight:600;font-size:12px;padding:10px;border-bottom:1px solid #f7f7f7;color:gray}.choices__button{text-indent:-9999px;appearance:none;border:0;background-color:transparent;background-repeat:no-repeat;background-position:center;cursor:pointer}.choices__button:focus,.choices__input:focus{outline:0}.choices__input{display:inline-block;vertical-align:baseline;background-color:#f9f9f9;font-size:14px;margin-bottom:5px;border:0;border-radius:0;max-width:100%;padding:4px 0 4px 2px}.choices__input::-webkit-search-cancel-button,.choices__input::-webkit-search-decoration,.choices__input::-webkit-search-results-button,.choices__input::-webkit-search-results-decoration{display:none}.choices__input::-ms-clear,.choices__input::-ms-reveal{display:none;width:0;height:0}[dir=rtl] .choices__input{padding-right:2px;padding-left:0}.choices__placeholder{opacity:.5}
\ No newline at end of file
diff --git a/webgui/documents.php b/webgui/documents.php
index 4eb8de2..da5583b 100644
--- a/webgui/documents.php
+++ b/webgui/documents.php
@@ -57,6 +57,7 @@ switch ($submit = form_get_action()) {
// WIP New standalone document
// debug $g_message->Add(print_r($_FILES, true));
// check for possible errors
+ // TODO use "noscale" option for images
if (!isset($_FILES['files']['error']) || is_array($_FILES['files']['error'])) {
$g_error->Add(_("Invalid file upload parameters."));
$action = ACT_ADD;
@@ -434,7 +435,7 @@ echo '
', _('Add Document'), "
\n";
-
+
+
'--- none ---'] + $opt_ecat, $flt->cat);
+form_create_select('category', _('Category'), $g_opt_none + $opt_ecat, $flt->cat);
form_create_select('manufacturer', _('Manufacturer'), $opt_manufacturer, $flt->manuf);
?>
diff --git a/webgui/globals.inc b/webgui/globals.inc
index 5d98c32..4400403 100644
--- a/webgui/globals.inc
+++ b/webgui/globals.inc
@@ -904,7 +904,8 @@ function db_get_opt_user($userid, $default=NULL) {
return $list;
}
-function db_get_opt_proj($vid, $default=NULL) {
+function db_get_opt_proj($vid, $exclude=[], $default=NULL) {
+ // exclude is a list of project states
global $pdo;
global $g_error;
if (isset($default)) {
@@ -912,7 +913,15 @@ function db_get_opt_proj($vid, $default=NULL) {
} else {
$list = array();
}
- $sql = "SELECT projid, projname FROM project WHERE vid=? ORDER BY projname";
+ $sql = "SELECT projid, projname FROM project WHERE vid=?";
+ $where = [];
+ foreach ($exclude as $excl) {
+ $where[] = "NOT FIND_IN_SET('$excl',projstate)";
+ }
+ if (! empty($where)) {
+ $sql .= ' AND '. implode(' AND ', $where);
+ }
+ $sql .= " ORDER BY projname";
$sth = $pdo->prepare($sql);
try {
$sth->execute([$vid]);
@@ -1047,6 +1056,18 @@ function form_create_text($fieldname, $label, $value) {
echo "
\n";
}
+function form_create_check($fieldname, $label, $checked) {
+ // create single checkbox with assigned label
+ echo '', "\n";
+ echo '\n";
+ echo '\n";
+ echo "
\n";
+}
+
function form_create_select($fieldname, $label, $optlist, $selval=NULL, $multiple=FALSE) {
echo '', "\n";
echo '
\n";
@@ -1063,6 +1084,7 @@ function form_create_select($fieldname, $label, $optlist, $selval=NULL, $multipl
}
function form_create_checks($fieldname, $label, $optlist, $selected = []) {
+ // create multiple combined checkboxes with title
echo '