diff options
| author | Geo Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2026-07-12 15:51:52 +0300 |
|---|---|---|
| committer | Geo Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2026-07-12 15:51:52 +0300 |
| commit | 02608271bb2a9f3a65ed536984d306ee14b48e34 (patch) | |
| tree | 3f23ec48a694ec014e845c4f70d9b5f1c065403c /public/ui-edit-item.php | |
| download | kalassa-02608271bb2a9f3a65ed536984d306ee14b48e34.tar.gz kalassa-02608271bb2a9f3a65ed536984d306ee14b48e34.tar.bz2 kalassa-02608271bb2a9f3a65ed536984d306ee14b48e34.zip | |
Diffstat (limited to 'public/ui-edit-item.php')
| -rw-r--r-- | public/ui-edit-item.php | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/public/ui-edit-item.php b/public/ui-edit-item.php new file mode 100644 index 0000000..df2ee1f --- /dev/null +++ b/public/ui-edit-item.php @@ -0,0 +1,629 @@ +<?php +// 00. INITIALIZATION ---------------------------------------------------------- +// * Load Parametres, Session and Functions; +// * Check User Permitions +// * Check Script Call +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + include("config/parametres.php"); + include("includes/sessions.php"); + include("includes/functions.php"); + + // if visitor has no ROLE -or- if ADMIN : then redirect to Login|Panel + // --------------------------------------------------------------------------- + if (!ROLE || (ROLE == ADMIN)) { + header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); + header("Location: /"); + die(); + } + + // if item ID not passed redirec to to Control-Panel (or login) + // --------------------------------------------------------------------------- + if (isset($_GET['id'])) $item_id = $_GET['id']; + else { + $pi_Error = array('url' => '/', 'msg' => ERR_NEED_ID); + // include ("includes/show-error.php"); + } + + +// 01. GET DATA NEEDED --------------------------------------------------------- +// * Load Parametres, Session and Functions; +// * Check User Permitions +// * Check Script Call +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + // get totals of categories + // --------------------------------------------------------------------------- + $totals = get_totals(); + + // read fields options (json format) + // --------------------------------------------------------------------------- + $formARRAY = json_decode(FORMJSON); + + // get item record + // --------------------------------------------------------------------------- + // init database connection + $_dbc = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DBMS); + if ($_dbc->connect_errno) { + echo "Database connection failed; Please try in a few minutes. "; + if (TESTING) echo $_dbc->connect_error; + $_dbc->close(); die(); + } + $_dbc->set_charset("utf8"); + + // prepare statemet + $_stm = $_dbc->prepare("SELECT identity, operator, `timestamp`, record FROM items WHERE id = ?"); + $_stm->bind_param("d", $item_id); // bind values + $_stm->execute(); // execute query + $_stm->store_result(); // store result + + if ($_stm->num_rows) { + + $_stm->bind_result($idnt, $opr, $tm, $serREC); // bind result variables + $_stm->fetch(); // fetch FIRST record values + // unserialize main record to variable + $record = unserialize($serREC); + + // edit record + $record['id'] = $item_id; + $record['identity'] = $idnt; + $record['operator'] = $opr; + $record['itemid'] = end(explode('.', $idnt)); + $record['totalitems'] = $totals[$record['ccode']]; + date_default_timezone_set('Europe/Athens'); + setlocale(LC_ALL, 'el_GR.UTF-8', 'grc'); + $record['timestamp'] = local_dt($tm); + } + else { + return array('success' => false, 'data' => "No items found"); // return error(s) + } + + $_stm->close(); // close statement + $_dbc->close(); // close connection + + +// 02. RENDER HTML and DATA ---------------------------------------------------- +// * Draw fileds from Json Array per section +// * Prepare JS needed +// * Put data from Record +// * Generate JS (prepared + static) +// --- +// Script is based on on ui-new-item.php +// More information about the script workflow can be found there. +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + // Init strigns for JS generator (needed to handle everything) /////////////// + // --------------------------------------------------------------------------- + $checkFilledJS = ""; // JS for checking empty fields + $ref2Select2JS = ""; // references to Select2-controls Javascript + $initSelectsJS = ""; // js to initialize select fields (single or multiple) + // --- depricated (added static into js) : $addJSreadonly = ""; // js to add readonly fields and their values to port-object + +?><!DOCTYPE html> +<html prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB" dir="ltr"> + <head> + <!-- Metas + Title --> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + + <title><?=PROJECT?> : Επεξεργασία Εγγραφής <?=$idnt?></title> + + <!-- CSS needed --> + <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,700&display=swap" rel="stylesheet"> + <link rel="stylesheet" href="/css/bootstrap.min.css" /><!-- v4.4.1 --> + <link rel="stylesheet" href="/css/select2.min.css" /><!-- v4.0.10 --> + <link rel="stylesheet" href="/css/pi.css" /> + </head> + <body> + + <?php // Menu ---------------------------------------------------------------- + include("includes/menu.php"); + ?> + + +<div class="pi-container"> +<h2>Επεξεργασία Εγγραφής <?=$idnt?></h2> + +<form id="post-form" method="POST"> + + <!-- TABS (start) --> + <div id="tabsContainer"> + <div class="tabArea"> + +<?php $i = 1; ?> +<?php foreach ($formARRAY as $key => $section) : ?> + <!-- START fields group (section) ////////////////////////////////////////// --> + + <input id="tab<?=$i?>" type="radio" name="tabs" value="<?=$i?>"<?=($i == 1) ? ' checked' : ''?>> + <label for="tab<?=$i?>"><?=$section->label?></label> + <div id="content<?=$i?>" class="tab--content"> + <div class="form-row"> + + + <?php foreach ($section->childs as $kk => $field) : ?> + <?php + + // get atributes of field + $atrs = explode('|', $field->atr); // attributes array + $ak = in_array('append-key', $atrs) ? true : false; // append key (for selects) + $rq = in_array('required', $atrs) ? 'required' : ''; // required + $class = (isset($field->len)) ? ' col-md-'.$field->len : 'col-md-12'; // column class (for width) + + ?> + + <!-- form group --> + <div class="form-group <?=$class?>"> + <label for="<?=$field->nam?>"> + <?=$field->lab?> + <?php if (($field->typ == 'select') && C_LABEL) : ?> + <span><?=$field->nam?></span> + <?php endif; ?> + </label> + + <?php + + switch ($field->typ) { + + case 'select': + + // exclude CCODE from default select behaviour + // because CCODE SHALL NOT CHANGE + if ($field->nam == 'ccode') { + + $fdata = parse_any($field->nam, $record['ccode']); // parse field + current value + + $txt = $fdata['multi'] ? implode(", ", $fdata['value']) : $fdata['value']; // if array of values, implode values + + echo '<input class="form-control" type="text" name="ccode" value="'. $txt .'" readonly>'; + + $checkFilledJS .= " + values.ccode = '". $record['ccode'] ."'; + "; + + } + else { + + // if MULTIPLE select + // ( deferantiate class for multi or single this will allow the { allowClear: true } option ) + // ( see: https://select2.org/placeholders ) + if (in_array('multiple', $atrs)) { + // MULTIPLE control: set name and multiple attribute + $name_n_multi = 'name="'. $field->nam .'[]" multiple="multiple">'; + + // prepare initialization of select2 (multiple) + $initSelectsJS .= " + var ". $field->nam ." = $('#". $field->nam ."'); + ". $field->nam .".select2({ width: '100%' }); + "; // depricated: ". $field->nam .".select2({ placeholder: '". $field->lab ."', width: '100%' }); + + // and set init value + if ($record[$field->nam] !="") { + $initSelectsJS .= " + ". $field->nam .".val( ['". str_replace(",", "','", $record[$field->nam]) ."'] ); + ". $field->nam .".trigger('change'); + "; + } + + // prepare check if empty field + $checkFilledJS .= " + if (getValues(".$field->nam.") =='') { + empty += '<span>". $section->label .":</span> ". $field->lab . (($rq == '') ? "" : " **") ."<br />'; + ". (($rq == '') ? "" : "needit.push('". $section->label .":". $field->lab ."');") ." + } + values.". $field->nam ." = getValues(".$field->nam."); + "; + } + else { + // is SINGLE control: only name needed + $name_n_multi = 'name="'. $field->nam .'"'; + + // prepare initialization of select2 (single) + $initSelectsJS .= " + var ". $field->nam ." = $('#". $field->nam ."'); + ". $field->nam .".select2({ placeholder: ' ', allowClear: true }); + "; // depricated: ". $field->nam .".select2({ placeholder: '". $field->lab ."', allowClear: true }); + + // and set init value + if ($record[$field->nam] !="") { + $initSelectsJS .= " + ". $field->nam .".val( ['". str_replace(",", "','", $record[$field->nam]) ."'] ); + ". $field->nam .".trigger('change'); + "; + } + + // prepare check if empty field + $checkFilledJS .= " + if (getValues(".$field->nam.") =='') { + empty += '<span>". $section->label .":</span> ". $field->lab . (($rq == '') ? "" : " **") ."<br />'; + ". (($rq == '') ? "" : "needit.push('". $section->label .":". $field->lab ."');") ." + } + values.". $field->nam ." = getValues(".$field->nam."); + "; + } + ?> + <select id="<?=$field->nam?>" class="select-field" <?=$name_n_multi?> style="width:100%;"> + + <?php if (!in_array('multiple', $atrs)) : ?> + <option></option> + <?php endif; ?> + <?php foreach ($field->opt as $kkk => $val): ?> + <option value="<?=$val->id?>"><?=(($ak) ? $val->id.' : ' : '' ) .$val->tag?></option> + <?php endforeach; ?> + </select> + <?php + } + break; + + case 'text': + $checkFilledJS .= " + if ($('input[name=". $field->nam ."]').val() =='') { + empty += '<span>". $section->label .":</span> ". $field->lab . (($rq == '') ? "" : " **") ."<br />'; + ". (($rq == '') ? "" : "needit.push('". $section->label .":". $field->lab ."');") ." + } + values.". $field->nam ." = $('input[name=". $field->nam ."]').val(); + "; + ?> + <input class="form-control" type="text" name="<?=$field->nam?>" value="<?=$record[$field->nam]?>" <?=$rq?>> + <?php break; + + case 'integer': + $checkFilledJS .= " + if ($('input[name=". $field->nam ."]').val() =='') { + empty += '<span>". $section->label .":</span> ". $field->lab . (($rq == '') ? "" : " **") ."<br />'; + ". (($rq == '') ? "" : "needit.push('". $section->label .":". $field->lab ."');") ." + } + values.". $field->nam ." = $('input[name=". $field->nam ."]').val(); + "; + ?> + <input class="form-control" type="number" name="<?=$field->nam?>" value="<?=$record[$field->nam]?>" min="0" step="1" <?=$rq?>> + <?php break; + + case 'float': + // credit: https://stackoverflow.com/questions/19011861/is-there-a-float-input-type-in-html5 + $checkFilledJS .= " + if ($('input[name=". $field->nam ."]').val() =='') { + empty += '<span>". $section->label .":</span> ". $field->lab . (($rq == '') ? "" : " **") ."<br />'; + ". (($rq == '') ? "" : "needit.push('". $section->label .":". $field->lab ."');") ." + } + values.". $field->nam ." = $('input[name=". $field->nam ."]').val(); + "; + ?> + <input class="form-control" type="number" name="<?=$field->nam?>" value="<?=$record[$field->nam]?>" min="0" step="0.1" <?=$rq?>> + <?php break; + + case 'textarea': + $checkFilledJS .= " + if ($('textarea[name=". $field->nam ."]').val() =='') { + empty += '<span>". $section->label .":</span> ". $field->lab . (($rq == '') ? "" : " **") ."<br />'; + ". (($rq == '') ? "" : "needit.push('". $section->label .":". $field->lab ."');") ." + } + values.". $field->nam ." = $('textarea[name=". $field->nam ."]').val(); + "; + ?> + <textarea class="form-control" name="<?=$field->nam?>" <?=$rq?>><?=$record[$field->nam]?></textarea> + <?php break; + + case 'auto': + // On EDIT mode the 'auto' fields have already their (read-only) value + ?> + <input class="form-control" type="text" name="<?=$field->nam?>" value="<?=$record[$field->nam]?>" readonly> + <?php break; + + default: ?> + <?=$field->nam?> (<?=$field->lab?>) : UNKNOWN TYPE + + <?php + } // end switch + + unset($atrs); // free array to re-use (on next field) + ?> + </div> + <!-- end /form group --> + + <?php endforeach; ?> + + </div><!-- /form-row --> + </div><!-- /tab-.-content --> + <?php $i++; ?> + + <!-- END fields group (section) --> +<?php endforeach; ?> + + + </div> + </div> + <!-- TABS (end) --> + + <!-- footer of form --> + + <div class="row"> + + <div class="col-md-4 line-right"> + <h3>Δεν έχουν συμπληρωθεί:</h3> + <div id="empty-fields"></div> + </div> + + <div class="col-md-8"> + + <!-- custom field --> + <div class="form-group"> + <label for="more">Συμπληρωματική Πληροφορία</label> + <?php + $fdata = parse_any($field->nam, $record['note']); // parse field + current value + $txt = $fdata['value']; // if array of values, implode values + ?> + <textarea name="note" class="form-control tall"><?=$txt?></textarea> + <?php + // append js code + // for checking if field is empty + // and attaching value to json data + $checkFilledJS .= " + if ($('textarea[name=note]').val() =='') { + empty += '<span>Γενικά:</span>Συμπληρωματική Πληροφορία<br />'; + } + values.note = $('textarea[name=note]').val(); + "; + ?> + </div> + + <div class="form-group"> + <input class="btn btn-primary" type="submit" value="Καταχώρηση Εγγραφής"> + </div> + </div> + + </div> + +</form> +</div> +<!-- DOM ENDS HERE --> + + <!-- scripts and libraries + load and register one by one, so you don't need to worry about if they are ready --> +<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-migrate/1.4.1/jquery-migrate.min.js"></script> +<script src="/js/bootstrap.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.full.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/i18n/el.js"></script> +<script> +// NOW RUN EVERYTHING AFTER JQUERY (AND DOM ready) +// ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// + + // 00. FLAGS and NEEDED FUNCTIONS + // --------------------------------------------------------------------------- + ////////////////////////////////////////////////////////////////////////////// + + var waitingResponse = false; // flag for an ajax request that was sent and still waiting response + + // pure JS ajax GET request + // return data as JSON + // no fancy things like UTF8; if needed use base64 --------------------------- + function ajax_get(url, callback) { + var xmlhttp = new XMLHttpRequest(); + xmlhttp.onreadystatechange = function() { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + + try { + var data = JSON.parse(xmlhttp.responseText); + } catch(err) { + console.log(err.message + " in " + xmlhttp.responseText); + return; + } + callback(data); + } + }; + + xmlhttp.open("GET", url, true); + xmlhttp.send(); + } + + + // 01. MENU MANAGEMENT + // --------------------------------------------------------------------------- + ////////////////////////////////////////////////////////////////////////////// + + // menu management + // --------------------------------------------------------------------------- + $('.dropdown-item').on('click', function(e){ + e.preventDefault(); + + if (!waitingResponse) { + waitingResponse = true; + + var r = confirm("Δεν έχετε αποθηκεύσει το τρέχον αντικείμενο!\nΕίστε σίγουροι ότι θέλετε να εγκαταλείψετε τη σελίδα;"); + if (r == true) { + + // all data-goto have the format: 'method,uri_address' + // uri_address is the url to call + // method options: + // * url : means goto url (redirect) + // * ajax : means call url via ajax; if 'success = true' then goto '/' after that + // ----------------------------------------------------------------------- + var opt = $(this).data('goto').split(','); // split data-goto + + if (opt[0] == 'url') { // if method = url + window.location.href = opt[1]; + } + else { // else, method = ajax + ajax_get(opt[1], function(response) { + if (response.success) { + window.location.href = '/'; + } + }); + } + + } + else { + // user did not confirmed the selection; do nothing + } + + waitingResponse = false; + } + + }); + + // 02. USER INTERFACE + // --------------------------------------------------------------------------- + ////////////////////////////////////////////////////////////////////////////// + + // tabs to accorderon -------------------------------------------------------- + ////////////////////////////////////////////////////////////////////////////// + + // FUNCTION: Set tabsContainer height + // acording to which tab is visible + // and tab mode (tabs|acordeon) + // --------------------------------------------------------------------------- + function set_tabsContainer_height() { + var ch_; // content height + var tc_base; // tabs-container base height + tc_base = ($(window).width() > 650) ? 100 : 400; + if ($('#content1').is(':visible')) ch_ = $('#content1').height(); + if ($('#content2').is(':visible')) ch_ = $('#content2').height(); + if ($('#content3').is(':visible')) ch_ = $('#content3').height(); + if ($('#content4').is(':visible')) ch_ = $('#content4').height(); + if ($('#content5').is(':visible')) ch_ = $('#content5').height(); + if ($('#content6').is(':visible')) ch_ = $('#content6').height(); + + $('#tabsContainer').height(ch_ + tc_base); + + } + set_tabsContainer_height(); // init (run for 1st time) + + // on tab selection + // calculate tabsContainer height + $('input:radio[name="tabs"]').change( function(){ + set_tabsContainer_height() + }); + + // on window change + // set tabsContainer height + $( window ).resize(function() { + set_tabsContainer_height(); + }); + + + + // 03. FORM-CONTROLS + // --------------------------------------------------------------------------- + ////////////////////////////////////////////////////////////////////////////// + + // Select2 controls + ////////////////////////////////////////////////////////////////////////////// + + // FUNCTION: Get selected value(s) of Select2 control + // pass arg: source-element + // return: value(s) comma-separated + // --------------------------------------------------------------------------- + function getValues(srcElm) { + var res; + var obj = srcElm.select2('data'); // get delected data array + + if (obj.length === 0) return ''; // if empty list then nothig is selected + else { + var i = 0; + obj.forEach(function(elm){ // loop through object elements array + + if (i) res += ',' + elm.id; // if not first item, prepend ',' befor value(id) + else res = elm.id; // else set (first) checked value + + i++; + }); + } + return res; + } + + // patch select2-multiple widths + // --------------------------------------------------------------------------- + $('.select-field').select2({ width: '100%' }); + + // init select2 fields + // (embed from php) + // --------------------------------------------------------------------------- + <?=$initSelectsJS?> + + + // 04. FORM-LOGIC + // --------------------------------------------------------------------------- + ////////////////////////////////////////////////////////////////////////////// + + // FUNCTION: Report empty fields + // --------------------------------------------------------------------------- + function reportEmpty() { + var empty = ''; + var needit = []; + var values = {}; + + // embed if-conditions from php + <?=$checkFilledJS?> + + $("#empty-fields").html(empty); // render empty fields + + // console.log(JSON.stringify(values)); + + return { need : needit, data: values }; // return all fields + } + reportEmpty(); + + $('form').on('keyup change paste', 'input, select, textarea', function(){ + console.log('Form changed!'); + reportEmpty(); + }); + + // validation? + // check: https://www.sitepoint.com/instant-validation/ + + + $('#post-form').on('submit', function(e){ + e.preventDefault(); + if (!waitingResponse) { + waitingResponse = true; + var resp = reportEmpty(); + + // add static (readonly) data to resp.data object + resp.data.id = <?=$item_id?>; + resp.data.identity = '<?=$idnt?>'; + + if (resp.need.length > 0) alert("Tα πεδία:\n\n" + resp.need.join(',\n') + "\n\nείναι υποχρεωτικά!"); + else { + // alert('sending: '+JSON.stringify(resp.data)); + + var postUrl = "/ajax.php?do=upditem&id=<?=$item_id?>"; // url to post form + var data2send = resp.data; // parse data to send + + $.ajax({ + type: 'POST', + url: postUrl, // make sure you respect the same origin policy with this url + data: data2send, + dataType: "text", + + success: function(data) { // server replies + var json = $.parseJSON(data); + if (json.success == true) { // good! post accepted + // alert(json.id) + window.location.href = '/ui-show-item.php?id=<?=$item_id?>' + } + else { + alert("Post not accepted.\nPlease check the data you submit."); + } + }, + + error: function() { + alert('Some ajax error! :('); + } + }); + + } + + waitingResponse = false; + } + + }); +</script> + </body> +</html> |
