summaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
authorGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-04-28 02:22:41 +0300
committerGeorge Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2023-04-28 02:22:41 +0300
commit6655db3dcf117cfd921a7b39600545c51e035b31 (patch)
tree087d573360d10b198e46b54a1b5513870d4ca5b1 /public
parenta2e68fce808dbe6fba320a6232a15380b63157f6 (diff)
downloadgyraf1gov-6655db3dcf117cfd921a7b39600545c51e035b31.tar.gz
gyraf1gov-6655db3dcf117cfd921a7b39600545c51e035b31.tar.bz2
gyraf1gov-6655db3dcf117cfd921a7b39600545c51e035b31.zip
brainstorming and first bytes of code
Diffstat (limited to 'public')
-rw-r--r--public/app/controllers/JsonToForm.php685
-rw-r--r--public/app/models/_info.md254
2 files changed, 794 insertions, 145 deletions
diff --git a/public/app/controllers/JsonToForm.php b/public/app/controllers/JsonToForm.php
new file mode 100644
index 0000000..9e305ce
--- /dev/null
+++ b/public/app/controllers/JsonToForm.php
@@ -0,0 +1,685 @@
+<?php
+
+class JsonToForm
+{
+ /**
+ * ## Help Constants and Functions ------------------------------------------------
+ * ////////////////////////////////////////////////////////////////////////////////
+ *
+ * // Cache fields options (json format) ////////////////////////////////////////
+ * // ---------------------------------------------------------------------------
+ * $formJSON = file_get_contents('config/kallassa.json');
+ * define("FORMJSON", $formJSON);
+ *
+ * // Cache CCODE attributes (json format) //////////////////////////////////////
+ * // ---------------------------------------------------------------------------
+ * $codeJSON = file_get_contents('config/ccode.json');
+ * define("CODEJSON", $codeJSON);
+ *
+ * // Parse anythig from a field ////////////////////////////////////////////////
+ * // ARGS:
+ * // $fkey = keyname (as in json fields oprions)
+ * // $inp = input value (string)
+ * // RETURN: array(
+ * // 'label' = field label,
+ * // 'multi' = (true|false) is multiple choice (select|radio|check) or not,
+ * // 'value' = human readable value (or array of values if multi)
+ * // ) -------------------------------------------------------------------------
+ */
+ public static function parse_any($fkey, $inp ="")
+ {
+ $formARRAY = json_decode(FORMJSON);
+
+ foreach ($formARRAY as $key => $section) {
+ foreach ($section->childs as $kk => $field) {
+
+ // find the field
+ if ($field->nam == $fkey) {
+
+ $values = array(); // human readble values if select (comma separated)
+
+ if ($field->typ == 'select') {
+ $multi = true;
+
+ if ($inp !='') {
+ $codes = explode(",", $inp); // split coded values
+ foreach ($field->opt as $kkk => $v) {
+ if (in_array($v->id, $codes)) { // check if option is in array
+ $values[] = ($field->nam == 'ccode') ? ($v->id.": ".$v->tag) : $v->tag;
+ }
+ }
+ }
+
+ }
+ else $multi = false;
+
+ // return everything in an array
+ return array(
+ 'label' => $field->lab,
+ 'multi' => $multi,
+ 'value' => ($multi ? $values : $inp)
+ );
+ }
+ }
+ }
+
+ // if not escaped already, then name return same
+ return array('label' => $fkey, 'multi' => false, 'value' => $inp );
+ }
+
+
+
+ // Parse anythig from ccode
+ public static function parse_ccode($ckey) {
+ $ccARRAY = json_decode(CODEJSON);
+
+ foreach ($ccARRAY as $key => $val) {
+ // find the field
+ if ($val->id == $ckey) {
+ // return everything in an array
+ return $val;
+ }
+ }
+ }
+
+
+ // Get totals of alla categories /////////////////////////////////////////////
+ // RETURN array of items (value) per category (array key)
+ // ---------------------------------------------------------------------------
+ public static function get_totals() {
+ $result = array();
+ $sum = 0;
+
+ $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 ccode, count(id) total FROM `items` GROUP BY ccode");
+ $stm->execute(); // execute query
+ $stm->store_result(); // store result
+ $stm->bind_result($c, $tot);
+ while ($stm->fetch()) {
+ // using md5() you can have any unicode string as key ;)
+ // credit: https://stackoverflow.com/questions/10696067/characters-allowed-in-php-array-keys -> Rob's answer
+ // but newer versions of php (v7+) seem to handle unicide keys nicely
+ $result[$c] = $tot;
+ $sum += $tot;
+ }
+
+ $result['all'] = $sum;
+
+ return $result;
+ }
+
+
+ // Preview Local Datetime ////////////////////////////////////////////////////
+ // (in Greek format and names )
+ // ---------------------------------------------------------------------------
+ public static function local_dt($t) {
+ $day = array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
+ $dayL = array("Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ");
+ $mon = array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+ $monL = array("Ιαν", "Φεβ", "Μαρ", "Απρ", "Μαϊ", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ");
+ $tm = array("am", "pm");
+ $tmL = array("πμ", "μμ");
+ $r = date("D. j M. Y, h:i:sa", $t);
+ $r = str_replace($day, $dayL, $r);
+ $r = str_replace($mon, $monL, $r);
+ $r = str_replace($tm, $tmL, $r);
+ return $r;
+ }
+
+
+ // Part of string
+ // UTF-8 SAFE
+ public static function str_part($str, $len) {
+ return (mb_strlen($str) > $len) ? mb_substr($str, 0, $len-1) ."…" : $str;
+ }
+
+
+ public static function make_a_form()
+ {
+
+ // Script Workflow:
+ // ---------------------------------------------------------------------------
+ // 1. read fields options
+ // 2. generate HTML
+ // 3. generate JS needed
+
+ // the UI
+ // ---------------------------------------------------------------------------
+ // Fields are grouped in sections
+ // These sections presented in tabs (or accordion if mobile device)
+ // Two (2) sections incduded to inform the user of empty fields or errors
+
+ // Libraries and FrameWorks used
+ // ---------------------------------------------------------------------------
+ // Bootstrap 4.3 is used for easy responsive HTML code
+ // JQuery 3.3 is used to handle user interation
+ // Select2 is used to make select-boxes (single or multiple) easier to use
+
+ // read fields options (json format) /////////////////////////////////////////
+ // ---------------------------------------------------------------------------
+ $formJSON = file_get_contents('config/kallassa.json');
+ $formARRAY = json_decode($formJSON);
+
+
+ // 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)
+
+
+
+ $html = '
+ <div class="pi-container">
+ <h2>Εισαγωγή Εγγραφής</h2>';
+
+ $i = 1;
+ foreach ($formARRAY as $key => $section) { // only one section
+
+ $html = '<hr />';
+
+ foreach ($section->childs as $kk => $field) {
+
+
+ // get attributes
+
+ $atrs = explode('|', $field->attr); // attributes array
+ $appendKey = in_array('append-key', $atrs) ? true : false; // append key (for selects)
+ $required = in_array('required', $atrs) ? 'required' : ''; // required
+ $asterisn = in_array('required', $atrs) ? '*' : ''; // asterisk in label if required
+ $class = (isset($field->len)) ? ' col-md-'.$field->len : 'col-md-12'; // column class (for width)
+ $name = $field->name;
+ $label = $field->label;
+
+
+ $html .= "
+ <div class='form-group {$class}'>
+ <label for='{$name}'>{$label} {$asterisk}</label>
+ ";
+
+ switch ($field->typ) {
+
+ case 'select':
+
+ if (in_array('multiple', $atrs)) { // if select is multiple
+
+ $html .="
+ <select id='{$name}$' class='select-field' name='{$name}[]' multiple='multiple' style='width:100%'>";
+
+ // prepare initialization of select2 (multiple)
+ $initSelectsJS .= "
+ var {$name} = $('#{$name}');
+ {$name}.select2({ width: '100%' });";
+
+ // prepare check if empty field
+ $checkFilledJS .= "
+ if (getValues({$name}) =='') { empty += '{$label} {$asterisk}<br />'; }
+ values.{$name} = getValues($name);";
+
+
+ } else { // select is single; draw select + add empty option
+
+ $html .="
+ <select id='{$name}$' class='select-field' name='{$name}' style='width:100%'>
+ <option></option>";
+
+ // prepare initialization of select2 (single)
+ $initSelectsJS .= "
+ var {$name} = $('#{$name}');
+ {$name}.select2({ allowClear: true });";
+
+ // prepare check if empty field
+ $checkFilledJS .= "
+ if (getValues({$name}) =='') { empty += '{$label} {$asterisk}<br />'; }
+ values.{$name} = getValues($name);";
+
+ }
+
+ // inject options
+ foreach ($field->options as $key => $val) {
+ $html .= "
+ <option value='{$val->id}'>{$val->tag}</option>";
+ }
+
+ // close select
+ $html .= "</select>";
+
+ break;
+
+
+ case 'text':
+
+ $html .= "
+ <input type='text' class='form-control' name='{$name}' {$required}>";
+
+ $checkFilledJS = "
+ if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; }
+ values.{$name} = $('input[name={$name}]').val();";
+
+ break;
+
+
+ case 'integer':
+
+ $html .= "
+ <input type='number' class='form-control' name='{$name}' min='0' step='1' {$required}>";
+
+ $checkFilledJS .= "
+ if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; }
+ values.{$name} = $('input[name={$name}]').val();";
+
+ break;
+
+
+ case 'textarea':
+
+ $html .= "
+ <textarea class='form-control' name='{$name}' {$required}></textarea>";
+
+ $checkFilledJS .= "
+ if ($('textarea[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; }
+ values.{$name} = $('textarea[name={$name}]').val();";
+
+ case 'date':
+
+ $html .= "
+ <input type='date' class='form-control' name='{$name}' {$required}>";
+
+ $checkFilledJS .= "
+ if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; }
+ values.{$name} = $('input[name={$name}]').val();";
+
+ break;
+
+
+ case 'email':
+
+ $html .= "
+ <input type='email' class='form-control' name='{$name}' {$required}>";
+
+ $checkFilledJS .= "
+ if ($('input[name={$name}]').val() =='') { empty += '{$label} {$asterisk}'<br />'; }
+ values.{$name} = $('input[name={$name}]').val();";
+
+ break;
+
+
+ default: // label, acts as common text
+
+ $html .= "<label>{$label}</label";
+
+
+ }
+ }
+ }
+ }
+
+}
+
+
+
+
+ /*****
+ // Script Workflow:
+ // ---------------------------------------------------------------------------
+ // 1. read fields options
+ // 2. generate HTML
+ // 3. generate JS needed
+
+ // the UI
+ // ---------------------------------------------------------------------------
+ // Fields are grouped in sections
+ // These sections presented in tabs (or accordion if mobile device)
+ // Two (2) sections incduded to inform the user of empty fields or errors
+
+ // Libraries and FrameWorks used
+ // ---------------------------------------------------------------------------
+ // Bootstrap 4.3 is used for easy responsive HTML code
+ // JQuery 3.3 is used to handle user interation
+ // Select2 is used to make select-boxes (single or multiple) easier to use
+
+
+ // read fields options (json format) /////////////////////////////////////////
+ // ---------------------------------------------------------------------------
+ $formJSON = file_get_contents('config/kallassa.json');
+ $formARRAY = json_decode($formJSON);
+
+
+ // 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)
+ */
+
+
+
+ /** document header
+ *
+ * <!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?> : Εισαγωγή Εγγραφής</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>
+ */
+
+
+ /** form footer
+ * <!-- 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>
+ * <textarea name="note" class="form-control tall"></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>
+ */
+
+
+ /** post-DOM-end + scripts
+ *
+ * </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();
+ *
+ * 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=additem"; // 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='+ json.id;
+ * }
+ * else {
+ * alert("Post not accepted.\nPlease check the data you submit.");
+ * // $('#oc-company-form')[0].reset();
+ * }
+ * },
+ *
+ * error: function() {
+ * alert('Some ajax error! :(');
+ * }
+ * });
+ * }
+ *
+ * waitingResponse = false;
+ * }
+ *
+ * });
+ *
+ * <?php
+ * // bibliography and References
+ * //
+ * // WHICH JQUERY:
+ * // read: https://jquery.com/download/
+ * //
+ * // SELECT2
+ * // https://stackoverflow.com/questions/12889309/get-selected-value-from-multi-value-select-boxes-by-jquery-select2
+ * //
+ * // tests:
+ * // https://jsfiddle.net/3nd1gL8o/1/
+ * // https://jsfiddle.net/3nd1gL8o/5/
+ * //
+ * // EXAMPLE with ALL CASES NEEDed:
+ * // https://jsfiddle.net/v684h0g2/2/
+ * ?>
+ * </script>
+ * </body>
+ * </html>
+ */
diff --git a/public/app/models/_info.md b/public/app/models/_info.md
index 5504523..0c19c02 100644
--- a/public/app/models/_info.md
+++ b/public/app/models/_info.md
@@ -1,150 +1,114 @@
# info about the structrure of the models
-According to the former impementation (atcom) the project will need to handle 200+ tables.
-The former project includes 209 tables with 5 or more rows (and 325 tables totaly)
-
-
-
-## Database schema
-
-Main tables and recomended constraints:
-
-```
-SET NAMES utf8;
-SET time_zone = '+00:00';
-SET foreign_key_checks = 0;
-SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
-
-SET NAMES utf8mb4;
-
-DROP TABLE IF EXISTS `course`;
-CREATE TABLE `course` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `parent_id` int(11) NOT NULL COMMENT 'if 0 then this is a root course',
- `label` varchar(140) COLLATE utf8mb4_unicode_ci NOT NULL,
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `lesson`;
-CREATE TABLE `lesson` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `course_id` int(11) NOT NULL,
- `title` varchar(140) COLLATE utf8mb4_unicode_ci NOT NULL,
- `body` text COLLATE utf8mb4_unicode_ci NOT NULL,
- `published` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0 = unpublished, 1 = published',
- PRIMARY KEY (`id`),
- KEY `course_id` (`course_id`),
- CONSTRAINT `lesson_ibfk_1` FOREIGN KEY (`course_id`) REFERENCES `course` (`id`),
- CONSTRAINT `lesson_ibfk_2` FOREIGN KEY (`course_id`) REFERENCES `course` (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `lesson_media`;
-CREATE TABLE `lesson_media` (
- `lesson_id` int(11) NOT NULL,
- `media_id` int(11) NOT NULL,
- PRIMARY KEY (`lesson_id`,`media_id`),
- KEY `media_id` (`media_id`),
- CONSTRAINT `lesson_media_ibfk_1` FOREIGN KEY (`lesson_id`) REFERENCES `lesson` (`id`),
- CONSTRAINT `lesson_media_ibfk_2` FOREIGN KEY (`lesson_id`) REFERENCES `lesson` (`id`),
- CONSTRAINT `lesson_media_ibfk_3` FOREIGN KEY (`lesson_id`) REFERENCES `lesson` (`id`),
- CONSTRAINT `lesson_media_ibfk_4` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`),
- CONSTRAINT `lesson_media_ibfk_5` FOREIGN KEY (`lesson_id`) REFERENCES `lesson` (`id`) ON DELETE NO ACTION,
- CONSTRAINT `lesson_media_ibfk_6` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`) ON DELETE NO ACTION,
- CONSTRAINT `lesson_media_ibfk_7` FOREIGN KEY (`lesson_id`) REFERENCES `lesson` (`id`) ON DELETE NO ACTION,
- CONSTRAINT `lesson_media_ibfk_8` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`) ON DELETE NO ACTION
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `lesson_privilege`;
-CREATE TABLE `lesson_privilege` (
- `lesson_id` int(11) NOT NULL,
- `privilege_id` int(11) NOT NULL COMMENT 'minimum privilege required to access the lesson',
- KEY `lesson_id` (`lesson_id`),
- KEY `privilege_id` (`privilege_id`),
- CONSTRAINT `lesson_privilege_ibfk_1` FOREIGN KEY (`lesson_id`) REFERENCES `lesson` (`id`),
- CONSTRAINT `lesson_privilege_ibfk_2` FOREIGN KEY (`privilege_id`) REFERENCES `privilege` (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `media`;
-CREATE TABLE `media` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `label` varchar(140) COLLATE utf8mb4_unicode_ci NOT NULL,
- `type` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
- `path` varchar(320) COLLATE utf8mb4_unicode_ci NOT NULL,
- `referable` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0 = hidden, 1 = referable',
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `page`;
-CREATE TABLE `page` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `title` varchar(140) COLLATE utf8mb4_unicode_ci NOT NULL,
- `body` text COLLATE utf8mb4_unicode_ci NOT NULL,
- `published` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0 = unpublished; 1 = published',
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `page_media`;
-CREATE TABLE `page_media` (
- `page_id` int(11) NOT NULL,
- `media_id` int(11) NOT NULL,
- KEY `page_id` (`page_id`),
- KEY `media_id` (`media_id`),
- CONSTRAINT `page_media_ibfk_1` FOREIGN KEY (`page_id`) REFERENCES `page` (`id`) ON DELETE NO ACTION,
- CONSTRAINT `page_media_ibfk_2` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`) ON DELETE NO ACTION
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `privilege`;
-CREATE TABLE `privilege` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `alias` varchar(8) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'keep it simple; use latin',
- `label` varchar(140) COLLATE utf8mb4_unicode_ci NOT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `alias` (`alias`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `privilege_inherit`;
-CREATE TABLE `privilege_inherit` (
- `higher_id` int(11) NOT NULL COMMENT 'higher priviledges inherit (include) lower ones',
- `lower_id` int(11) NOT NULL,
- PRIMARY KEY (`higher_id`,`lower_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `user`;
-CREATE TABLE `user` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `first_name` int(11) NOT NULL,
- `last_name` int(11) NOT NULL,
- `email` int(11) NOT NULL,
- `expiration` int(11) NOT NULL COMMENT 'account expiration date; 0 = never',
- `password` int(11) NOT NULL,
- `salt` int(11) NOT NULL,
- `otp` int(11) NOT NULL COMMENT 'one time password for reset password',
- `otp_expiration` int(11) NOT NULL,
- `active` int(11) NOT NULL COMMENT 'account flag; 1=active, 0=inactive',
- PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-
-DROP TABLE IF EXISTS `user_privilege`;
-CREATE TABLE `user_privilege` (
- `user_id` int(11) NOT NULL,
- `privilege_id` int(11) NOT NULL,
- PRIMARY KEY (`user_id`,`privilege_id`),
- KEY `privilege_id` (`privilege_id`),
- CONSTRAINT `user_privilege_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
- CONSTRAINT `user_privilege_ibfk_2` FOREIGN KEY (`privilege_id`) REFERENCES `privilege` (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-
-```
+## user fields; insert / update sql queries
+
+INSERT INTO user
+( id,
+ prefix,
+ first_name,
+ last_name,
+ email,
+ father_name,
+ registration_number,
+ sector_id,
+ specialty,
+ belonging_school,
+ working_shcool,
+ position_type_id,
+ phone,
+ password,
+ expiration,
+ otp,
+ otp_expiration,
+ activation,
+ creation,
+active) VALUES (:id,
+ :prefix,
+ :first_name,
+ :last_name,
+ :email,
+ :father_name,
+ :registration_number,
+ :sector_id,
+ :specialty,
+ :belonging_school,
+ :working_shcool,
+ :position_type_id,
+ :phone,
+ :password,
+ :expiration,
+ :otp,
+ :otp_expiration,
+ :activation,
+ :creation,
+:active )
+
+
+
+UPDATE user
+SET prefix = :prefix,
+first_name = :first_name,
+last_name = :last_name,
+email = :email,
+father_name = :father_name,
+registration_number = :registration_number,
+sector_id = :sector_id,
+specialty = :specialty,
+belonging_school = :belonging_school,
+working_shcool = :working_shcool,
+position_type_id = :position_type_id,
+phone = :phone,
+password = :password,
+expiration = :expiration,
+otp = :otp,
+otp_expiration = :otp_expiration,
+activation = :activation,
+creation = :creation,
+active = :active,
+
+
+## record_types
+
+document forms -> json
+
+request = {
+ user_id -> user: {
+ ...
+ }
+ date: ...
+ body: ...
+ media: [ ... array of media-id(s) ]
+}
+
+penalty = {
+ user_id -> user: {
+ ...
+ },
+ date:
+ time:
+ subject:
+ of_student:
+ place:
+ president:
+ members: [ list ]
+ reason:
+ apology:
+ decision:
+}
+
+
+## records
+
+id
+user_id
+type
+source_json
+
+
+## record_media
+
+record_id
+media_id