Webgui programming
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
YMS - Yacht Management System
|
||||
Prototype
|
||||
|
||||
Many features are incomplete, buggy or missing.
|
||||
Use at your own risk!
|
||||
|
||||
+4
-1
@@ -217,6 +217,7 @@ CREATE TABLE company (
|
||||
compid smallint(6) NOT NULL AUTO_INCREMENT,
|
||||
compname varchar(60) NOT NULL,
|
||||
comptype tinyint(3) NOT NULL DEFAULT 1,
|
||||
comptype2 tinyint(3) DEFAULT NULL,
|
||||
shortname varchar(20) DEFAULT NULL,
|
||||
street varchar(30),
|
||||
zip varchar(10),
|
||||
@@ -258,7 +259,7 @@ CREATE TABLE project (
|
||||
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',
|
||||
projstate enum('new','plan','ongoing','paused','finished') NOT NULL DEFAULT 'new',
|
||||
PRIMARY KEY (projid)
|
||||
);
|
||||
|
||||
@@ -273,6 +274,8 @@ CREATE TABLE task (
|
||||
duedate date DEFAULT NULL,
|
||||
started datetime DEFAULT NULL,
|
||||
finished datetime DEFAULT NULL,
|
||||
responsible smallint(6) NOT NULL,
|
||||
/* TODO executed_by : company or user? or both? */
|
||||
PRIMARY KEY (taskid)
|
||||
);
|
||||
|
||||
|
||||
+1
-1
@@ -6,4 +6,4 @@ mv /var/www/html/config.inc-sample /var/www/html/config.inc
|
||||
chmod 640 /var/www/html/config.inc
|
||||
chgrp www-data /var/www/html/config.inc
|
||||
rm /var/www/html/index.html
|
||||
rm /var/www/html/locale/dc_DE.po
|
||||
rm /var/www/html/locale/de_DE.po
|
||||
|
||||
+20
-3
@@ -43,6 +43,7 @@ switch ($submit = form_get_action()) {
|
||||
$p[':compname'] = gpc_get_string($_POST, 'compname');
|
||||
$p[':shortname'] = gpc_get_string($_POST, 'shortname', 20);
|
||||
$p[':comptype'] = gpc_get_int($_POST, 'comptype');
|
||||
$p[':comptype2'] = gpc_get_int($_POST, 'comptype2');
|
||||
$p[':street'] = gpc_get_string($_POST, 'street', 30);
|
||||
$p[':zip'] = gpc_get_string($_POST, 'zip', 10);
|
||||
$p[':city'] = gpc_get_string($_POST, 'city', 30);
|
||||
@@ -228,8 +229,8 @@ echo '<h2>', _('Add Company'), "</h2>\n";
|
||||
elseif ($action == ACT_VIEW):
|
||||
// ========== VARIANT: view single record =====================================
|
||||
|
||||
$sql = "SELECT compname, comptype, shortname, street, zip, city, country,"
|
||||
. " contact, phone, email, web, customerno, contractno, remarks "
|
||||
$sql = "SELECT compname, comptype, comptype2, shortname, street, zip, city,"
|
||||
. " country, contact, phone, email, web, customerno, contractno, remarks "
|
||||
. "FROM company "
|
||||
. "WHERE compid=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
@@ -242,6 +243,7 @@ echo '<table class="table">', "\n";
|
||||
echo '<tr><th scope="row" style="width:20%">', _('Name'),"</th><td>", $company->compname, "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Short name'),"</th><td>", $company->shortname, "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Type'),"</th><td>", $opt_comptype[$company->comptype], "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Secondary type'),"</th><td>", $company->comptype2 ? $opt_comptype[$company->comptype2] : '-', "</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";
|
||||
@@ -299,7 +301,7 @@ elseif ($action == ACT_EDIT):
|
||||
|
||||
echo '<h2>', _('Edit Company'), "</h2>\n";
|
||||
|
||||
$sql = "SELECT compname, comptype, street, zip, city, country,"
|
||||
$sql = "SELECT compname, comptype, comptype2, street, zip, city, country,"
|
||||
. " contact, phone, email, web, customerno, contractno, remarks "
|
||||
. "FROM company "
|
||||
. "WHERE compid=?";
|
||||
@@ -332,6 +334,21 @@ foreach ($opt_comptype as $k => $v) {
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="comptype2" class="form-label"><?=_('Secondary company type')?></label>
|
||||
<select name="comptype2" class="form-control">
|
||||
<?php
|
||||
echo '<option value="">--- kein ---', "</option>\n";
|
||||
foreach ($opt_comptype as $k => $v) {
|
||||
echo '<option value="', $k ,'"';
|
||||
if ($company->comptype2 == $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 ?>">
|
||||
|
||||
@@ -35,6 +35,13 @@ $g_shapedir = 'shapes';
|
||||
// documents and images
|
||||
$g_doc_basepath = '/var/local/yms';
|
||||
$g_doc_maxsize = 1024*1024*16; // 16 MB
|
||||
$g_doc_typemap = array(
|
||||
'generic' => 'doc',
|
||||
'manual' => 'doc',
|
||||
'invoice' => 'doc',
|
||||
'picture' => 'pic',
|
||||
'drawing' => 'drw'
|
||||
);
|
||||
|
||||
$g_storage_limit = 1024; // MB
|
||||
|
||||
|
||||
+12
-1
@@ -42,6 +42,17 @@ switch ($submit = form_get_action()) {
|
||||
case 'insert':
|
||||
// WIP New standalone document
|
||||
// debug $g_message->Add(print_r($_FILES, true));
|
||||
// check for possible errors
|
||||
if (!isset($_FILES['files']['error']) || is_array($_FILES['files']['error'])) {
|
||||
$g_error->Add(_("Invalid file upload parameters."));
|
||||
$action = ACT_ADD;
|
||||
break;
|
||||
}
|
||||
if (($_FILES['files']['error'] == UPLOAD_ERR_INI_SIZE) || ($_FILES['files']['error'] == UPLOAD_ERR_FORM_SIZE)) {
|
||||
$g_error->Add(_("Exceeded filesize limit."));
|
||||
$action = ACT_ADD;
|
||||
break;
|
||||
}
|
||||
if (empty($_FILES['files']['tmp_name']) ) {
|
||||
$g_warning->Add(_('No file for upload submitted. Try again by selecting a file first.'));
|
||||
$action = ACT_ADD;
|
||||
@@ -117,7 +128,7 @@ switch ($submit = form_get_action()) {
|
||||
$p[':doctype'] = gpc_get_string($_POST, 'doctype');
|
||||
$p[':filename'] = gpc_get_string($_POST, 'filename');
|
||||
$p[':title'] = gpc_get_string($_POST, 'title', 40);
|
||||
$p['remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||
db_exec_update('document', $p, 'docid');
|
||||
$action = ACT_VIEW;
|
||||
break;
|
||||
|
||||
+261
-51
@@ -50,9 +50,9 @@ 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');
|
||||
bindtextdomain($g_textdomain, 'locale');
|
||||
bind_textdomain_codeset($g_textdomain, 'UTF-8');
|
||||
textdomain($g_textdomain);
|
||||
|
||||
date_default_timezone_set($g_timezone);
|
||||
|
||||
@@ -63,12 +63,18 @@ if ($g_scriptname != 'login.php') {
|
||||
$_SESSION['prelogin'] = $_SERVER['REQUEST_URI'];
|
||||
header_location('login.php');
|
||||
}
|
||||
$g_referrer = $_SESSION['coming_from'];
|
||||
$g_referrer = $_SESSION['coming_from'] ?? $g_scriptname;
|
||||
$_SESSION['coming_from'] = $g_scriptname;
|
||||
}
|
||||
|
||||
// database
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$g_db_host;dbname=$g_db_schema;charset=utf8mb4", $g_db_username, $g_db_password);
|
||||
} catch (PDOException $e) {
|
||||
echo '<pre>';
|
||||
print_r($e);
|
||||
echo '</pre>';
|
||||
}
|
||||
$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'");
|
||||
@@ -87,6 +93,10 @@ $valid = FALSE;
|
||||
// document storage
|
||||
$g_doc_mimetypes = ['image/png', 'image/jpeg', 'image/svg+xml', 'application/pdf'];
|
||||
|
||||
// form option lists
|
||||
$g_opt_all = array(-2 => _('― all ―'));
|
||||
$g_opt_none = array(-1 => _('― none ―'));
|
||||
|
||||
// Initialize message system
|
||||
$g_message = new Message;
|
||||
$g_success = new MessageSuccess;
|
||||
@@ -105,6 +115,10 @@ class Message {
|
||||
function __construct() {
|
||||
$this->caption = _('Information');
|
||||
$this->alertclass = 'alert-info';
|
||||
if (isset($_SESSION['message']['info'])) {
|
||||
$this->Add($_SESSION['message']['info']);
|
||||
unset($_SESSION['message']['info']);
|
||||
}
|
||||
}
|
||||
|
||||
function SetCaption($str) {
|
||||
@@ -140,6 +154,10 @@ class MessageSuccess extends Message {
|
||||
function __construct() {
|
||||
$this->caption = _('Success');
|
||||
$this->alertclass = 'alert-success';
|
||||
if (isset($_SESSION['message']['succ'])) {
|
||||
$this->Add($_SESSION['message']['succ']);
|
||||
unset($_SESSION['message']['succ']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +165,10 @@ class MessageWarning extends Message {
|
||||
function __construct() {
|
||||
$this->caption = _('Warning');
|
||||
$this->alertclass = 'alert-warning';
|
||||
if (isset($_SESSION['message']['warn'])) {
|
||||
$this->Add($_SESSION['message']['warn']);
|
||||
unset($_SESSION['message']['warn']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +176,10 @@ class MessageError extends Message {
|
||||
function __construct() {
|
||||
$this->caption = _('Error');
|
||||
$this->alertclass = 'alert-danger';
|
||||
if (isset($_SESSION['message']['err'])) {
|
||||
$this->Add($_SESSION['message']['err']);
|
||||
unset($_SESSION['message']['err']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +235,9 @@ class User {
|
||||
// password check successful
|
||||
$_SESSION['userid'] = $row->userid;
|
||||
$this->loggedin = TRUE;
|
||||
header_location($_SESSION['prelogin'] ?? 'index.php');
|
||||
$target = $_SESSION['prelogin'] ?? 'index.php';
|
||||
unset($_SESSION['prelogin']);
|
||||
header_location($target);
|
||||
} else {
|
||||
$this->errormessage = _('Username or password invalid');
|
||||
}
|
||||
@@ -344,13 +372,17 @@ function db_save_filter($flt, $sno) {
|
||||
}
|
||||
|
||||
function get_enum($enum) {
|
||||
// Translate and beautify enums
|
||||
// translate and beautify enums
|
||||
$lookup = array(
|
||||
'NULL' => _('n/a'),
|
||||
'bad' => _('Bad'),
|
||||
'box' => _('Box'),
|
||||
'cat' => _('Catamaran'),
|
||||
'completed' => _('Completed'),
|
||||
'closed' => _('Closed'),
|
||||
'company' => _('Company'),
|
||||
'defect' => _('Defect'),
|
||||
'deleted' => _('Deleted'),
|
||||
'done' => _('Done'),
|
||||
'drawing' => _('Drawing'),
|
||||
'equipment' => _('Equipment'),
|
||||
@@ -364,40 +396,52 @@ function get_enum($enum) {
|
||||
'locked' => _('Locked'),
|
||||
'low' => _('Low'),
|
||||
'manual' => _('Manual'),
|
||||
'mediim' => _('Medium'),
|
||||
'medium' => _('Medium'),
|
||||
'mono' => _('Monohull'),
|
||||
'new' => _('New'),
|
||||
'none' => _('None'),
|
||||
'normal' => _('Normal'),
|
||||
'ongoing' => _('Ongoing'),
|
||||
'open' => _('Open'),
|
||||
'paused' => _('Paused'),
|
||||
'pending' => _('Pending'),
|
||||
'picture' => _('Picture'),
|
||||
'planned' => _('Planned'),
|
||||
'precise' => _('Precise'),
|
||||
'project' => _('Project'),
|
||||
'repairable' => _('Repairable'),
|
||||
'rough' => _('Rough'),
|
||||
'storage' => _('Storage'),
|
||||
'task' => _('Task'),
|
||||
'tri' => _('Trimaran'),
|
||||
'unknown' => _('Unknown'),
|
||||
'user' => _('User'),
|
||||
'vessel' => _('Vessel'),
|
||||
'waiting' => _('waiting')
|
||||
);
|
||||
return $lookup[$enum] ?? $enum;
|
||||
}
|
||||
|
||||
function db_load_enum($table, $column, $lookup=false, $as_dict=false) {
|
||||
function db_load_enum($table, $column, $lookup=false, $as_dict=false, $check_null=false) {
|
||||
// returns array of enum-values as defined in database
|
||||
// if lookup is true the name lookup and translaton is applied
|
||||
// if as_dict is true the enum value is returned as the array key
|
||||
// if check_null is true the nullable-check is applied and returned
|
||||
global $pdo;
|
||||
$sql = "SELECT TRIM(TRAILING ')' FROM SUBSTRING(column_type,6)) "
|
||||
$sql = "SELECT TRIM(TRAILING ')' FROM SUBSTRING(column_type,6)), is_nullable "
|
||||
. "FROM information_schema.columns "
|
||||
. "WHERE table_name=? AND column_name=?";
|
||||
. "WHERE table_schema=DATABASE() AND table_name=? AND column_name=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute([$table, $column]);
|
||||
$row = $sth->fetch(PDO::FETCH_NUM);
|
||||
// for PHP < 7.4
|
||||
// return array_map(function($x) { return trim($x, "'"); }, explode(',', $sth->fetchColumn()));
|
||||
// return array_map(function($x) { return trim($x, "'"); }, explode(',', $row[0]));
|
||||
// for PHP => 7.4
|
||||
$arr = array_map(fn($x) => trim($x, "'"), explode(',', $sth->fetchColumn()));
|
||||
$arr = array_map(fn($x) => trim($x, "'"), explode(',', $row[0]));
|
||||
// prepend special value NULL if column is nullable
|
||||
if ($check_null and $row[1] == 'YES') {
|
||||
array_unshift($arr, 'NULL');
|
||||
}
|
||||
if ($lookup) {
|
||||
if ($as_dict) {
|
||||
$dict = array();
|
||||
@@ -413,6 +457,98 @@ function db_load_enum($table, $column, $lookup=false, $as_dict=false) {
|
||||
}
|
||||
}
|
||||
|
||||
function db_load_taglist($objtype, $objid) {
|
||||
// returns comma separated list for object
|
||||
global $pdo;
|
||||
global $g_error;
|
||||
$taglist = '';
|
||||
$sql = "SELECT GROUP_CONCAT(tagname) "
|
||||
. "FROM tagref JOIN tag USING (tagid) "
|
||||
. "WHERE objtype=? AND objid=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
try {
|
||||
$sth->execute([$objtype, $objid]);
|
||||
$taglist = $sth->fetchColumn();
|
||||
} catch(PDOException $e) {
|
||||
$g_error->Add($e->getMessage());
|
||||
}
|
||||
return $taglist;
|
||||
}
|
||||
|
||||
function db_save_taglist($objtype, $objid, $taglist) {
|
||||
global $pdo;
|
||||
global $g_error;
|
||||
// WIP
|
||||
// - taglist is comma separated string
|
||||
// - create not existing tags
|
||||
// - update tagref: create new, remove unused
|
||||
$tags = array_filter(explode(',', preg_replace('/\s+/u', '', $taglist)));
|
||||
if (empty($tags)) {
|
||||
// remove all from tagref
|
||||
$sth = $pdo->prepare("DELETE FROM tagref WHERE objtype=? AND objid=?");
|
||||
try {
|
||||
$sth->execute([$objtype, $objid]);
|
||||
} catch(PDOException $e) {
|
||||
$g_error->Add($e->getMessage());
|
||||
}
|
||||
} else {
|
||||
// get list of non existing tags
|
||||
$in = str_repeat('?,', count($tags) - 1) . '?';
|
||||
$sql = "SELECT tagid, tagname FROM tag WHERE tagname IN ($in)";
|
||||
$sth = $pdo->prepare($sql);
|
||||
try {
|
||||
$sth->execute(array_values($tags));
|
||||
} catch(PDOException $e) {
|
||||
$g_error->Add($e->getMessage());
|
||||
}
|
||||
$tagids = array();
|
||||
$existing = array();
|
||||
foreach ($sth->fetchAll() as $row) {
|
||||
$existing[] = $row['tagname'];
|
||||
$tagids[] = $row['tagid'];
|
||||
}
|
||||
$newtags = array_diff($tags, $existing);
|
||||
$sth = $pdo->prepare("INSERT INTO tag (tagname) VALUES (?)");
|
||||
foreach ($newtags as $t) {
|
||||
// maxlength 20 for each tag!
|
||||
$sth->execute([substr($t, 0, 20)]);
|
||||
$tagids[] = $pdo->LastInsertId();
|
||||
}
|
||||
// update references
|
||||
$sql = "SELECT tagid FROM tagref WHERE objtype=? AND objid=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute([$objtype, $objid]);
|
||||
$refids = array();
|
||||
$obsolete = array();
|
||||
foreach ($sth->fetchAll() as $row) {
|
||||
if (in_array($row['tagid'], $tagids)) {
|
||||
// mark existing used references
|
||||
$refids[] = $row['tagid'];
|
||||
} else {
|
||||
// obsolete reference
|
||||
$obsolete[] = $row['tagid'];
|
||||
}
|
||||
}
|
||||
// create missing references
|
||||
$missing = array_diff($tagids, $refids);
|
||||
if (! empty($missing)) {
|
||||
$sql = "INSERT INTO tagref (tagid, objid, objtype) VALUES (?, ?, ?)";
|
||||
$sth = $pdo->prepare($sql);
|
||||
foreach ($missing as $m) {
|
||||
$sth->execute([$m, $objid, $objtype]);
|
||||
}
|
||||
}
|
||||
// remove obsolete references
|
||||
if (! empty($obsolete)) {
|
||||
$sql = "DELETE FROM tagref WHERE tagid=? AND objid=? and objtype=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
foreach ($obsolete as $o) {
|
||||
$sth->execute([$o, $objid, $objtype]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function db_get_ddtext($ddid, $ddval) {
|
||||
// returns single value for dropdown
|
||||
global $pdo;
|
||||
@@ -428,6 +564,8 @@ function db_get_ddtext($ddid, $ddval) {
|
||||
return $sth->fetchColumn();
|
||||
}
|
||||
|
||||
// Functions to get option lists (key/value)
|
||||
|
||||
function db_get_options($ddid, $orderby = '', $default = NULL) {
|
||||
// returns list for dropdown
|
||||
global $pdo;
|
||||
@@ -461,7 +599,6 @@ function db_get_opt_vessel() {
|
||||
return $list;
|
||||
}
|
||||
|
||||
// Functions to get option lists (key/value)
|
||||
|
||||
function db_get_opt_storage($vid) {
|
||||
global $pdo;
|
||||
@@ -619,10 +756,31 @@ function float_to_sql($var) {
|
||||
|
||||
// ========== FORM FUNCTIONS ==================================================
|
||||
|
||||
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 form_create_select($fieldname, $label, $optlist, $selval=NULL) {
|
||||
echo '<div class="mb-3">', "\n";
|
||||
echo '<label for="', $fieldname, '">', $label, "</label>\n";
|
||||
echo '<select class="form-select" name="', $fieldname,'" id="', $fieldname,'">';
|
||||
echo '<select class="form-select" name="', $fieldname,'" id="', $fieldname, '">', "\n";
|
||||
foreach ($optlist as $k => $v) {
|
||||
echo '<option value="', $k, '"';
|
||||
if (isset($selval) and ($k == $selval)) {
|
||||
@@ -686,60 +844,40 @@ function form_delete_buttons($script, $id, $token) {
|
||||
echo "</div>\n";
|
||||
}
|
||||
|
||||
function form_tag_assignment($script, $id) {
|
||||
function form_tag_assignment($script, $id, $tags) {
|
||||
echo '<tr>';
|
||||
echo '<th>', _('Tags'), "</th>\n";
|
||||
echo '<td>', $tags, '</td>';
|
||||
echo "</tr>\n<tr>";
|
||||
echo '<th>', _('Tag assignment'), "</th>\n";
|
||||
echo '<td><form method="post" action="', $script, '">', "\n";
|
||||
echo '<div class="form-floating">';
|
||||
echo '<input type="hidden" name="id" value="', $id .'">', "\n";
|
||||
echo '<label>', _('(Separate by comma)'), '</label>', "\n";
|
||||
echo '<input type="text" maxlength="80" class="form-control" name="tagstring">', "\n";
|
||||
echo '<input type="text" maxlength="80" class="form-control" name="tagstring" value="', $tags, '">', "\n";
|
||||
echo '<input type="submit">', "\n";
|
||||
echo "</div></form></td></td>\n";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
// ========== COMMON FUNCTIONS ================================================
|
||||
|
||||
function header_location($location) {
|
||||
header("Location: $location");
|
||||
exit;
|
||||
function filter_create_select($fieldname, $label, $optlist, $selval=NULL) {
|
||||
echo '<label for="', $fieldname,'">', $label,'</label>', "\n";
|
||||
echo '<select id="', $fieldname, '" name="', $fieldname, '">', "\n";
|
||||
foreach ($optlist as $k => $v) {
|
||||
echo '<option value="', $k, '"';
|
||||
if ($k == $selval) {
|
||||
echo ' selected';
|
||||
}
|
||||
echo '>', $v, '</option>', "\n";
|
||||
}
|
||||
echo "</select>\n";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// ========== GPC FUNCTIONS ===================================================
|
||||
|
||||
function gpc_get_string(&$GPC, $varname, $maxlen = NULL, $default = NULL) {
|
||||
// TODO Parameter nullval: single value or array of values which considered as null
|
||||
// Default value for nullval is "-1"
|
||||
if (!isset($GPC[$varname]) or (strlen(trim($GPC[$varname])) == 0)) {
|
||||
return $default;
|
||||
}
|
||||
@@ -799,6 +937,15 @@ function gpc_get_bool(&$GPC, $varname, $default = FALSE) {
|
||||
}
|
||||
|
||||
function gpc_get_date(&$GPC, $varname, $default = NULL) {
|
||||
// TODO improve
|
||||
if (!isset($GPC[$varname]) || $GPC[$varname] == '') {
|
||||
return $default;
|
||||
}
|
||||
return $GPC[$varname];
|
||||
}
|
||||
|
||||
function gpc_get_datetime(&$GPC, $varname, $default = NULL) {
|
||||
// TODO improve
|
||||
if (!isset($GPC[$varname]) || $GPC[$varname] == '') {
|
||||
return $default;
|
||||
}
|
||||
@@ -829,6 +976,8 @@ function gpc_get_enum(&$GPC, $varname, $values, $default = NULL) {
|
||||
return $GPC[$varname];
|
||||
}
|
||||
|
||||
// ========== FORMAT FUNCTIONS ================================================
|
||||
|
||||
function format_float($val, $decimals = 2, $suffix = '') {
|
||||
global $g_lconv;
|
||||
if (!isset($val) || $val == '') {
|
||||
@@ -910,6 +1059,67 @@ function format_measurement($n, $unit, $v1, $v2, $v3) {
|
||||
return $m;
|
||||
}
|
||||
|
||||
// ========== COMMON FUNCTIONS ================================================
|
||||
|
||||
function header_location($location, $message=NULL) {
|
||||
if (is_array($message)) {
|
||||
$valid_keys = array('succ', 'info', 'warn', 'err');
|
||||
foreach ($message as $k => $v) {
|
||||
if (in_array($k, $valid_keys)) {
|
||||
$_SESSION['message'][$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
header("Location: $location");
|
||||
exit;
|
||||
}
|
||||
|
||||
function pgettext($context, $msgid) {
|
||||
// implement missing function
|
||||
global $g_textdomain;
|
||||
$ctxstr = "{$context}\004{$msgid}";
|
||||
$translation = dcgettext($g_textdomain, $ctxstr, LC_MESSAGES);
|
||||
if ($translation == $ctxstr) {
|
||||
return $msgid;
|
||||
} else {
|
||||
return $translation;
|
||||
}
|
||||
}
|
||||
|
||||
function get_color_brightness($color, $default=0.5) {
|
||||
// returns a value between 0 and 1
|
||||
// color is a 6 char hex string
|
||||
if (strlen($color) != 6) {
|
||||
return $default;
|
||||
}
|
||||
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 page_caption_search($caption) {
|
||||
// print page caption with searchbox
|
||||
?>
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<h1><?=$caption?></h1>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<form class="form-inline" method="post" action="search.php">
|
||||
<div class="input-group input-group-sm">
|
||||
<input name="needle" type="search" class="form-control" placeholder="<?=_('Search')?>">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-sm btn-primary" type="submit"><i class="bi bi-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
function get_pagination($script, $param, $page, $lastpage, $small=false) {
|
||||
// no direct output, returns string for multiple output
|
||||
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
<link href="bootstrap/bootstrap-icons.min.css" rel="stylesheet">
|
||||
<script src="bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
<link rel="stylesheet" href="default.css">
|
||||
<?php
|
||||
if (isset($GLOBALS['local_script'])) {
|
||||
echo '<script type="text/javascript">', "\n";
|
||||
echo $GLOBALS['local_script'];
|
||||
echo "</script>\n";
|
||||
}
|
||||
?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-xxl">
|
||||
|
||||
+10
-1
@@ -138,6 +138,14 @@ $sql = "SELECT vesselname, model, loa, lwl, beam, draught, draught_min,"
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute([$vid]);
|
||||
$vessel = $sth->fetch(PDO::FETCH_OBJ);
|
||||
|
||||
// Show remarks first
|
||||
if (strlen($vessel->remarks) > 0) {
|
||||
echo "<p>";
|
||||
echo $vessel->remarks;
|
||||
echo "</p>\n";
|
||||
}
|
||||
|
||||
// get vessel shape
|
||||
// test for predefined base shape
|
||||
$shapefilepath = dirname(__FILE__).'/'.$g_shapedir.'/'.$vessel->shapefile;
|
||||
@@ -146,7 +154,8 @@ if (isset($vessel->shapefile) and file_exists($shapefilepath)) {
|
||||
} else {
|
||||
// use internal default shape
|
||||
$baseshape = <<<EOT
|
||||
<svg version="1.1" width="1024" height="350" viewBox="0 0 1024 350" id="svg1">
|
||||
<svg version="1.1" width="1024" height="350" viewBox="0 0 1024 350" id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="g1">
|
||||
<path id="path1" style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:8, 4, 2, 4;stroke-dashoffset:0;stroke-opacity:1" d="M 3.3e-6,174.91172 1023.9982,174.90837" />
|
||||
<path id="path2" style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" d="m 1.1002728,174.9708 c 0,0 0.150828,-90.157538 0.02448,-103.853791 C 66.951611,46.573152 247.6267,3.4573666 430.56326,3.8276086 670.30694,4.3128215 758.66035,44.913257 838.18466,74.965511 917.70898,105.01776 1022.8821,175.00227 1022.8821,175.00227" />
|
||||
|
||||
+16
-27
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/******************************************************************************
|
||||
* YMS - Yacht Management Software
|
||||
* Copyright (C) 2024 Thomas Hooge
|
||||
* Copyright (C) 2024-2025 Thomas Hooge
|
||||
*
|
||||
* SPDX-License-Identifier: WTFPL
|
||||
******************************************************************************/
|
||||
@@ -17,6 +17,7 @@ $opt_user = array();
|
||||
foreach ($sth->fetchAll() as $row) {
|
||||
$opt_user[$row['userid']] = $row['displayname'];
|
||||
}
|
||||
$opt_state = db_load_enum('project', 'projstate', true, true);
|
||||
|
||||
// ========== ACTIONS START ===================================================
|
||||
|
||||
@@ -37,11 +38,11 @@ switch ($submit = form_get_action()) {
|
||||
break;
|
||||
|
||||
case 'insert':
|
||||
$p['vid'] = $user->id;
|
||||
$p[':vid'] = $user->vid;
|
||||
$p[':projname'] = gpc_get_string($_POST, 'projname');
|
||||
$p[':responsible'] = gpc_get_int($_POST, 'responsible');
|
||||
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||
$id = db_exec_insert('company', $p);
|
||||
$id = db_exec_insert('project', $p);
|
||||
$action = ACT_VIEW;
|
||||
break;
|
||||
|
||||
@@ -50,6 +51,7 @@ switch ($submit = form_get_action()) {
|
||||
$p[':projname'] = gpc_get_string($_POST, 'projname');
|
||||
$p[':startdate'] = gpc_get_date($_POST, 'startdate');
|
||||
$p[':duration'] = gpc_get_int($_POST, 'duration');
|
||||
$p[':projstate'] = gpc_get_string($_POST, 'projstate');
|
||||
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
|
||||
db_exec_update('project', $p, 'projid');
|
||||
$action = ACT_VIEW;
|
||||
@@ -121,9 +123,10 @@ 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 "
|
||||
. "WHERE vid=? AND projid IS NULL "
|
||||
. "ORDER BY taskid";
|
||||
$sth = $pdo->query($sql);
|
||||
$sth = $pdo->prepare($sql);
|
||||
$sth->execute([$user->vid]);
|
||||
$res = $sth->fetchAll();
|
||||
echo '<table class="table table-striped">', "\n";
|
||||
echo "<thead>\n";
|
||||
@@ -156,16 +159,9 @@ echo '<h2>', _('Add Project'), "</h2>\n";
|
||||
<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";
|
||||
}
|
||||
form_create_select('responsible', _('Responsible'), $opt_user, $project->responsible);
|
||||
?>
|
||||
</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>
|
||||
@@ -178,7 +174,7 @@ foreach ($opt_user as $k => $v) {
|
||||
elseif ($action == ACT_VIEW):
|
||||
// ========== VARIANT: view single record =====================================
|
||||
|
||||
$sql = "SELECT projname, startdate, duration, responsible, remarks "
|
||||
$sql = "SELECT projname, startdate, duration, responsible, projstate, remarks "
|
||||
. "FROM project "
|
||||
. "WHERE projid=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
@@ -190,6 +186,7 @@ echo '<tr><th scope="row" style="width:20%">', _('Name'),"</th><td>", $project->
|
||||
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">', _('State'),"</th><td>", $project->projstate, "</td></tr>\n";
|
||||
echo '<tr><th scope="row">', _('Remarks'),"</th><td>", $project->remarks, "</td></tr>\n";
|
||||
echo "</table>\n";
|
||||
|
||||
@@ -223,7 +220,7 @@ elseif ($action == ACT_EDIT):
|
||||
|
||||
echo '<h2>', _('Edit Project'), "</h2>\n";
|
||||
|
||||
$sql = "SELECT projname, responsible, startdate, duration, remarks "
|
||||
$sql = "SELECT projname, responsible, startdate, duration, projstate, remarks "
|
||||
. "FROM project "
|
||||
. "WHERE projid=?";
|
||||
$sth = $pdo->prepare($sql);
|
||||
@@ -237,20 +234,9 @@ $project = $sth->fetch(PDO::FETCH_OBJ);
|
||||
<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";
|
||||
}
|
||||
form_create_select('responsible', _('Responsible'), $opt_user, $project->responsible);
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="startdate"><?=_('Startdate')?></label>
|
||||
<input type="date" class="form-control" id="startdate" name="startdate" value="<?=$project->startdate ?>">
|
||||
@@ -259,6 +245,9 @@ foreach ($opt_user as $k => $v) {
|
||||
<label for="duration"><?=_('Duration, days')?></label>
|
||||
<input type="number" class="form-control" id="duration" name="duration" min="1" value="<?=$project->duration ?>">
|
||||
</div>
|
||||
<?php
|
||||
form_create_select('projstate', _('Status'), $opt_state, $project->projstate);
|
||||
?>
|
||||
<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>
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
/******************************************************************************
|
||||
* YMS - Yacht Management Software
|
||||
* Copyright (C) 2024 Thomas Hooge
|
||||
* Copyright (C) 2024-2025 Thomas Hooge
|
||||
*
|
||||
* SPDX-License-Identifier: WTFPL
|
||||
******************************************************************************/
|
||||
|
||||
Reference in New Issue
Block a user