diff --git a/4dev/database/ORDER b/4dev/database/ORDER index 916f9c29..e5070a32 100644 --- a/4dev/database/ORDER +++ b/4dev/database/ORDER @@ -1,5 +1,7 @@ # functions function/update_function.sql +function/random_string.sql +function/edit_set_access_uid.sql # generic tables table/edit_temp_files.sql table/edit_generic.sql @@ -33,3 +35,4 @@ trigger/trg_edit_scheme.sql trigger/trg_edit_user.sql trigger/trg_edit_visible_group.sql trigger/trg_edit_menu_group.sql +trigger/trg_set_edit_access_uid.sql diff --git a/4dev/database/function/random_string.sql b/4dev/database/function/random_string.sql new file mode 100755 index 00000000..5a0a6c5d --- /dev/null +++ b/4dev/database/function/random_string.sql @@ -0,0 +1,18 @@ +-- create random string with length X + +CREATE FUNCTION random_string(randomLength int) +RETURNS text AS $$ +SELECT array_to_string( + ARRAY( + SELECT substring( + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', + trunc(random() * 62)::int + 1, + 1 + ) + FROM generate_series(1, randomLength) AS gs(x) + ), + '' +) +$$ LANGUAGE SQL +RETURNS NULL ON NULL INPUT +VOLATILE; -- LEAKPROOF; \ No newline at end of file diff --git a/4dev/database/function/set_generic.sql b/4dev/database/function/set_generic.sql index d9ee552e..aa3f8ac6 100644 --- a/4dev/database/function/set_generic.sql +++ b/4dev/database/function/set_generic.sql @@ -1,9 +1,12 @@ -- adds the created or updated date tags CREATE OR REPLACE FUNCTION set_generic() RETURNS TRIGGER AS ' + DECLARE + random_length INT = 12; -- that should be long enough BEGIN IF TG_OP = ''INSERT'' THEN NEW.date_created := ''now''; + NEW.cuid := random_string(random_length); ELSIF TG_OP = ''UPDATE'' THEN NEW.date_updated := ''now''; END IF; diff --git a/4dev/database/table/edit_access.sql b/4dev/database/table/edit_access.sql index 22ea6485..72742df9 100644 --- a/4dev/database/table/edit_access.sql +++ b/4dev/database/table/edit_access.sql @@ -18,3 +18,4 @@ CREATE TABLE edit_access ( DELETE FROM edit_access; INSERT INTO edit_access (name, enabled, protected) VALUES ('Admin Access', 't', 1); +INSERT INTO edit_access (name, enabled, protected) VALUES ('User Access', 't', 1); diff --git a/4dev/database/table/edit_access_user.sql b/4dev/database/table/edit_access_user.sql index 8348d169..84cd2b9d 100644 --- a/4dev/database/table/edit_access_user.sql +++ b/4dev/database/table/edit_access_user.sql @@ -19,4 +19,8 @@ CREATE TABLE edit_access_user ( ) INHERITS (edit_generic) WITHOUT OIDS; DELETE FROM edit_access_user; -INSERT INTO edit_access_user (edit_default, edit_access_id, edit_user_id, edit_access_right_id) VALUES (1, 1, 1, 8); +INSERT INTO edit_access_user (edit_default, edit_access_id, edit_user_id, edit_access_right_id) VALUES (1, + (SELECT edit_access_id FROM edit_access WHERE uid = 'AdminAccess') + (SELECT edit_user_id FROM edit_user WHERE username = 'admin') + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); diff --git a/4dev/database/table/edit_generic.sql b/4dev/database/table/edit_generic.sql index 88c80f22..a1e9ef8a 100644 --- a/4dev/database/table/edit_generic.sql +++ b/4dev/database/table/edit_generic.sql @@ -7,7 +7,7 @@ -- DROP TABLE edit_generic; CREATE TABLE edit_generic ( - eg_status INT, + cuid VARCHAR, date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT clock_timestamp(), date_updated TIMESTAMP WITHOUT TIME ZONE ); diff --git a/4dev/database/table/edit_group.sql b/4dev/database/table/edit_group.sql index 93365c62..dc6ba893 100644 --- a/4dev/database/table/edit_group.sql +++ b/4dev/database/table/edit_group.sql @@ -16,4 +16,11 @@ CREATE TABLE edit_group ( FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE ) INHERITS (edit_generic) WITHOUT OIDS; -INSERT INTO edit_group (name, enabled, edit_scheme_id, edit_access_right_id) VALUES ('Admin', 1, 2, 8); +INSERT INTO edit_group (name, enabled, edit_scheme_id, edit_access_right_id) VALUES ('Admin', 1, + (SELECT edit_scheme_id FROM edit_scheme WHERE name = 'Admin'), + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); +INSERT INTO edit_group (name, enabled, edit_scheme_id, edit_access_right_id) VALUES ('User', 1, + (SELECT edit_scheme_id FROM edit_scheme WHERE name = 'User'), + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'write') +); diff --git a/4dev/database/table/edit_language.sql b/4dev/database/table/edit_language.sql index 282d0d21..6f94a91e 100644 --- a/4dev/database/table/edit_language.sql +++ b/4dev/database/table/edit_language.sql @@ -18,3 +18,4 @@ CREATE TABLE edit_language ( ) INHERITS (edit_generic) WITHOUT OIDS; INSERT INTO edit_language (short_name, long_name, iso_name, order_number, enabled, lang_default) VALUES ('en', 'English', 'UTF-8', 1, 1, 1); +INSERT INTO edit_language (short_name, long_name, iso_name, order_number, enabled, lang_default) VALUES ('ja', 'Japanese', 'UTF-8', 2, 1, 0); diff --git a/4dev/database/table/edit_page_access.sql b/4dev/database/table/edit_page_access.sql index 165f6a23..fe76e89f 100644 --- a/4dev/database/table/edit_page_access.sql +++ b/4dev/database/table/edit_page_access.sql @@ -17,12 +17,48 @@ CREATE TABLE edit_page_access ( FOREIGN KEY (edit_access_right_id) REFERENCES edit_access_right (edit_access_right_id) MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE ) INHERITS (edit_generic) WITHOUT OIDS; -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 1, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 2, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 3, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 4, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 5, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 6, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 7, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 8, 8); -INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, 1, 9, 8); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 1, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 2, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') + ); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 3, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 4, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 5, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 6, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin' + ); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 7, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin' +); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 8, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); +INSERT INTO edit_page_access (enabled, edit_group_id, edit_page_id, edit_access_right_id) VALUES (1, + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + 9, + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); diff --git a/4dev/database/table/edit_scheme.sql b/4dev/database/table/edit_scheme.sql index 809dfe9e..893bdeef 100644 --- a/4dev/database/table/edit_scheme.sql +++ b/4dev/database/table/edit_scheme.sql @@ -18,3 +18,4 @@ CREATE TABLE edit_scheme ( INSERT INTO edit_scheme (name, header_color, enabled) VALUES ('Default Scheme', 'E0E2FF', 1); INSERT INTO edit_scheme (name, header_color, enabled) VALUES ('Admin', 'CC7E7E', 1); INSERT INTO edit_scheme (name, header_color, enabled) VALUES ('Visitor', 'B0C4B3', 1); +INSERT INTO edit_scheme (name, header_color, enabled) VALUES ('User', '1E789E', 1); diff --git a/4dev/database/table/edit_user.sql b/4dev/database/table/edit_user.sql index db412dee..509d72e4 100644 --- a/4dev/database/table/edit_user.sql +++ b/4dev/database/table/edit_user.sql @@ -10,6 +10,8 @@ CREATE TABLE edit_user ( edit_user_id SERIAL PRIMARY KEY, username VARCHAR UNIQUE, password VARCHAR, + first_name VARCHAR, + last_name VARCHAR, enabled SMALLINT NOT NULL DEFAULT 0, debug SMALLINT NOT NULL DEFAULT 0, db_debug SMALLINT NOT NULL DEFAULT 0, @@ -35,4 +37,9 @@ CREATE TABLE edit_user ( -- inserts admin user so basic users can be created DELETE FROM edit_user; -INSERT INTO edit_user (username, password, enabled, debug, db_debug, email, protected, admin, edit_language_id, edit_group_id, edit_scheme_id, edit_access_right_id) VALUES ('admin', 'admin', 1, 1, 1, '', 1, 1, 1, 1, 2, 8); +INSERT INTO edit_user (username, password, enabled, debug, db_debug, email, protected, admin, edit_language_id, edit_group_id, edit_scheme_id, edit_access_right_id) VALUES ('admin', 'admin', 1, 1, 1, '', 1, 1, + (SELECT edit_language_id FROM edit_language WHERE short_name = 'en'), + (SELECT edit_group_id FROM edit_group WHERE name = 'Admin'), + (SELECT edit_scheme_id FROM edit_scheme WHERE name = 'Admin') + (SELECT edit_access_right_id FROM edit_access_right WHERE type = 'admin') +); diff --git a/www/admin/edit_base.inc b/www/admin/edit_base.inc index 9713df12..ad6690aa 100644 --- a/www/admin/edit_base.inc +++ b/www/admin/edit_base.inc @@ -139,8 +139,11 @@ $PAGES = $_SESSION["PAGES"]; //$form->debug('menu', $form->printAr($PAGES)); -// baue nav aus $PAGES ... -for ($i = 0; $i < count($PAGES); $i ++) { +// build nav from $PAGES ... +if (!is_array($PAGES)) { + $PAGES = array (); +} +for ($i = 0, $i_max = count($PAGES); $i < $i_max; $i ++) { if ($PAGES[$i]["menu"] && $PAGES[$i]["online"]) { $menuarray[] = $PAGES[$i]; } diff --git a/www/layout/admin/default/css/edit.css b/www/layout/admin/default/css/edit.css index a889bff2..19371ba0 100644 --- a/www/layout/admin/default/css/edit.css +++ b/www/layout/admin/default/css/edit.css @@ -367,6 +367,30 @@ input[type="text"]:focus, textarea:focus, select:focus { font-size: 8px; } +/* NEW VERSION with CSS key frame animation */ +.progress { + width: 100px; + height: 100px; + background: rgba(255, 255, 255, 0.6); + border: 20px solid rgba(255, 255, 255 ,0.25); + border-left-color: rgba(3, 155, 229 ,1); + border-top-color: rgba(3, 155, 229 ,1); + border-radius: 50%; + display: inline-block; + animation: rotate 600ms infinite linear; + /* align */ + left: 0; + top: 0; + position: absolute; + z-index: 100; +} +/* Animation for above progress */ +@keyframes rotate { + to { + transform: rotate(1turn) + } +} + /* ***************************** ADMIN EDIT INTERFACE COLORS ********************************* */ /* set all colors here and not in the config file */ /* for edit interface */ diff --git a/www/layout/admin/default/javascript/edit.js b/www/layout/admin/default/javascript/edit.js index f12f23fd..0de06ae5 100644 --- a/www/layout/admin/default/javascript/edit.js +++ b/www/layout/admin/default/javascript/edit.js @@ -2,6 +2,8 @@ code is taken and adapted from dokuwiki */ +/* jshint esversion: 6 */ + /** * Some browser detection */ @@ -207,3 +209,116 @@ function formatBytes(bytes) return parseFloat(Math.round(bytes * Math.pow(10, 2)) / Math.pow(10, 2)) + ['kB', 'MB', 'GB', 'TB', 'PB', 'EB'][i]; } + +// *** DOM MANAGEMENT FUNCTIONS +// METHOD: cel [create element] +// PARAMS: tag: must set tag (div, span, etc) +// id: optional set for id, if input, select will be used for name +// content: text content inside, is skipped if sub elements exist +// css: array for css tags +// options: anything else (value, placeholder, OnClick, style) +// RETURN: object +// DESC : creates object for DOM element creation flow +const cel = (tag, id = '', content = '', css = [], options = {}) => + element = { + tag: tag, + id: id, + content: content, + css: css, + options: options, + sub: [] + }; + +// METHOD: ael [attach element] +// PARAMS: base: object where to attach/search +// attach: the object to be attached +// id: optional id, if given search in base for this id and attach there +// RETURN: "none", technically there is no return needed +// DESC : attach a cel created object to another to create a basic DOM tree +function ael(base, attach, id = '') +{ + if (id) { + // base id match already + if (base.id == id) { + base.sub.push(attach); + } else { + // sub check + if (base.sub.length > 0) { + base.sub.each(function(t) { + // recursive call to sub element + ael(t, attach, id); + }); + } + } + } else { + base.sub.push(attach); + } + return base; +} + +// METHOD: rel [rese element] +// PARAMS: cel created element +// RETURN: "none", is self change, but returns base.sub +// DESC : resets the sub elements of the base element given +const rel = (base) => base.sub = []; + +// METHOD: phfo [produce html from object] +// PARAMS: object tree with dom element declarations +// RETURN: HTML string that can be used as innerHTML +// DESC : parses the object tree created with cel/ael +// and converts it into an HTML string that can +// be inserted into the page +function phfo(tree) +{ + // holds the elements + let content = []; + // main part line + let line = '<' + tree.tag; + // first id, if set + if (tree.id) { + line += ' id="' + tree.id + '"'; + // if anything input (input, textarea, select then add name too) + if (['input', 'textarea', 'select'].includes(tree.tag)) { + line += ' name="' + tree.id + '"'; + } + } + // second CSS + if (tree.css.length > 0) { + line += ' class="'; + tree.css.each(function(t) { + line += t + ' '; + }); + // strip last space + line = line.slice(0, -1); + line += '"'; + } + // options is anything key = "data" + if (tree.options) { + // ignores id, name, class as key + for (const [key, item] of Object.entries(tree.options)) { + if (!['id', 'name', 'class'].includes(key)) { + line += ' ' + key + '="' + item + '"'; + } + } + } + // finish open tag + line += '>'; + // push finished line + content.push(line); + // dive into sub tree to attach sub nodes + // NOTES: we cannot have content (text) AND sub nodes at the same level + // NODE takes preference over content + if (tree.sub.length > 0) { + tree.sub.each(function(t) { + content.push(phfo(t)); + }); + } else if (tree.content) { + content.push(tree.content); + } + // if not input close + if (tree.tag != 'input') { + content.push(''); + } + // combine to string + return content.join(''); +} diff --git a/www/layout/frontend/default/css/frontend.css b/www/layout/frontend/default/css/frontend.css index 382cd316..9b66442e 100644 --- a/www/layout/frontend/default/css/frontend.css +++ b/www/layout/frontend/default/css/frontend.css @@ -3,3 +3,27 @@ color: #a4a4a4; font-size: 8px; } + +/* NEW VERSION with CSS key frame animation */ +.progress { + width: 100px; + height: 100px; + background: rgba(255, 255, 255, 0.6); + border: 20px solid rgba(255, 255, 255 ,0.25); + border-left-color: rgba(3, 155, 229 ,1); + border-top-color: rgba(3, 155, 229 ,1); + border-radius: 50%; + display: inline-block; + animation: rotate 600ms infinite linear; + /* align */ + left: 0; + top: 0; + position: absolute; + z-index: 100; +} +/* Animation for above progress */ +@keyframes rotate { + to { + transform: rotate(1turn) + } +} \ No newline at end of file diff --git a/www/lib/CoreLibs/DB/IO.inc b/www/lib/CoreLibs/DB/IO.inc index 137eb20a..d05e31c1 100644 --- a/www/lib/CoreLibs/DB/IO.inc +++ b/www/lib/CoreLibs/DB/IO.inc @@ -1656,7 +1656,7 @@ class IO extends \CoreLibs\Basic return false; } $not_write_update_array = array (); - return $this->dbWriteData_ext($write_array, $primary_key, $table, $not_write_array, $not_write_update_array, $data); + return $this->dbWriteDataExt($write_array, $primary_key, $table, $not_write_array, $not_write_update_array, $data); } // METHOD: dbWriteDataExt diff --git a/www/lib/CoreLibs/Output/Form/Generate.inc b/www/lib/CoreLibs/Output/Form/Generate.inc index dda68ed5..a7d4ccf4 100644 --- a/www/lib/CoreLibs/Output/Form/Generate.inc +++ b/www/lib/CoreLibs/Output/Form/Generate.inc @@ -516,8 +516,8 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO } } elseif (is_array($this->element_list[$element_list[$i]]["read_data"]) && $this->element_list[$element_list[$i]]["delete"]) { // $this->debug('form_clean', "ID [$id] [$prfx.$pk_name]"); - // $this->debug('form_clean', "ID arr: ".$this->print_ar($_POST[$id])); - // $this->debug('form_clean', "PK arr: ".$this->print_ar($_POST[$prfx.$pk_name])); + // $this->debug('form_clean', "ID arr: ".$this->printAr($_POST[$id])); + // $this->debug('form_clean', "PK arr: ".$this->printAr($_POST[$prfx.$pk_name])); for ($j = 0, $j_max = count($_POST[$prfx.$pk_name]); $j < $j_max; $j ++) { if (!$_POST[$remove_name[$i]][$j] && $_POST[$prfx.$pk_name][$j]) { $q = "DELETE FROM ".$element_list[$i]." WHERE ".$pk_name." = ".$_POST[$prfx.$pk_name][$j]; @@ -975,7 +975,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO // $this->debug('edit_error_chk', "KEY: $prfx$key | count: ".count($_POST[$prfx.$key])." | M: $max"); // $this->debug('edit_error_chk', "K: ".$_POST[$prfx.$key]." | ".$_POST[$prfx.$key][0]); } - $this->debug('post_array', $this->print_ar($_POST)); + $this->debug('post_array', $this->printAr($_POST)); # check each row for ($i = 0; $i < $max; $i ++) { // either one of the post pks is set, or the mandatory @@ -1305,7 +1305,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO foreach ($reference_array["elements"] as $el_name => $data_array) { // this is only for reference_data part, at least one of the text fields need to be set for writing $blow_write = array (); - // $this->debug('edit_error_query', "QUERY: ".$this->print_ar($_POST)); + // $this->debug('edit_error_query', "QUERY: ".$this->printAr($_POST)); // go through all submitted data // for ($i = 0; $i < count($_POST[$el_name]); $i ++) for ($i = 0; $i < $max; $i ++) { @@ -1542,7 +1542,7 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO // generic data read in (counts for all rows) // visible list data output foreach ($this->element_list[$table_name]["elements"] as $el_name => $data_array) { - $this->debug('CFG', 'El: '.$el_name.' -> '.$this->print_ar($data_array)); + $this->debug('CFG', 'El: '.$el_name.' -> '.$this->printAr($data_array)); // if the element name matches the read array, then set the table as a name prefix $q_select[] = $el_name; // this is for reading the data // prefix the name for any further data parts @@ -1587,9 +1587,9 @@ class Generate extends \CoreLibs\DB\Extended\ArrayIO } // $proto[$el_name] = $this->error ? $_POST[$el_name][(count($_POST[$el_name]) - 1)] : ''; } - // $this->debug('CFG DATA', 'Data: '.$this->print_ar($data)); - // $this->debug('CFG PROTO', 'Proto: '.$this->print_ar($proto)); - // $this->debug('CFG SELECT', 'Proto: '.$this->print_ar($q_select)); + // $this->debug('CFG DATA', 'Data: '.$this->printAr($data)); + // $this->debug('CFG PROTO', 'Proto: '.$this->printAr($proto)); + // $this->debug('CFG SELECT', 'Proto: '.$this->printAr($q_select)); // query for reading in the data $this->debug('edit_error', "ERR: ".$this->error); // if we got a read data, build the read select for the read, and read out the "selected" data