diff --git a/.gitignore b/.gitignore index fe59acd..b21055b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .env tmp/ *.log -app/webroot/test.html \ No newline at end of file +app/webroot/test.html +*.po~ +*.po \ No newline at end of file diff --git a/app/controllers/admin_base_trait.php b/app/controllers/admin_base_trait.php index 2abeb19..4bee189 100644 --- a/app/controllers/admin_base_trait.php +++ b/app/controllers/admin_base_trait.php @@ -2,50 +2,76 @@ trait AdminBaseTrait { private $_model = ''; + private $_model_camelized = ''; + private $_response = [ + 'd' => [], + 'message' => '' + ]; + private $_is_routed = false; + private $_actions = []; - private function _init() { - parent::__construct(); + private function _additional_before_filter() {} - $this->layout = 'layout'; - $this->helper = ['Sessions','Menu']; + private function _prepare_data() { + if(in_array($this->action, $this->_actions)): + $this->_model = Singulars($this->action); + $this->_model_camelized = Camelize($this->_model); + $this->_is_routed = true; + $this->action = 'landing'; + endif; } - public function before_filter() { - Require_login(); - $this->menuLinks = adminMenu(); + private function _edit_reg() { + $this->layout = false; + if(empty($this->params[1])): + throw new Exception('ID param must be given'); + else: + $this->render = ['file'=>"{$this->controller}/{$this->_model}_addedit.phtml"]; + $this->data = $this->{$this->_model_camelized}->Find($this->params[1]); + endif; + } + + private function _add_reg() { + $this->layout = false; + $this->render = ['file'=>"{$this->controller}/{$this->_model}_addedit.phtml"]; + $this->data = $this->{$this->_model_camelized}->Niu(); + } + + private function _list_regs() { + $this->render = ['file'=>"{$this->controller}/{$this->_model}_list.phtml"]; + $conditions = ''; + $this->searchterm = ''; + + if(!empty($_POST['search']) and !empty($_POST['search']['term']) and !empty($_POST['search']['fields'])): + $this->searchterm = $_POST['search']['term']; + while(null !== ($field = array_shift($_POST['search']['fields']))): + empty($conditions) or ($conditions = "{$conditions} OR "); + $conditions = "{$conditions}`{$field}` LIKE '%{$_POST['search']['term']}%'"; + endwhile; + endif; + + $this->data = $this->{$this->_model_camelized}->Paginate(['conditions'=>$conditions]); } - public function deleteregAction() { + private function _delete_reg() { $code = HTTP_422; - /** message key is a kinda standard, if an error occurs, message is the same attribute as in exception object */ - $response = [ - 'd' => [], - 'message' => '' - ]; if (!empty($this->_model) and !empty($this->params['id'])): - $model = Camelize(Singulars($this->_model)); - - $obj = $this->{$model}->Find((integer)$this->params['id']); - ($obj->Delete() and ($code = HTTP_200) and ($response['message'] = 'Success')) or ($response['m'] = (string)$obj->_error); + $obj = $this->{$this->_model_camelized}->Find((integer)$this->params['id']); + ($obj->Delete() and ($code = HTTP_200) and ($this->_response['message'] = _('general.save.success'))) or ($this->_response['m'] = (string)$obj->_error); endif; http_response_code($code); - $this->respondToAJAX(json_encode($response)); + $this->respondToAJAX(json_encode($this->_response)); } - public function addregAction() { + private function _save_reg() { $code = HTTP_422; - $response = [ - 'd' => [], - 'message' => 'Error Saving' - ]; if(!empty($this->_model) and !empty($_POST[$this->_model])): - $model = Camelize(Singulars($this->_model)); - $data = $this->{$model}->Niu($_POST[$this->_model]); + $data = $this->{$this->_model_camelized}->Niu($_POST[$this->_model]); ( $data->Save() - and ($response['d'] = $data and ($response['message'] = 'Success') and $code = HTTP_200) + and ($response['d'] = $data and ($response['message'] = _('general.save.success')) and $code = HTTP_200) ) or ($response['message'] = (string)$data->_error); endif; @@ -53,4 +79,36 @@ public function addregAction() { http_response_code($code); $this->respondToAJAX(json_encode($response)); } + + public function before_filter() { + Require_login(); + $this->menuLinks = adminMenu(); + $this->_additional_before_filter(); + $this->_prepare_data(); + } + + public function landingAction() { + $this->render = ['text'=>'noop']; + + if($this->_is_routed): + empty($this->params[0]) and ($this->params[0] = 'list'); + switch($this->params[0]): + case 'edit': + $this->_edit_reg(); + break; + case 'add': + $this->_add_reg(); + break; + case 'delete': + $this->_delete_reg(); + break; + case 'list': + $this->_list_regs(); + break; + case 'save': + $this->_save_reg(); + break; + endswitch; + endif; + } } diff --git a/app/controllers/admin_controller.php b/app/controllers/admin_controller.php index 6cdbe21..a16ef24 100644 --- a/app/controllers/admin_controller.php +++ b/app/controllers/admin_controller.php @@ -1,36 +1,35 @@ _init(); - } + public $layout = 'layout'; + public $helper = ['Sessions','Menu']; - public function indexAction() { - $this->render = ['text'=>'noop']; - } + public function __construct() { + parent::__construct(); - public function usersAction() { - $this->users = $this->User->Find(); + textdomain('translations'); } - public function deleteuserAction() { - $this->_model = 'user'; - $this->deleteregAction(); + private function _additional_before_filter() { + $this->_actions = [ + 'users', + 'projects', + 'estates', + 'translations' + ]; } - public function useraddregAction() { - $this->_model = 'user'; - $this->addregAction(); + public function indexAction() { + $this->render = ['text'=>'noop']; } - public function useraddeditAction() { - $this->layout = false; - if(empty($this->params['id'])): - $this->data = $this->ProjectGroup->Niu(); - else: - $this->data = $this->ProjectGroup->Find($this->params['id']); - endif; + public function buildlanguagesAction() { + chdir(INST_PATH); + system('dumbo run background/gettext > /dev/null 2>&1 &'); + $this->respondToAJAX('{}'); } } \ No newline at end of file diff --git a/app/controllers/background_controller.php b/app/controllers/background_controller.php new file mode 100644 index 0000000..db3f7c1 --- /dev/null +++ b/app/controllers/background_controller.php @@ -0,0 +1,154 @@ + + * @version 1.0 + * @package MUYCCTV + * @subpackage Controllers + */ +class BackgroundController extends Page { + public $layout = false; + public $noTemplate = [ + 'index', + 'gettext', + 'serverdata' + ]; + private $_colorMsg = null; + public $shellOutput = true; + + public function __construct() { + parent::__construct(); + class_exists('DumboShellColors') or require_once('DumboShellColors.php'); + $this->_colorMsg = new DumboShellColors(); + } + + private function _logger($source, $message) { + if (empty($source) or empty($message) or !is_string($source) or !is_string($message)): + return false; + endif; + $logdir = INST_PATH.'tmp/logs/'; + is_dir($logdir) or mkdir($logdir, 0775); + $file = "{$source}.log"; + $stamp = date('d-m-Y H:i:s'); + + file_exists("{$logdir}{$file}") and filesize("{$logdir}{$file}") >= 524288000 and rename("{$logdir}{$file}", "{$logdir}{$stamp}_{$file}"); + $this->shellOutput and fwrite(STDOUT, $this->_colorMsg->getColoredString($message, 'white', 'green') . "\n"); + file_put_contents("{$logdir}{$file}", "[{$stamp}] - {$message}\n", FILE_APPEND); + return true; + } + + private function _readFiles($path, $pattern) { + $files = []; + $dir = opendir($path); + //first level, not subdirectories + while(false !== ($file = readdir($dir))): + $file !== '.' and $file !== '..' and is_file("{$path}{$file}") and preg_match($pattern, $file, $matches) === 1 and ($files[] = "{$path}{$file}"); + endwhile; + closedir($dir); + //Second level, subdirectories + $dir = opendir($path); + while(false !== ($file = readdir($dir))): + $npath = "{$path}{$file}"; + if ($file !== '.' and $file !== '..' and is_dir($npath) and is_readable($npath)): + $dir1 = opendir("{$path}{$file}"); + if(false !== $dir1): + while(false !== ($file1 = readdir($dir1))): + is_file("{$path}{$file}/{$file1}") and preg_match($pattern, $file1, $matches) === 1 and ($files[] = "{$path}{$file}/{$file1}"); + endwhile; + closedir($dir1); + endif; + endif; + endwhile; + closedir($dir); + sort($files); + + return $files; + } + + public function gettextAction() { + $files = array_merge( + $this->_readFiles(INST_PATH.'app/', '/(.+)\.php/'), + $this->_readFiles(INST_PATH.'app/views/', '/(.+)\.phtml/') + ); + + $tmpFile = tempnam('/tmp', 'gettext'); + file_put_contents($tmpFile, implode(PHP_EOL, $files)); + $languages = [ + 'en_US' => 'English', + 'es_CO' => 'Spanish', + 'es_MX' => 'Spanish', + 'pt_BR' => 'Portuguese' + ]; + $locales = [ + 'en_US', + 'es_CO', + 'es_MX', + 'pt_BR' + ]; + file_exists(INST_PATH.'locale') or mkdir(INST_PATH.'locale'); + while (null !== ($locale = array_shift($locales))): + file_exists(INST_PATH."locale/{$locale}.utf8") or mkdir(INST_PATH."locale/{$locale}.utf8"); + file_exists(INST_PATH."locale/{$locale}.utf8/LC_MESSAGES") or mkdir(INST_PATH."locale/{$locale}.utf8/LC_MESSAGES"); + $srclangpo = INST_PATH."locale/{$locale}.po"; + exec("xgettext --language=PHP --sort-output --files-from={$tmpFile} -o {$srclangpo} > /dev/null 2>&1 "); + $tgtlang = INST_PATH."locale/{$locale}.utf8/LC_MESSAGES/translations.po"; + file_exists($tgtlang) or copy($srclangpo, $tgtlang); + exec("msgmerge --update {$tgtlang} {$srclangpo} > /dev/null 2>&1"); + unlink($srclangpo); + + $moHeader = <<, 2021. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: KOMODO-1.0\\n" +"Report-Msgid-Bugs-To: javier@latuteca.com\\n" +"POT-Creation-Date: 2020-05-08 03:01-0500\\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n" +"Last-Translator: Javier Serrano \\n" +"Language-Team: DEVELOPMENT \\n" +"Language: {$languages[$locale]}\\n" +"MIME-Version: 1.0\\n" +"Content-Type: text/plain; charset=UTF-8\\n" +"Content-Transfer-Encoding: 8bit\\n" +\n +DUMBO; + + $fp = fopen($tgtlang, 'r'); + if($fp): + while(false !== ($buffer = fgets($fp, 1024))): + if (preg_match('@^msgid[ ]{1}\"[a-zA-Z0-9.]+\"$@i', $buffer)) { + $id = trim(str_replace('"', '', str_replace('msgid ', '', $buffer))); + $str = trim(str_replace('"', '', str_replace('msgstr ', '', fgets($fp, 1024)))); + + $this->Translation->Find([ + 'first', + 'conditions' => "`locale` = '{$locale}' AND `keyid` = '{$id}'" + ])->counter() === 0 and $this->Translation->Niu([ + 'locale' => $locale, + 'translation' => $str, + 'keyid' => $id + ])->Save(); + } + endwhile; + fclose($fp); + endif; + + file_put_contents($tgtlang, $moHeader); + + $translations = $this->Translation->Find_by_locale($locale)->getArray(); + while(null !== ($reg = array_shift($translations))): + $ent = html_entity_decode($reg['translation'], ENT_QUOTES, 'UTF-8'); + $str = "msgid \"{$reg['keyid']}\"\nmsgstr \"{$ent}\"\n\n"; + file_put_contents($tgtlang, $str, FILE_APPEND); + endwhile; + $tgtlang = substr($tgtlang, 0, -2); + exec("msgfmt --output-file={$tgtlang}mo {$tgtlang}po > /dev/null 2>&1"); + endwhile; + unlink($tmpFile); + } + +} diff --git a/app/controllers/common_trait.php b/app/controllers/common_trait.php new file mode 100644 index 0000000..0b8efb5 --- /dev/null +++ b/app/controllers/common_trait.php @@ -0,0 +1,31 @@ +layout = false; + } + + public function signinAction() { + $code = HTTP_401; + + if (!empty($_POST['e']) and !empty($_POST['p'])): + $id = $this->User->login($_POST['e'], $_POST['p'], $this->_loginLevel); + $id > 0 and ($code = HTTP_202) and ($_SESSION['user'] = $id); + endif; + + http_response_code($code); + $this->respondToAJAX('{}'); + } + /** + * Destroy all registered information of a session and redirect to the login page. + */ + public function logoutAction() { + $this->layout = false; + php_sapi_name() !== 'cli' && session_destroy(); + $_SESSION = null; + unset($_SESSION); + header("Location: /{$this->controller}/login"); + } +} \ No newline at end of file diff --git a/app/controllers/index_controller.php b/app/controllers/index_controller.php index aa74433..2f64619 100644 --- a/app/controllers/index_controller.php +++ b/app/controllers/index_controller.php @@ -1,15 +1,14 @@ 'login,logout,signin' ]; - - public function __construct() { - $this->_init(); - } + public $noTemplate = ['logout']; public function before_filter() { Require_login(); @@ -22,26 +21,7 @@ public function indexAction() { public function loginAction() { $this->layout = false; + !empty($_SESSION['user']) and header('Location: /login/index'); } - public function signinAction() { - $code = HTTP_401; - - if (!empty($_POST['e']) and !empty($_POST['p'])): - $id = $this->User->login($_POST['e'], $_POST['p']); - $id > 0 and ($code = HTTP_202) and ($_SESSION['user'] = $id); - endif; - http_response_code($code); - $this->respondToAJAX('{}'); - } - /** - * Destroy all registered information of a session and redirect to the login page. - */ - public function logoutAction() { - $this->layout = false; - php_sapi_name() !== 'cli' && session_destroy(); - $_SESSION = null; - unset($_SESSION); - header('Location: /index/login'); - } } \ No newline at end of file diff --git a/app/helpers/Menu_Helper.php b/app/helpers/Menu_Helper.php index 8bafe0b..fe023ca 100644 --- a/app/helpers/Menu_Helper.php +++ b/app/helpers/Menu_Helper.php @@ -32,7 +32,9 @@ public function __construct($link, $label, $items = [], $icon = '', $target = '_ function adminMenu() { return [ new menuEntry('/admin/index', 'Inicio', null, 'home'), - new menuEntry('/admin/users', 'Usuarios', null, 'user'), + new menuEntry('/admin/users', 'Usuarios', null, 'users'), + new menuEntry('/admin/translations', _('admin.menu.label.translations'), null, 'g_translate'), + new menuEntry('/admin/profile', _('admin.menu.label.profile'), null, 'profile'), new menuEntry('/index/logout?logout=1', 'Salir', null, 'exit') ]; } @@ -40,6 +42,7 @@ function adminMenu() { function generalMenu() { return [ new menuEntry('/index/index', 'Inicio', null, 'home'), + new menuEntry('/admin/users', 'Usuarios', null, 'user'), new menuEntry('/index/logout?logout=1', 'Salir', null, 'exit') ]; -} \ No newline at end of file +} diff --git a/app/models/project.php b/app/models/project.php new file mode 100644 index 0000000..2d34520 --- /dev/null +++ b/app/models/project.php @@ -0,0 +1,6 @@ +before_save = ['setDomain', 'sanitize', 'checkKeyID']; + $this->validate = [ + 'presence_of' => [ + ['field'=>'keyid','message'=>_('model.error.required.translation.key')], + ['field'=>'locale','message'=>_('model.error.required.translation.locale')] + ] + ]; + } + + public function setDomain() { + empty($this->domain) and ($this->domain = explode('.', $this->keyid)[0]); + } + + public function sanitize() { + $this->translation = htmlentities($this->translation, ENT_QUOTES, 'UTF-8', false); + } + + public function checkKeyID() { + $translation = new $this; + $translation->Find([ + 'first', + 'conditions' => [ + ['keyid', $this->keyid], + ['locale', $this->locale] + ] + ])->counter() and $this->_error->add(['field' => 'keyid', 'message' => _('model.error.duplicated.key')]); + } +} \ No newline at end of file diff --git a/app/models/user.php b/app/models/user.php index 4d58fa9..287fa52 100644 --- a/app/models/user.php +++ b/app/models/user.php @@ -38,6 +38,6 @@ public function encryptPassword() { public function login($user, $password) { $user = $this->Find_by_email($user); // will return 0 or the user id - return ($user->counter() === 1 and $user->password === sha1($password)) * $user->id; + return (int)($user->counter() === 1 and $user->password === sha1($password)) * (int)$user->id; } } diff --git a/app/views/admin/translation_addedit.phtml b/app/views/admin/translation_addedit.phtml new file mode 100644 index 0000000..0437ee2 --- /dev/null +++ b/app/views/admin/translation_addedit.phtml @@ -0,0 +1,33 @@ + + + + + + data->id)): ?> +

+ +

+ +
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+
+
\ No newline at end of file diff --git a/app/views/admin/translation_list.phtml b/app/views/admin/translation_list.phtml new file mode 100644 index 0000000..228b778 --- /dev/null +++ b/app/views/admin/translation_list.phtml @@ -0,0 +1,96 @@ + +
+
+

+
+
+ + + +
+
+ + + +
+
+ +
+
+
+ data->counter() > 0): ?> +
+ + : data->WillPaginate(); ?> + data->PaginateTotalPages;?> + +
+
+ + + + + + + + + + + + data as $row): ?> + + + + + + + + + +
locale;?>keyid;?>translation;?> + + + + + +
+
+
+
+ + : data->WillPaginate(); ?> + data->PaginateTotalPages;?> + +
+ +

+ +
+
+ + \ No newline at end of file diff --git a/app/views/admin/user_addedit.phtml b/app/views/admin/user_addedit.phtml new file mode 100644 index 0000000..e02db27 --- /dev/null +++ b/app/views/admin/user_addedit.phtml @@ -0,0 +1,64 @@ + + + + + + data->id)): ?> +

+ +

+ +
+ +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+ +
+ +
+
+ +
+
+
+
\ No newline at end of file diff --git a/app/views/admin/user_list.phtml b/app/views/admin/user_list.phtml new file mode 100644 index 0000000..8e3e98a --- /dev/null +++ b/app/views/admin/user_list.phtml @@ -0,0 +1,90 @@ + +
+
+

+
+
+
+
+ + + +
+
+ +
+
+
+ data->counter() > 0): ?> +
+ + : data->WillPaginate(); ?> + data->PaginateTotalPages;?> + +
+
+ + + + + + + + + + + + + data as $row): ?> + + + + + + + + + + +
firstname;?>lastname;?>email;?>status;?> + + + + + +
+
+
+
+ + : data->WillPaginate(); ?> + data->PaginateTotalPages;?> + +
+ +

+ +
+
+ + \ No newline at end of file diff --git a/app/views/admin/users.phtml b/app/views/admin/users.phtml deleted file mode 100644 index a8215c6..0000000 --- a/app/views/admin/users.phtml +++ /dev/null @@ -1,30 +0,0 @@ -
-
- - - - - - - - - - - - users as $row): ?> - - - - - - - - - -
idnamecreated_atActions
id;?>name;?>created_at;?> - delete - Edit -
-
- Add new... -
\ No newline at end of file diff --git a/app/views/index/login.phtml b/app/views/index/login.phtml index 3a6d4fe..17067be 100644 --- a/app/views/index/login.phtml +++ b/app/views/index/login.phtml @@ -9,7 +9,12 @@

Basilisk Project Management System

- + diff --git a/app/views/layout.phtml b/app/views/layout.phtml index 8978954..038a57e 100644 --- a/app/views/layout.phtml +++ b/app/views/layout.phtml @@ -6,21 +6,16 @@ -
-
- - Menu - -
-
-

-
-
+ + + +
+

+
yield;?> - diff --git a/app/webroot/css/styles.css b/app/webroot/css/styles.css index b340a57..348fa28 100644 --- a/app/webroot/css/styles.css +++ b/app/webroot/css/styles.css @@ -1398,16 +1398,219 @@ a:visited, a:active { background: var(--default); } -muy-button-action.main-add { +.site-logotype { + color: var(--primary); + font-family: 'MarketFresh', sans-serif; + text-align: left; + text-transform: uppercase; +} + +#page-content { + background-color: var(--secondary-hover); +} + +dmb-button-action.icon { + width: auto; +} + +dmb-button-action.icon:before { + align-items: center; + font-size: 1.2em; +} + +dmb-button-action.main-add { align-items: center; font-size: 1.2em; } -muy-button-action.main-add::before { +dmb-button-action.main-add::before { font-size: 1.2em; margin: 0 0.5em; } +dmb-card { + background-color: var(--primary-contrast); + border: none; + border-radius: 0.5em; + box-shadow: 0px 2px 1px -1px #00000099, 0px 1px 1px 0px #00000066, 0px 1px 3px 0px #00000055; + color: var(--primary); + float: left; + margin-bottom: 1em; + margin-right: 1em; + min-height: 12em; + padding: 0.5em; + position: relative; + width: 21em; + word-wrap: break-word; +} + +dmb-card .head { + border-bottom: solid 1px var(--default); + padding-bottom: 0.5em; +} + +dmb-card .head .header { + color: var(--primary); + font-weight: bold; + margin: 0; + padding: 0.5em; +} + +dmb-card .head h2 { + margin: 0; +} + +dmb-card .body { + margin-top: 0.5em; +} + +dmb-card .body .item { + margin-bottom: 0.5em; +} + +dmb-card .body .label { + color: var(--primary); +} + +dmb-card .body .content { + color: var(--primary); + font-weight: bold; + overflow-wrap: break-word; + text-align: right; + word-wrap: break-word; +} + +dmb-card.half-height { + min-height: 6em; +} + +dmb-card.icon { + padding-right: 4em; + position: relative; +} + +dmb-card.icon:before { + border-radius: 50%; + font-size: 3em; + padding: 10px; + position: absolute; + right: 0.1em; + top: 0.1em; +} + +dmb-card.icon .body .content { + font-size: 2em; + text-align: center; + width: 100%; +} + +dmb-card.icon .body .label { + font-size: smaller; +} + +dmb-card.border-start { + border-bottom: 0; + border-left: 4px; + border-right: 0; + border-top: 0; + border-style: solid; +} + +dmb-card.border-primary { + border-color: var(--primary); +} + +dmb-card.border-primary.icon:before { + background-color: var(--primary); + color: var(--primary-contrast); +} + +dmb-card.border-secondary { + border-color: var(--secondary); +} + +dmb-card.border-secondary.icon:before { + background-color: var(--secondary); + color: var(--secondary-contrast); +} + +dmb-card.border-default { + border-color: var(--default); +} + +dmb-card.border-default.icon:before { + background-color: var(--default); + color: var(--default-contrast); +} + +dmb-card.border-error { + border-color: var(--error); +} + +dmb-card.border-error.icon:before { + background-color: var(--error); + color: var(--error-contrast); +} + +dmb-card.border-success { + border-color: var(--success); +} + +dmb-card.border-success.icon:before { + background-color: var(--success); + color: var(--success-contrast); +} + +dmb-card.border-warning { + border-color: var(--warning); +} + +dmb-card.border-warning.icon:before { + background-color: var(--warning); + color: var(--warning-contrast); +} + +dmb-card.border-information { + border-color: var(--information); +} + +dmb-card.border-information.icon:before { + background-color: var(--information); + color: var(--information-contrast); +} + +dmb-card.small { + height: auto; + min-height: 3em; + width: 16em; +} + +dmb-card.full { + height: auto; + padding: 2em; + width: 100%; +} + +dmb-close-panel { + top: 0; +} + +dmb-close-panel .icon { + font-size: 2em; +} + +dmb-content { + top: 3em; +} + +dmb-header { + height: 3em; +} + +dmb-input input { + background-color: var(--primary-contrast); +} + dmb-login { display: block; margin: auto; @@ -1439,17 +1642,29 @@ dmb-login .site-logo svg { } dmb-menu-button { - top: 1em; - left: 1.5em; + display: block; + float: left; + height: 2em; + left: 0; + margin-right: 1em; + margin-top: 0.3em; + position: initial; + top: 0; + transform: translateX(50%); } dmb-menu-button .icon:before { font-size: 2em; } +.dmb-menu dmb-header { + background-color: var(--primary); + color: var(--primary-contrast); +} + .dmb-menu dmb-content { - background: var(--secondary); - color: var(--secondary-contrast); + background: var(--primary-contrast); + color: var(--primary); padding-left: 0; padding-right: 0; text-align: left; @@ -1457,7 +1672,7 @@ dmb-menu-button .icon:before { .dmb-menu dmb-content .item { box-sizing: border-box; - color: var(--secondary-contrast); + color: var(--primary); cursor: pointer; float: left; height: 4em; @@ -1467,11 +1682,11 @@ dmb-menu-button .icon:before { } .dmb-menu dmb-content .item * { - color: var(--secondary-contrast); + color: var(--primary); } .dmb-menu dmb-content .item *:before { - color: var(--secondary-contrast); + color: var(--primary); } .dmb-menu dmb-content .item .menu-label { @@ -1483,11 +1698,11 @@ dmb-menu-button .icon:before { } .dmb-menu dmb-content .item.selected, .dmb-menu dmb-content .item:hover { - background-color: var(--primary); + background-color: var(--secondary-hover); } .dmb-menu dmb-content .item:after { - background-color: var(--secondary-contrast); + background-color: var(--secondary); border: 0 none; bottom: 0; content: ' '; @@ -1502,6 +1717,21 @@ dmb-menu-button .icon:before { font-size: 2em; } +.dmb-menu dmb-content .item-main.icon:before { + font-size: 2.5em; + left: auto; + position: absolute; + right: 0.5em; +} + +.dmb-menu dmb-content .item-main ~ .submenu { + display: none; +} + +.dmb-menu dmb-content .item-main.actived ~ .submenu { + display: inline; +} + .dmb-menu dmb-content .item-secondary { padding: 1.5em 0 0 4em; } @@ -1517,6 +1747,60 @@ dmb-menu-button .legend { } } +dmb-more-option { + display: inline-block; + padding: 0.3em 0.5em; + border-bottom: solid 1px var(--default); + width: 100%; +} + +dmb-more-option:last-child { + border-bottom: none; +} + +dmb-more-option:hover { + color: var(--default); +} + +dmb-more-options { + color: var(--primary); + cursor: pointer; + display: inline-block; + position: relative; +} + +dmb-more-options .wrapper { + background-color: var(--secondary); + display: none; + padding: 0.2em 0.3em; + position: absolute; + right: 3em; +} + +dmb-more-options .wrapper.active { + display: inline-block; + z-index: 1; +} + +dmb-more-options .wrapper:after { + content: ''; + border: 1em solid var(--secondary); + border-right-color: transparent; + border-bottom-color: transparent; + height: 0; + margin-top: -1em; + margin-bottom: -1em; + margin-right: -3em; + position: absolute; + right: 1em; + top: 1em; + width: 0; +} + +dmb-more-options .wrapper dmb-more-option { + color: var(--secondary-contrast); +} + dmb-page-background { position: fixed; height: 100vh; @@ -1531,7 +1815,61 @@ dmb-page-background svg { width: 100%; } -.dmb-table { +dmb-pagination { + margin-bottom: 1em; + margin-top: 1em; + padding-bottom: 1em; + padding-top: 1em; +} + +dmb-pagination .paginate-page { + border: solid 1px var(--default-hover); + margin-left: -1px; + margin-right: 0; + padding: 0.375rem 0.75rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +dmb-pagination .paginate-page:hover:not(.paginate-page-active) { + background-color: var(--secondary-hover); +} + +dmb-pagination .paginate-page-active { + background-color: var(--primary); + border-color: var(--primary); + color: var(--primary-contrast); + cursor: default; +} + +dmb-search { + width: 100%; +} + +dmb-search dmb-input { + float: left; + margin-right: 1em; + width: calc(99% - 4em); +} + +dmb-search dmb-input label { + display: none; +} + +dmb-search dmb-input input { + height: 2.7em; +} + +.col dmb-search dmb-button.button { + float: left; + width: 3em; +} + +dmb-select select { + background-color: var(--primary-contrast); + color: var(--primary); +} + +dmb-table { clear: both; float: none; margin: auto; @@ -1540,8 +1878,8 @@ dmb-page-background svg { width: 100%; } -.dmb-table table { - border: solid 0.06em var(--secondary-hover); +dmb-table table { + border: solid 0.06em var(--secondary); border-radius: 0; border-spacing: 0; clear: both; @@ -1549,60 +1887,66 @@ dmb-page-background svg { width: 100%; } -.dmb-table table thead { - background-color: var(--primary); +dmb-table table thead { + background-color: transparent; border: solid 0.06em var(--secondary); } -.dmb-table table thead tr { - background-color: var(--primary-hover); +dmb-table table thead tr { + background-color: transparent; } -.dmb-table table thead tr:first-child { - background-color: var(--primary); +dmb-table table thead tr:first-child { + background-color: transparent; } -.dmb-table table thead tr th { - background-color: var(--primary); +dmb-table table thead tr th { + background-color: transparent; + border-right: 0.06em var(--secondary) dashed; border-radius: 0; margin: 0; padding: 0.5em; text-transform: uppercase; } -.dmb-table table tbody tr td { +dmb-table table thead tr th:last-child { + border-right: 0 none transparent; +} + +dmb-table table tbody tr td { border-right: 0.06em var(--secondary) dashed; + border-top: 0.06em var(--secondary) dashed; border-radius: 0; padding: 0.5em; margin: 0; text-align: center; } -.dmb-table table tbody tr td:last-child { +dmb-table table tbody tr td:last-child { border-right: 0 none transparent; } -.dmb-table table tbody tr td.truncated { +dmb-table table tbody tr td.truncated { overflow: hidden; text-overflow: ellipsis; width: 25em; white-space: nowrap; } -.dmb-table table tbody tr td.actions { +dmb-table table tbody tr td.actions { width: 2em; white-space: nowrap; } -.dmb-table table tbody tr:nth-child(odd) { +dmb-table table tbody tr:nth-child(odd) { background-color: var(--secondary-hover); } -.dmb-table table tbody tr:hover { - background-color: var(--success-hover); +dmb-table table tbody tr:hover { + background-color: var(--default-hover); } -.dmb-table table tfoot tr td { +dmb-table table tfoot tr td { background-color: var(--secondary-hover); border-radius: 0; padding-bottom: 0.6em; @@ -1610,7 +1954,7 @@ dmb-page-background svg { text-align: center; } -.dmb-table .table-button { +dmb-table .table-button { background-color: var(--primary); border: 1px solid var(--default-hover); border-radius: 0.2em; @@ -1620,13 +1964,13 @@ dmb-page-background svg { width: 2.2em; } -.dmb-table .table-button:before { +dmb-table .table-button:before { font-size: 1em; color: var(--secondary); width: 2em; } -.dmb-table .head-button { +dmb-table .head-button { background-color: var(--primary-contrast); border: 1px solid var(--default-hover); border-radius: 0.2em; @@ -1635,7 +1979,7 @@ dmb-page-background svg { padding: 0.2em; } -.dmb-table .head-button:before { +dmb-table .head-button:before { font-size: 1em; color: var(--secondary); } diff --git a/app/webroot/index.php b/app/webroot/index.php index a575870..3d07924 100644 --- a/app/webroot/index.php +++ b/app/webroot/index.php @@ -1,16 +1,20 @@ { - return response.json(); - }) - .then(() => { - window.location.reload(); - }) - .catch(error => { - window.dmbDialogService.closeAll(); - window.dmbDialogService.error(error); - }); - break; + case 'exec-form': + if(formToExec) { + form = document.querySelector(formToExec); + if(url) form.setAttribute('action', url); + if(target) form.setAttribute('target', target); + form.submit(); + } + break; + case 'open-panel': + panel = document.querySelector(this.getAttribute('panel')); + if(url) panel.setAttribute('source', url); + panel.open(); + break; + case 'launch-url': + location.href = url; + break; + case 'ajax': + if(pageLoader) pageLoader.open(); + fetch(new Request(url)) + .then(response => { + return response.json(); + }) + .then(() => { + window.location.reload(); + }) + .catch(error => { + window.dmbDialogService.closeAll(); + window.dmbDialogService.error(error); + }); + break; } } } customElements.define('dmb-button-action', DmbButtonAction); /** - * Component handle login - */ + * @dmbdoc directive + * @name DMB.directive:DmbCard + * + * @description + * This directive only will contains the data, the directive is set to add proper styles and further behaviors. + * + * @example + + */ +class DmbCard extends DumboDirective { + constructor() { + super(); + } +} + +customElements.define('dmb-card', DmbCard); +/** + * Component handle login + */ class DmbLogin extends DumboDirective { + #_form; + constructor() { super(); const template = ''; this.setTemplate(template); this.valids = []; - this.form = null; + this.#_form = null; } init() { const button = this.querySelector('dmb-button'); - this.form = this.querySelector('dmb-form'); - - this.form.setAttribute('action', `${this.getAttribute('target')}signin`); - button.click((e) => { - e.preventDefault(e); - this.loginClick(); - }); + const inputs = this.querySelectorAll('dmb-input'); + const target = this.getAttribute('target'); + //set dialog transparency + this.closest('dmb-view').style.backgroundColor = '#ffffff99'; + this.#_form = this.querySelector('dmb-form'); + inputs[0].setAttribute('label', this.getAttribute('user-label') || ''); + inputs[1].setAttribute('label', this.getAttribute('pass-label') || ''); + + this.#_form.setAttribute('action', `${target}signin`); + this.#_form.setAttribute('redirect', `${target}index`); + button.innerText = this.getAttribute('button-label') || ''; + this.#_form.callback = this.loginClick; } /** @@ -150,11 +190,25 @@ class DmbLogin extends DumboDirective { */ loginClick() { - const canSend = this.form.submit(); + const target = this.getAttribute('action'); + const redirect = this.getAttribute('redirect'); + const init = { + method: 'POST', + body: this.getFormData() + }; + const loginRequest = new Request(target, init); - if (canSend) { - this.handleLogin(this.getAttribute('target')); - } + fetch(loginRequest) + .then(response => { + if (!response.ok) throw new Error('Usuario o password incorrecto'); + return response.json(); + }) + .then(() => { + window.location = redirect; + }) + .catch(error => { + window.dmbDialogService.error(error); + }); } /** @@ -184,13 +238,215 @@ class DmbLogin extends DumboDirective { customElements.define('dmb-login', DmbLogin); /** - * + * @dmbdoc directive + * @name DMB.directive:DmbMoreOption + * + * @description + * Will render a DOM element for more option entry for an action + * + * @attribute behavior tells to the component how to perform the action. Valid options: open-panel, launch-url, ajax + * @attribute url URL to link or to load according the behavior + * @attribute panel (Optional) Query selector for the panel to open if the behavior is set to open-panel + * + * @example + + + */ +class DmbMoreOption extends DumboDirective { + constructor() { + super(); + this.url = ''; + this.pageLoader = null; + this.panel = null; + this.behavior = ''; + } + + init() { + this.behavior = this.getAttribute('behavior') || ''; + + if (!this.behavior.length) { + throw 'A behavior attribute must to be defined.'; + } + + this.url = this.getAttribute('url') || ''; + this.pageLoader = document.querySelector('#page-loader'); + this.panel = this.getAttribute('panel'); + + this.addEventListener('click', e => { + e.preventDefault(); + this.handleClick(); + }); + } + + handleClick() { + let panel = null; + switch (this.behavior) { + case 'open-panel': + panel = document.querySelector(this.panel); + if(this.url) panel.setAttribute('source', this.url); + panel.open(); + break; + case 'launch-url': + location.href = this.url; + break; + case 'ajax': + if(this.pageLoader) this.pageLoader.open(); + fetch(new Request(this.url)) + .then(response => { + if(this.pageLoader) this.pageLoader.close(); + return response.json(); + }) + .then((response) => { + window.dmbDialogService.closeAll(); + window.dmbDialogService.info(response.message); + setTimeout(() => { + location.reload(); + }, 1000); + }) + .catch(error => { + window.dmbDialogService.closeAll(); + window.dmbDialogService.error(error.message); + }); + break; + } + } +} + +customElements.define('dmb-more-option', DmbMoreOption); +/** + * @dmbdoc directive + * @name DMB.directive:DmbMoreOptions + * + * @description + * Wrapper handler for the group of muy-option items. Render an icon (three vertical points) and on click display the options. + * + * @example + + + + + + + */ +class DmbMoreOptions extends DumboDirective { + constructor() { + super(); + + const template = '
'; + this.setTemplate(template); + this.wrapper = null; + this.option = document.createElement('dmb-more-option'); + } + + init() { + this.wrapper = this.querySelector('.wrapper'); + this.classList.add('icon'); + this.classList.add('icon-more_vert'); + this.addEventListener('click', (e) => { + e.preventDefault(); + this.wrapper.classList.toggle('active'); + }); + + this.buildOptions(); + } + + setOptions(options) { + if (!Array.isArray(options)) { + throw 'Options must to be an array'; + } + this.options = options; + this.buildOptions(); + } + + buildOptions() { + let size = 0; + let i = 0; + let option = null; + + if (this.options && Array.isArray(this.options)) { + size = this.options.length; + for (i = 0; i < size; i++) { + option = this.option.cloneNode(); + option.innerHTML = this.options[i].text; + + if (this.options[i].behavior) option.setAttribute(this.options[i].behavior); + if (this.options[i].url) option.setAttribute(this.options[i].url); + if (this.options[i].panel) option.setAttribute(this.options[i].panel); + + this.wrapper.appendChild(option); + } + } + } +} + +customElements.define('dmb-more-options', DmbMoreOptions); +class MuySearch extends DumboDirective { + constructor () { + super(); + const template = '' + + '' + + '' + + ''; + this.setTemplate(template); + } + + init() { + let fields = ''; + let field = ''; + let input = null; + let newinput = null; + let form = null; + let i = 0; + let value = ''; + let id = null; + + if (!this.hasAttribute('fields')) throw new Error('Fields to include in search must be set.'); + fields = this.getAttribute('fields').trim(); + if (!fields.length) throw new Error('Fields to include in search must be set.'); + + form = this.querySelector('form'); + form.setAttribute('action', this.getAttribute('action')); + this.querySelector('dmb-input').setAttribute('label', this.getAttribute('label')); + value = this.getAttribute('dmb-value') || ''; + id = this.getAttribute('dmb-id') || null; + if(id) { + form.id = id; + } + + fields = fields.split(','); + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + this.querySelector('dmb-input input').value = value; + + while (!!(field = fields.shift())) { + newinput = input.cloneNode(); + newinput.setAttribute('name', `search[fields][${i}]`); + newinput.value = field; + form.prepend(newinput); + i++; + } + + } + +} +customElements.define('dmb-search', MuySearch); +/** + * */ class DmbSimpleForm extends DumboDirective { constructor () { super(); } - + init() { const form = this.querySelector('dmb-form'); const init = { diff --git a/app/webroot/js/specs.min.js b/app/webroot/js/specs.min.js index 2d0c6bf..514d0c3 100644 --- a/app/webroot/js/specs.min.js +++ b/app/webroot/js/specs.min.js @@ -1,3 +1,13 @@ +describe('DmbCard Directive', () => { + let element = null; + + element = document.createElement('dmb-card'); + document.body.append(element); + + it('Should render element', () => { + expect(element).toBeDefined(); + }); +}); describe('DmbLogin Directive', () => { let element = null; let inputs = null; diff --git a/app/webroot/libs/dmb-components.min.js b/app/webroot/libs/dmb-components.min.js index 9f5782a..b5d74ee 100644 --- a/app/webroot/libs/dmb-components.min.js +++ b/app/webroot/libs/dmb-components.min.js @@ -1 +1 @@ -class DmbForm extends DumboDirective{constructor(){super();this._valids=0;this.setTemplate('
');this.form=null}get valids(){return this._valids}init(){this.form=this.querySelector("form");this.form.setAttribute("method",this.getAttribute("method")||"POST");this.form.setAttribute("action",this.getAttribute("action")||"#");this.form.setAttribute("name",this.getAttribute("dmb-name")||"");this.form.setAttribute("id",this.getAttribute("dmb-id")||this.generateId());this.form.setAttribute("enctype",this.getAttribute("enctype")||"application/x-www-form-urlencoded");this.form.onSubmit=(e=>{e.preventDefault();return this.submit()})}reset(){this.form.reset()}validate(formElements,parentSelector){let item=null;let parent=null;let hasInvalids=false;while(item=formElements.shift()){if(item.closest(".novalidate")===null){parent=item.closest(parentSelector);parent.resetValidation();parent.setValidation();if(!item.hasAttribute("valid")&&!item.hasAttribute("hidden")){item.reportValidity();item.focus();hasInvalids=true}else{this._valids++}}}return!hasInvalids}submit(){const inputs=[...this.querySelectorAll("dmb-input[validate] input")];const selects=[...this.querySelectorAll("dmb-select[validate] select")];const textAreas=[...this.querySelectorAll("dmb-text-area[validate] textarea")];const isAsync=this.hasAttribute("async");let totalvalidations=0;this._valids=0;totalvalidations=this.validate(inputs,"dmb-input")+this.validate(selects,"dmb-select")+this.validate(textAreas,"dmb-text-area");if(totalvalidations===3){this.dispatchEvent(new Event("onsubmit"));if(isAsync){if(typeof this.callback==="function")this.callback()}else{this.form.submit()}return true}return false}getFormData(){return new FormData(this.form)}}customElements.define("dmb-form",DmbForm);class DmbHeader extends DumboDirective{constructor(){super()}init(){let titleDOM=null;if(this.title){titleDOM=document.createElement("h2");titleDOM.classList.add("dmb-header-title");titleDOM.textContent=this.title;this.prepend(titleDOM)}}}customElements.define("dmb-header",DmbHeader);class DmbSelect extends DumboDirective{static get observedAttributes(){return["valid","values","dmb-name","label","dmb-class","validate","dmb-value"]}constructor(){super();const template=""+"";this.setTemplate(template);this.validations={_required:value=>{let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error=""}return response}};this.isValid=false;this.valueList=[];this.validators=[];this._errorInputClass="_error"}set values(newValues=[]){this.valueList=newValues;this.buildOptions()}init(){const select=this.querySelector("select");let value=null;let options=null;let option=null;let opval=null;this.hasAttribute("label")&&(this.querySelector("label").innerText=this.getAttribute("label"));this.hasAttribute("label")&&select.setAttribute("aria-label",this.getAttribute("label")||"");this.hasAttribute("dmb-class")&&select.setAttribute("dmb-class",this.getAttribute("dmb-class")||"");select.setAttribute("name",this.getAttribute("dmb-name")||"");this.hasAttribute("validate")&&select.setAttribute("validate",this.getAttribute("validate"));select.id=this.getAttribute("dmb-id")||this.generateId();select.multiple=this.hasAttribute("multiple");if(this.hasAttribute("dmb-value")){value=this.getAttribute("dmb-value").trim();value=select.multiple?JSON.parse(value):value}if(select&&this.getAttribute("validate")){this.validators=this.buildValidators(select,this.getAttribute("validate"))}select.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});options=[...select.querySelectorAll("option")];if(options.length){while(option=options.shift()){option.value=(option.getAttribute("value")||"").trim();opval=isNaN(option.value)?option.value:parseInt(option.value);value=isNaN(value)?value:parseInt(value);if(!option.hasAttribute("selected")&&(opval&&opval==value)||Array.isArray(value)&&value.includes(opval)){option.setAttribute("selected",true);option.selected=true}}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let options=element.querySelectorAll("option");let content=[...options].filter(x=>x.selected).map(x=>x.value.trim()||"");let valid=true;let validator=null;let func=null;let result=null;!element.multiple&&(content=content[0]);for(var i=0,len=validators.length;i{const target=e.target;const classes=target.getAttribute("class");const form=document.querySelector(formTarget);if(/paginate-(\w+-)?page/gm.test(classes)){if(form){e.preventDefault();form.setAttribute("action",e.target.getAttribute("href"));form.submit()}}})}}customElements.define("dmb-pagination",DmbPagination);class DmbInfoPop extends DumboDirective{constructor(){super();const template='
';this.setTemplate(template)}init(){const size=this.getAttribute("size")||"small";this.querySelector(".float-content").classList.add(`float-content_${size}`)}}customElements.define("dmb-info-pop",DmbInfoPop);class DmbDialog extends DumboDirective{static get observedAttributes(){return["open"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){this.openValue=newValue!==null}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(new Event("close"));this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(new Event("close-dialog"));return true}open(){this.hasAttribute("open")||this.setAttribute("open","");this.dispatchEvent(new Event("open"))}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}init(){let delay=1e3*this.getAttribute("delay");this.hasAttribute("no-close")||this.setCloseButton();setTimeout(()=>{this.open()},delay)}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=this.querySelector(".close-modal-button");if(!icon||!icon.length){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")});this.querySelector(".wrapper").prepend(icon)}}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}info(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("info");msg=msg||"";this.classList.add("info");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-dialog",fn)}}}customElements.define("dmb-dialog",DmbDialog);class DmbMenuButton extends DumboDirective{constructor(){super();let template=''+'';this.setTemplate(template)}init(){this.addEventListener("click",()=>{let menu=this.getAttribute("menu");if(menu.length){document.querySelector(menu).showModal()}})}}customElements.define("dmb-menu-button",DmbMenuButton);class DmbFooter extends DumboDirective{constructor(){super()}init(){const dmbview=this.parentNode.querySelector("dmb-content");if(dmbview){dmbview.classList.add("padded-footer")}}}customElements.define("dmb-footer",DmbFooter);class DmbInput extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name","label"]}constructor(){super();const template=""+'';this.setTemplate(template);this.isValid=false;this._errorInputClass="_error";this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false}return response},_email:function(value){let response={valid:true,error:null},re=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;if(value&&!re.test(value)){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("input");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":this.buildValidators();break;case"label":if(input){this.querySelector("label").innerText=newValue;input.setAttribute("aria-label",newValue);input.setAttribute("placeholder",newValue)}break}}buildValidators(){let validators=[];let validatorList=(this.getAttribute("validate")||"").split(",");const input=this.querySelector("input");for(let i=0,len=validatorList.length;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};const type=element.getAttribute("type");let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;if(type!=="file")element.value=content;while(validator=validators.shift()){func=this.validations["_"+validator.key]||unknownValidator;result=func(content,validator.param);if(result.valid!==true){valid=false;break}}if(valid===true){element.parentNode.classList.remove(this._errorInputClass)}else{element.parentNode.classList.add(this._errorInputClass)}this.isValid=valid;valid?element.setAttribute("valid",""):element.removeAttribute("valid")}resetValidation(){let elements=this.getElementsByClassName(this._errorInputClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorInputClass)}}setValidation(){this._runValidators(this.querySelector("input"),this.buildValidators())}init(){const input=this.querySelector("input");const labelElement=this.querySelector("label");const label=this.getAttribute("label")||null;const masked=this.getAttribute("masked")||null;const autocomplete=this.getAttribute("autocomplete")||null;const classd=this.getAttribute("dmb-class")||null;const name=this.getAttribute("dmb-name")||null;const validate=this.getAttribute("validate")||null;const pattern=this.getAttribute("pattern")||null;const value=this.getAttribute("value")||null;const type=this.getAttribute("type")||"text";input.id=this.getAttribute("dmb-id")||this.generateId();input.setAttribute("type",type);if(label){this.querySelector("label").innerText=label;input.setAttribute("aria-label",label);input.setAttribute("placeholder",label)}if(labelElement){labelElement.setAttribute("for",input.id)}if(type==="checkbox"){this.insertBefore(input,labelElement)}if(masked)input.setAttribute("masked",masked);if(autocomplete)input.setAttribute("autocomplete",autocomplete);if(classd)input.setAttribute("class",classd);if(name)input.setAttribute("name",name);if(validate)input.setAttribute("validate",validate);if(pattern)input.setAttribute("pattern",pattern);if(value)input.value=value;type==="file"&&this.hasAttribute("accept")&&input.setAttribute("accept",this.getAttribute("accept"));const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};const maskInputAlpha=e=>{var char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{var char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}this.buildValidators();input.addEventListener("blur",()=>{this.setValidation()},true)}}customElements.define("dmb-input",DmbInput);class DmbImageUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbimgInput=this.querySelector('dmb-input[type="file"]');const imgInput=dmbimgInput.querySelector('input[type="file"]');const previewimg=this.querySelector(".preview img");previewimg.setAttribute("alt",this.getAttribute("img-alt")||"Image Preview");this.hasAttribute("validate")&&dmbimgInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbimgInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbimgInput.setAttribute("label",this.getAttribute("label"));imgInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])})}loadFile(file){const previewimg=this.querySelector(".preview img");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();previewimg.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-image-uploader",DmbImageUploader);class DmbToggle extends DumboDirective{static get observedAttributes(){return["value"]}constructor(){super();const template='';this.setTemplate(template);this.val=0}set value(val=0){this.val=val;this.setStatus()}get value(){return this.val}attributeChangedCallback(attr,oldValue,newValue){switch(attr){case"value":this.val=parseInt(newValue);this.setStatus();break}}init(){this.val=parseInt(this.getAttribute("value")||"0");this.setStatus();this.addEventListener("click",()=>{this.val=1*!this.val;this.setStatus()})}setStatus(){if(this.val===1){this.classList.add("on")}else{this.classList.remove("on")}}click(method){if(typeof method==="function"){this.addEventListener("click",method)}}}customElements.define("dmb-toggle",DmbToggle);class DmbClosePanel extends DumboDirective{constructor(){super();const template='';this.setTemplate(template)}init(){const orientation=this.getAttribute("orientation")||"right";const icon=this.querySelector("i.icon");let panel=null;this.classList.add(orientation);icon.classList.add(`icon-chevron-${orientation}`);this.addEventListener("click",()=>{panel=this.closest("dmb-panel");panel.close()})}}customElements.define("dmb-close-panel",DmbClosePanel);class DmbVideoUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbVideoInput=this.querySelector('dmb-input[type="file"]');const videoInput=dmbVideoInput.querySelector('input[type="file"]');const willPreview=this.hasAttribute("preview")&&!!this.getAttribute("preview").length;this.hasAttribute("validate")&&dmbVideoInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbVideoInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbVideoInput.setAttribute("label",this.getAttribute("label"));willPreview&&videoInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])});willPreview||this.querySelector(".preview video").remove()}loadFile(file){const videoComponent=this.querySelector(".preview video");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();videoComponent.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-video-uploader",DmbVideoUploader);class DmbPanel extends DumboDirective{static get observedAttributes(){return["source"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){!!newValue&&newValue.length&&this.loadExternalSource()}loadExternalSource(){const url=this.getAttribute("source");let wrapper=null;let sourceRequest=null;if(url&&url.length){sourceRequest=new Request(url);fetch(sourceRequest).then(res=>res.text()).then(data=>{wrapper=this.querySelector(".wrapper");wrapper.innerHTML=data})}return true}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(new Event("close"));this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(new Event("close-dialog"))}open(){this.setAttribute("open","");this.dispatchEvent(new Event("open"));this.addEventListener("click",e=>{if(this.openValue&&e.target===this){this.close("cancelled")}},true)}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")});this.querySelector(".wrapper").prepend(icon)}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");message.textContent=msg;wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");message.textContent=msg;wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-panel",fn)}}init(){!this.classList.contains("right")&&!this.classList.contains("left")&&this.classList.add("right");!this.classList.contains("small")&&!this.classList.contains("large")&&this.classList.add("small");this.addEventListener("click",e=>{e.target===this&&this.close("cancelled")},true);this.loadExternalSource()}}customElements.define("dmb-panel",DmbPanel);class DmbTextArea extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name"]}constructor(){super();const template=""+"";this.setTemplate(template);this.isValid=false;this.validators=[];this._errorInputClass="_error";this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("textarea");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(input)input.setAttribute("name",newValue);break;case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":if(input)input.setAttribute("validate",newValue);break}}init(){let input=this.getElementsByTagName("textarea").item(0);this.querySelector("label").innerText=this.getAttribute("label");input.setAttribute("aria-label",this.getAttribute("label")||"");input.setAttribute("masked",this.getAttribute("masked")||"");input.setAttribute("autocomplete",this.getAttribute("autocomplete")||"");input.setAttribute("class",this.getAttribute("dmb-class")||"");input.setAttribute("name",this.getAttribute("dmb-name")||"");input.setAttribute("validate",this.getAttribute("validate")||"");input.setAttribute("placeholder",this.getAttribute("placeholder")||"");input.setAttribute("valid","true");input.id=this.getAttribute("dmb-id")||this.generateId();const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};if(input&&this.getAttribute("validate")){this.validators=this.buildValidators(input,this)}input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});const maskInputAlpha=e=>{var char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{var char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("validate")){this.validators=this.buildValidators(input,this);input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},true)}if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;element.value=content;for(var i=0,len=validators.length;i'+'H2'+'H3'+'H4'+'H5'+'H6'+''+''+''+''+''+''+''+''+''+'
'+''+'
'+"
"+'
'+''+'
'+"
"+'Source'+''+""+''+'
'+"
"+''+"";this.setTemplate(template);this.isValid=false;this._errorWysiwygClass="v_error";this.colorPalette=["000000","FF9966","6699FF","99FF66","CC0000","00CC00","0000CC","333333","0066FF","FFFFFF"];this.toolbarElements=[];this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error="Este campo es obligatorio"}return response}}}init(){const forePalette=this.querySelector(".palette .fore-palette");const backPalette=this.querySelector(".back-palette .fore-palette");let hideButtons=null;let showButtons=null;let executeCommand=null;let a=document.createElement("a");let ap=document.createElement("a");let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");this.toolbarElements=this.querySelectorAll(".dmb-wysiwyg__toolbar-button");a.dataset.command="foreColor";ap.dataset.command="backColor";a.setAttribute("href","#");ap.setAttribute("href","#");a.classList.add("palette-item");ap.classList.add("palette-item");a.classList.add("dmb-wysiwyg__toolbar-button");ap.classList.add("dmb-wysiwyg__toolbar-button");for(let i=0;i{for(let j=0;j{for(let j=0;j{const me=e.target;let command=me.dataset.command;let value=me.dataset.value;let url;let textArea;let editArea;e.stopImmediatePropagation();e.stopPropagation();e.preventDefault();switch(command){case"h2":case"h3":case"h4":case"h5":case"h6":case"p":document.execCommand("formatBlock",true,command);break;case"foreColor":case"backColor":document.execCommand(command,true,value);break;case"createlink":case"insertimage":url=prompt("Enter the link here: ","");if(url&&url.length){document.execCommand(command,false,url)}break;case"source":hideButtons(this.toolbarElements);me.parentNode.querySelector(".normal-button").style.display="flex";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");textArea.value=editArea.innerHTML;textArea.setAttribute("hidden",false);textArea.removeAttribute("hidden");editArea.setAttribute("hidden",true);break;case"normal":showButtons(this.toolbarElements);me.style.display="none";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");editArea.innerHTML=textArea.value;editArea.setAttribute("hidden",false);editArea.removeAttribute("hidden");textArea.setAttribute("hidden",true);break;default:document.execCommand(command,false,null);break}});for(let i=0;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=(element.value||element.innerHTML).trim();let valid=true;let validator=null;let func=null;let result=null;let message=null;for(let i=0,len=validators.length;i{this._runValidators(textarea,validators)},true);editarea.addEventListener("blur",()=>{this._runValidators(editarea,validators)},true);document.body.addEventListener(window.dmbEventsService.validate.listener,()=>{this._runValidators(textarea,validators);this._runValidators(editarea,validators)},true);document.body.addEventListener(window.dmbEventsService.resetValidation.listener,()=>{let elements=this.getElementsByClassName(this._errorWysiwygClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorWysiwygClass)}},true)}syncData(){let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");let editArea=this.querySelector("section.dmb-wysiwyg__content-content");if(textArea.hasAttribute("hidden")){textArea.value=editArea.innerHTML}else{editArea.innerHTML=textArea.value}}attributeChangedCallback(attr,oldValue,newValue){const textarea=this.querySelector("textarea.dmb-wysiwyg__content-content");const editarea=this.querySelector("section.dmb-wysiwyg__content-content");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(textarea)textarea.setAttribute("name",newValue);break;case"dmb-name":if(textarea)textarea.setAttribute("name",newValue);break;case"validate":if(textarea){textarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}if(editarea){editarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}break}}}customElements.define("dmb-wysiwyg",DmbWysiwyg);class DmbPageLoader extends DumboDirective{constructor(){super();window.addEventListener("beforeunload",()=>{this.classList.add("active")});document.addEventListener("readystatechange",()=>setTimeout(()=>{document.readyState==="complete"&&this.classList.contains("active")&&this.close()},100));document.addEventListener("DOMContentLoaded",()=>setTimeout(()=>{this.classList.contains("active")&&this.close()},100));window.addEventListener(window.dmbEventsService.pageLoaderClose.listener,()=>this.close());window.addEventListener("load",()=>this.close())}open(){!this.classList.contains("active")&&this.classList.add("active");return true}close(){this.classList.contains("active")&&this.classList.remove("active");return true}}customElements.define("dmb-page-loader",DmbPageLoader);class DmbContent extends DumboDirective{constructor(){super()}}customElements.define("dmb-content",DmbContent);class DmbView extends DumboDirective{constructor(){super()}}customElements.define("dmb-view",DmbView); \ No newline at end of file +class DmbForm extends DumboDirective{constructor(){super();this._valids=0;this.setTemplate('
');this.form=null;this.callback=this.callback||null}get valids(){return this._valids}init(){let inputs=null;let item=null;this.form=this.querySelector("form");this.form.setAttribute("method",this.getAttribute("method")||"POST");this.form.setAttribute("action",this.getAttribute("action")||"#");this.form.setAttribute("autocomplete",this.getAttribute("autocomplete")||"on");this.form.setAttribute("name",this.getAttribute("dmb-name")||"");this.form.setAttribute("target",this.getAttribute("target")||"");this.form.setAttribute("id",this.getAttribute("dmb-id")||this.generateId());this.form.setAttribute("enctype",this.getAttribute("enctype")||"application/x-www-form-urlencoded");inputs=[...this.querySelectorAll('input:not([type="submit"])')];if(this.querySelector('input[type="submit"]')===null||inputs.length>1){while(item=inputs.shift()){item.addEventListener("keypress",e=>{if(13===e.keyCode){this.submit()}})}}}reset(){this.form.reset()}validate(formElements,parentSelector){let item=null;let hasInvalids=false;formElements.forEach(element=>{element.closest(parentSelector).resetValidation()});this.dispatchEvent(window.DmbEvents.formBeforeValidate.event);while(item=formElements.shift()){if(item.closest(".novalidate")===null){item.closest(parentSelector).setValidation();if(!item.hasAttribute("valid")&&!item.hasAttribute("hidden")){item.reportValidity();item.focus();hasInvalids=true}else{this._valids++}}}this.dispatchEvent(window.DmbEvents.formAfterValidate.event);return!hasInvalids}submit(){this.dispatchEvent(window.DmbEvents.formSubmit.event);const inputs=[...this.querySelectorAll("dmb-input[validate] input")];const selects=[...this.querySelectorAll("dmb-select[validate] select")];const textAreas=[...this.querySelectorAll("dmb-text-area[validate] textarea")];const isAsync=this.hasAttribute("async");const form=this.querySelector("form");let totalvalidations=0;this._valids=0;totalvalidations=this.validate(inputs,"dmb-input")+this.validate(selects,"dmb-select")+this.validate(textAreas,"dmb-text-area");if(totalvalidations===3){if(isAsync){if(typeof this.callback==="function"){this.callback(this)}return false}else{form.submit()}return true}return false}getFormData(){return new FormData(this.form)}}customElements.define("dmb-form",DmbForm);class DmbHeader extends DumboDirective{constructor(){super()}init(){let titleDOM=null;if(this.title){titleDOM=document.createElement("h2");titleDOM.classList.add("dmb-header-title");titleDOM.textContent=this.title;this.prepend(titleDOM)}}}customElements.define("dmb-header",DmbHeader);class DmbSelect extends DumboDirective{static get observedAttributes(){return["valid","values","dmb-name","label","dmb-class","validate","dmb-value"]}constructor(){super();const template=""+"";this.setTemplate(template);this.validations={_required:value=>{let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error=""}return response}};this.isValid=false;this.valueList=[];this.validators=[];this._errorInputClass="_error"}set values(newValues=[]){this.valueList=newValues;this.buildOptions()}init(){const select=this.querySelector("select");let value=null;let options=null;let option=null;let opval=null;this.hasAttribute("label")&&(this.querySelector("label").innerText=this.getAttribute("label"));this.hasAttribute("label")&&select.setAttribute("aria-label",this.getAttribute("label"));this.hasAttribute("dmb-class")&&select.setAttribute("class",this.getAttribute("dmb-class"));select.setAttribute("name",this.getAttribute("dmb-name")||"");this.hasAttribute("validate")&&select.setAttribute("validate",this.getAttribute("validate"));select.id=this.getAttribute("dmb-id")||this.generateId();select.multiple=this.hasAttribute("multiple");if(this.hasAttribute("dmb-value")){value=this.getAttribute("dmb-value").trim();value=select.multiple?JSON.parse(value):value}if(select&&this.getAttribute("validate")){this.validators=this.buildValidators(select,this.getAttribute("validate"))}select.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});options=[...select.querySelectorAll("option")];if(options.length){while(option=options.shift()){option.value=(option.getAttribute("value")||"").trim();opval=isNaN(option.value)?option.value:parseInt(option.value);value=isNaN(value)?value:parseInt(value);if(!option.hasAttribute("selected")&&(opval&&opval==value)||Array.isArray(value)&&value.includes(opval)){option.setAttribute("selected",true);option.selected=true}}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let options=element.querySelectorAll("option");let content=[...options].filter(x=>x.selected).map(x=>x.value.trim()||"");let valid=true;let validator=null;let func=null;let result=null;!element.multiple&&(content=content[0]);for(var i=0,len=validators.length;i{const target=e.target;const classes=target.getAttribute("class");if(formTarget){form=document.querySelector(formTarget)}if(/paginate-page(-\w+)?/gm.test(classes)){if(form){e.preventDefault();form.setAttribute("action",e.target.getAttribute("href"));form.submit()}}})}}customElements.define("dmb-pagination",DmbPagination);class DmbInfoPop extends DumboDirective{constructor(){super();const template='
';this.setTemplate(template)}init(){const size=this.getAttribute("size")||"small";this.querySelector(".float-content").classList.add(`float-content_${size}`)}}customElements.define("dmb-info-pop",DmbInfoPop);class DmbDialog extends DumboDirective{static get observedAttributes(){return["open"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){this.openValue=newValue!==null}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(new Event("close"));this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(new Event("close-dialog"));return true}open(){this.hasAttribute("open")||this.setAttribute("open","");this.dispatchEvent(window.DmbEvents.dialogOpen.event)}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}init(){let delay=1e3*this.getAttribute("delay");this.hasAttribute("no-close")||this.setCloseButton();setTimeout(()=>{this.open()},delay)}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=this.querySelector(".close-modal-button");if(!icon||!icon.length){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");this.querySelector(".wrapper").prepend(icon);icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")})}}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}info(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("info");msg=msg||"";this.classList.add("info");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-dialog",fn)}}}customElements.define("dmb-dialog",DmbDialog);class DmbMenuButton extends DumboDirective{constructor(){super();let template=''+'';this.setTemplate(template)}init(){this.addEventListener("click",()=>{let menu=this.getAttribute("menu");if(menu.length){document.querySelector(menu).showModal()}})}}customElements.define("dmb-menu-button",DmbMenuButton);class DmbFooter extends DumboDirective{constructor(){super()}init(){const dmbview=this.parentNode.querySelector("dmb-content");if(dmbview){dmbview.classList.add("padded-footer")}}}customElements.define("dmb-footer",DmbFooter);class DmbInput extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name","label"]}constructor(){super();const template=""+'';this.setTemplate(template);this.isValid=false;this._errorInputClass="_error";this.validations={_required:function(value,param,input){let response={valid:true,error:null};param=null;if(typeof value==="undefined"||value===null||value===""||input.getAttribute("type")==="checkbox"&&!input.checked){response.valid=false}return response},_email:function(value){let response={valid:true,error:null},re=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;if(value&&!re.test(value)){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}set value(val){const input=this.querySelector("input");input.value=val}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("input");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":this.buildValidators();break;case"label":if(input){this.querySelector("label").innerText=newValue;input.setAttribute("aria-label",newValue);input.setAttribute("placeholder",newValue)}break}}buildValidators(){let validators=[];let validatorList=(this.getAttribute("validate")||"").split(",");const input=this.querySelector("input");for(let i=0,len=validatorList.length;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};const type=element.getAttribute("type");let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;if(type!=="file")element.value=content;while(validator=validators.shift()){func=this.validations["_"+validator.key]||unknownValidator;result=func(content,validator.param,validator.input);if(result.valid!==true){valid=false;break}}if(valid===true){element.parentNode.classList.remove(this._errorInputClass)}else{element.parentNode.classList.add(this._errorInputClass)}this.isValid=valid;valid?element.setAttribute("valid",""):element.removeAttribute("valid")}resetValidation(){let elements=this.getElementsByClassName(this._errorInputClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorInputClass)}}setValidation(){this._runValidators(this.querySelector("input"),this.buildValidators())}init(){const input=this.querySelector("input");const labelElement=this.querySelector("label");const label=this.getAttribute("label")||null;const placeholder=this.getAttribute("placeholder")||label;const masked=this.getAttribute("masked")||null;const autocomplete=this.getAttribute("autocomplete")||null;const classd=this.getAttribute("dmb-class")||null;const name=this.getAttribute("dmb-name")||null;const validate=this.getAttribute("validate")||null;const pattern=this.getAttribute("pattern")||null;const value=this.getAttribute("value")||this.getAttribute("dmb-value")||null;const step=this.getAttribute("step")||null;const type=this.getAttribute("type")||"text";const checked=this.hasAttribute("checked");input.id=this.getAttribute("dmb-id")||this.generateId();input.setAttribute("type",type);if(label){this.querySelector("label").innerText=label;input.setAttribute("aria-label",label)}if(placeholder){input.setAttribute("placeholder",placeholder)}if(labelElement){labelElement.setAttribute("for",input.id)}if(type==="checkbox"){this.insertBefore(input,labelElement);if(checked){input.setAttribute("checked","on")}}if(masked)input.setAttribute("masked",masked);if(autocomplete)input.setAttribute("autocomplete",autocomplete);if(classd)input.setAttribute("class",classd);if(name)input.setAttribute("name",name);if(validate)input.setAttribute("validate",validate);if(pattern)input.setAttribute("pattern",pattern);if(value)input.value=value;if(step)input.setAttribute("step",step);type==="file"&&this.hasAttribute("accept")&&input.setAttribute("accept",this.getAttribute("accept"));const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};const maskInputAlpha=e=>{const char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{const char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}this.buildValidators();input.addEventListener("blur",()=>{this.setValidation()},true)}}customElements.define("dmb-input",DmbInput);class DmbImageUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbimgInput=this.querySelector('dmb-input[type="file"]');const imgInput=dmbimgInput.querySelector('input[type="file"]');const previewimg=this.querySelector(".preview img");previewimg.setAttribute("alt",this.getAttribute("img-alt")||"Image Preview");this.hasAttribute("validate")&&dmbimgInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbimgInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbimgInput.setAttribute("label",this.getAttribute("label"));imgInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])})}loadFile(file){const previewimg=this.querySelector(".preview img");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();previewimg.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-image-uploader",DmbImageUploader);class DmbToggle extends DumboDirective{static get observedAttributes(){return["value"]}constructor(){super();const template='';this.setTemplate(template);this.val=0}set value(val=0){this.val=val;this.setStatus()}get value(){return this.val}attributeChangedCallback(attr,oldValue,newValue){switch(attr){case"value":this.val=parseInt(newValue);this.setStatus();break}}init(){this.val=parseInt(this.getAttribute("value")||"0");this.setStatus();this.addEventListener("click",()=>{this.val=1*!this.val;this.setStatus()})}setStatus(){if(this.val===1){this.classList.add("on")}else{this.classList.remove("on")}}click(method){if(typeof method==="function"){this.addEventListener("click",method)}}}customElements.define("dmb-toggle",DmbToggle);class DmbClosePanel extends DumboDirective{constructor(){super();const template='';this.setTemplate(template)}init(){const orientation=this.getAttribute("orientation")||"right";const icon=this.querySelector("i.icon");let panel=null;this.classList.add(orientation);icon.classList.add(`icon-chevron-${orientation}`);this.addEventListener("click",()=>{panel=this.closest("dmb-panel");panel.close()})}}customElements.define("dmb-close-panel",DmbClosePanel);class DmbVideoUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbVideoInput=this.querySelector('dmb-input[type="file"]');const videoInput=dmbVideoInput.querySelector('input[type="file"]');const willPreview=this.hasAttribute("preview")&&!!this.getAttribute("preview").length;this.hasAttribute("validate")&&dmbVideoInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbVideoInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbVideoInput.setAttribute("label",this.getAttribute("label"));willPreview&&videoInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])});willPreview||this.querySelector(".preview video").remove()}loadFile(file){const videoComponent=this.querySelector(".preview video");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();videoComponent.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-video-uploader",DmbVideoUploader);class DmbPanel extends DumboDirective{static get observedAttributes(){return["source"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){!!newValue&&newValue.length&&this.loadExternalSource()}loadExternalSource(){const url=this.getAttribute("source");let wrapper=null;let sourceRequest=null;if(url&&url.length){sourceRequest=new Request(url);fetch(sourceRequest).then(res=>res.text()).then(data=>{wrapper=this.querySelector(".wrapper");wrapper.innerHTML=data})}return true}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(window.DmbEvents.panelClose.event);this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(window.DmbEvents.dialogClose.event)}open(){this.setAttribute("open","");this.dispatchEvent(window.DmbEvents.panelOpened.event);this.addEventListener("click",e=>{if(this.openValue&&e.target===this){this.close("cancelled")}},true)}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")});this.querySelector(".wrapper").prepend(icon)}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");message.textContent=msg;wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");message.textContent=msg;wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-panel",fn)}}init(){!this.classList.contains("right")&&!this.classList.contains("left")&&this.classList.add("right");!this.classList.contains("small")&&!this.classList.contains("large")&&this.classList.add("small");this.addEventListener("click",e=>{e.target===this&&this.close("cancelled")},true);this.loadExternalSource()}}customElements.define("dmb-panel",DmbPanel);class DmbTextArea extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name"]}constructor(){super();const template=""+"";this.setTemplate(template);this.isValid=false;this.validators=[];this._errorInputClass="_error";this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("textarea");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(input)input.setAttribute("name",newValue);break;case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":if(input)input.setAttribute("validate",newValue);break}}init(){let input=this.getElementsByTagName("textarea").item(0);this.querySelector("label").innerText=this.getAttribute("label");input.setAttribute("aria-label",this.getAttribute("label")||"");input.setAttribute("masked",this.getAttribute("masked")||"");input.setAttribute("autocomplete",this.getAttribute("autocomplete")||"");input.setAttribute("class",this.getAttribute("dmb-class")||"");input.setAttribute("name",this.getAttribute("dmb-name")||"");input.setAttribute("validate",this.getAttribute("validate")||"");input.setAttribute("placeholder",this.getAttribute("placeholder")||"");input.setAttribute("valid","true");input.id=this.getAttribute("dmb-id")||this.generateId();const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};if(input&&this.getAttribute("validate")){this.validators=this.buildValidators(input,this)}input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});const maskInputAlpha=e=>{let char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{let char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("validate")){this.validators=this.buildValidators(input,this);input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},true)}if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;element.value=content;for(var i=0,len=validators.length;i'+'H2'+'H3'+'H4'+'H5'+'H6'+''+''+''+''+''+''+''+''+''+'
'+''+'
'+"
"+'
'+''+'
'+"
"+'Source'+''+""+''+'
'+"
"+''+"";this.setTemplate(template);this.isValid=false;this._errorWysiwygClass="v_error";this.colorPalette=["000000","FF9966","6699FF","99FF66","CC0000","00CC00","0000CC","333333","0066FF","FFFFFF"];this.toolbarElements=[];this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error="Este campo es obligatorio"}return response}}}init(){const forePalette=this.querySelector(".palette .fore-palette");const backPalette=this.querySelector(".back-palette .fore-palette");let hideButtons=null;let showButtons=null;let executeCommand=null;let a=document.createElement("a");let ap=document.createElement("a");let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");this.toolbarElements=this.querySelectorAll(".dmb-wysiwyg__toolbar-button");a.dataset.command="foreColor";ap.dataset.command="backColor";a.setAttribute("href","#");ap.setAttribute("href","#");a.classList.add("palette-item");ap.classList.add("palette-item");a.classList.add("dmb-wysiwyg__toolbar-button");ap.classList.add("dmb-wysiwyg__toolbar-button");for(let i=0;i{for(let j=0;j{for(let j=0;j{const me=e.target;let command=me.dataset.command;let value=me.dataset.value;let url;let textArea;let editArea;e.stopImmediatePropagation();e.stopPropagation();e.preventDefault();switch(command){case"h2":case"h3":case"h4":case"h5":case"h6":case"p":document.execCommand("formatBlock",true,command);break;case"foreColor":case"backColor":document.execCommand(command,true,value);break;case"createlink":case"insertimage":url=prompt("Enter the link here: ","");if(url&&url.length){document.execCommand(command,false,url)}break;case"source":hideButtons(this.toolbarElements);me.parentNode.querySelector(".normal-button").style.display="flex";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");textArea.value=editArea.innerHTML;textArea.setAttribute("hidden",false);textArea.removeAttribute("hidden");editArea.setAttribute("hidden",true);break;case"normal":showButtons(this.toolbarElements);me.style.display="none";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");editArea.innerHTML=textArea.value;editArea.setAttribute("hidden",false);editArea.removeAttribute("hidden");textArea.setAttribute("hidden",true);break;default:document.execCommand(command,false,null);break}});for(let i=0;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=(element.value||element.innerHTML).trim();let valid=true;let validator=null;let func=null;let result=null;let message=null;for(let i=0,len=validators.length;i{this._runValidators(textarea,validators)},true);editarea.addEventListener("blur",()=>{this._runValidators(editarea,validators)},true);document.body.addEventListener(window.DmbEvents.validate.listener,()=>{this._runValidators(textarea,validators);this._runValidators(editarea,validators)},true);document.body.addEventListener(window.DmbEvents.resetValidation.listener,()=>{let elements=this.getElementsByClassName(this._errorWysiwygClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorWysiwygClass)}},true)}syncData(){let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");let editArea=this.querySelector("section.dmb-wysiwyg__content-content");if(textArea.hasAttribute("hidden")){textArea.value=editArea.innerHTML}else{editArea.innerHTML=textArea.value}}attributeChangedCallback(attr,oldValue,newValue){const textarea=this.querySelector("textarea.dmb-wysiwyg__content-content");const editarea=this.querySelector("section.dmb-wysiwyg__content-content");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(textarea)textarea.setAttribute("name",newValue);break;case"dmb-name":if(textarea)textarea.setAttribute("name",newValue);break;case"validate":if(textarea){textarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}if(editarea){editarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}break}}}customElements.define("dmb-wysiwyg",DmbWysiwyg);class DmbPageLoader extends DumboDirective{constructor(){super();window.addEventListener("beforeunload",()=>{this.classList.add("active")});document.addEventListener("readystatechange",()=>setTimeout(()=>{document.readyState==="complete"&&this.classList.contains("active")&&this.close()},100));document.addEventListener("DOMContentLoaded",()=>setTimeout(()=>{this.classList.contains("active")&&this.close()},100));window.addEventListener(window.DmbEvents.pageLoaderClose.listener,()=>this.close());window.addEventListener("load",()=>this.close())}open(){!this.classList.contains("active")&&this.classList.add("active");return true}close(){this.classList.contains("active")&&this.classList.remove("active");return true}}customElements.define("dmb-page-loader",DmbPageLoader);class DmbContent extends DumboDirective{constructor(){super()}}customElements.define("dmb-content",DmbContent);class DmbView extends DumboDirective{constructor(){super()}}customElements.define("dmb-view",DmbView); \ No newline at end of file diff --git a/app/webroot/libs/dmb-factories.min.js b/app/webroot/libs/dmb-factories.min.js index c0713a0..c0d3bbd 100644 --- a/app/webroot/libs/dmb-factories.min.js +++ b/app/webroot/libs/dmb-factories.min.js @@ -1 +1 @@ -Window.prototype.dmbEventsService={panelClose:{event:new Event("dmb-panel.close"),listener:"dmb-panel.close"},panelOpen:{event:new Event("dmb-panel.open"),listener:"dmb-panel.open"},panelClosed:{event:new Event("dmb-panel.closed"),listener:"dmb-panel.closed"},panelOpened:{event:new Event("dmb-panel.opened"),listener:"dmb-panel.opened"},resetValidation:{event:new Event("dmb-validation.reset"),listener:"dmb-validation.reset"},validate:{event:new Event("dmb-validation.validate"),listener:"dmb-validation.validate"},pageLoaderClose:{event:new Event("dmb-page-loader.close"),listener:"dmb-page-loader.close"}};class DmbDialogService{setMessage(e,n){const d=document.createElement("span");return d.classList.add("message"),d.textContent=n,e.append(d),!0}open(){const e=document.createElement("dmb-dialog",{is:"dmb-dialog"});return document.body.append(e),e.showModal(),e}error(e){const n=document.createElement("dmb-dialog");return document.body.append(n),n.error(e),n.showModal(),n}info(e){const n=document.createElement("dmb-dialog");return document.body.append(n),n.info(e),n.showModal(),n}loader(){const e=document.createElement("dmb-dialog",{is:"dmb-dialog"});return e.classList.add("loader"),document.body.append(e),e.showModal(),e}drawer(e,n="small"){const d=document.createElement("dmb-dialog",{is:"dmb-dialog"});return d.classList.add("drawer"),d.classList.add(n),document.body.append(d),"string"==typeof e?d.querySelector(".wrapper").innerHTML=e:d.querySelector(".wrapper").append(e),d.setCloseButton(),d.showModal(),d}closeAll(){const e=document.querySelectorAll("dmb-dialog"),n=e.length;if(n)for(let d=0;d diff --git a/locale/en_US.utf8/LC_MESSAGES/translations.mo b/locale/en_US.utf8/LC_MESSAGES/translations.mo new file mode 100644 index 0000000..1d1a3ba Binary files /dev/null and b/locale/en_US.utf8/LC_MESSAGES/translations.mo differ diff --git a/locale/es_CO.utf8/LC_MESSAGES/translations.mo b/locale/es_CO.utf8/LC_MESSAGES/translations.mo new file mode 100644 index 0000000..4653c2d Binary files /dev/null and b/locale/es_CO.utf8/LC_MESSAGES/translations.mo differ diff --git a/locale/es_MX.utf8/LC_MESSAGES/translations.mo b/locale/es_MX.utf8/LC_MESSAGES/translations.mo new file mode 100644 index 0000000..4653c2d Binary files /dev/null and b/locale/es_MX.utf8/LC_MESSAGES/translations.mo differ diff --git a/locale/pt_BR.utf8/LC_MESSAGES/translations.mo b/locale/pt_BR.utf8/LC_MESSAGES/translations.mo new file mode 100644 index 0000000..815b828 Binary files /dev/null and b/locale/pt_BR.utf8/LC_MESSAGES/translations.mo differ diff --git a/migrations/create_attachments.php b/migrations/create_attachments.php index 8388c88..09c7d33 100644 --- a/migrations/create_attachments.php +++ b/migrations/create_attachments.php @@ -2,13 +2,13 @@ class CreateAttachment extends Migrations { function _init_() { $this->_fields = [ - ['field'=>'id', 'type'=>'INTEGER(11) AUTO_INCREMENT PRIMARY KEY', 'null'=>'false'], - ['field'=>'issue_id', 'type'=>'INT', 'null'=>'false', 'limit'=>'11'], + ['field' => 'id', 'type' => 'INTEGER', 'autoincrement' => true, 'primary' => true], + ['field'=>'issue_id', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'], ['field'=>'type', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'50'], ['field'=>'path', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'255'], ['field'=>'name', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'150'], - ['field'=>'created_at', 'type'=>'INT', 'null'=>'false', 'limit'=>'11'], - ['field'=>'updated_at', 'type'=>'INT', 'null'=>'false', 'limit'=>'11'] + ['field'=>'created_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'], + ['field'=>'updated_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'] ]; } diff --git a/migrations/create_issues.php b/migrations/create_issues.php index 7ded7cf..215adf2 100644 --- a/migrations/create_issues.php +++ b/migrations/create_issues.php @@ -2,12 +2,13 @@ class CreateIssue extends Migrations { function _init_() { $this->_fields = [ - ['field'=>'id', 'type'=>'INTEGER(11) AUTO_INCREMENT PRIMARY KEY', 'null'=>'false'], - ['field'=>'points', 'type'=>'INT', 'null'=>'false', 'limit'=>'3'], + ['field' => 'id', 'type' => 'INTEGER', 'autoincrement' => true, 'primary' => true], + ['field'=>'project_id', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'], + ['field'=>'points', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'3'], ['field'=>'title', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'255'], ['field'=>'description', 'type'=>'TEXT', 'null'=>'false'], - ['field'=>'created_at', 'type'=>'INT', 'null'=>'false', 'limit'=>'11'], - ['field'=>'updated_at', 'type'=>'INT', 'null'=>'false', 'limit'=>'11'] + ['field'=>'created_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'], + ['field'=>'updated_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'] ]; } diff --git a/migrations/create_params.php b/migrations/create_params.php index 03d19e6..2f89bad 100644 --- a/migrations/create_params.php +++ b/migrations/create_params.php @@ -2,11 +2,11 @@ class CreateParam extends Migrations { function _init_() { $this->_fields = [ - ['field'=>'id', 'type'=>'INTEGER(11) AUTO_INCREMENT PRIMARY KEY', 'null'=>'false'], + ['field' => 'id', 'type' => 'INTEGER', 'autoincrement' => true, 'primary' => true], ['field'=>'name', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'150'], ['field'=>'value', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'255'], - ['field'=>'created_at', 'type'=>'INT', 'null'=>'false', 'limit'=>'11'], - ['field'=>'updated_at', 'type'=>'INT', 'null'=>'false', 'limit'=>'11'] + ['field'=>'created_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'], + ['field'=>'updated_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'] ]; } diff --git a/migrations/create_projects.php b/migrations/create_projects.php new file mode 100644 index 0000000..d78bbac --- /dev/null +++ b/migrations/create_projects.php @@ -0,0 +1,20 @@ +_fields = [ + ['field' => 'id', 'type' => 'INTEGER', 'autoincrement' => true, 'primary' => true], + ['field'=>'name', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'150'], + ['field'=>'code', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'5'], + ['field'=>'created_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'], + ['field'=>'updated_at', 'type'=>'INTEGER', 'null'=>'false', 'limit'=>'11'] + ]; + } + + function up() { + $this->Create_Table(); + } + + function down() { + $this->Drop_Table(); + } +} diff --git a/migrations/create_translations.php b/migrations/create_translations.php new file mode 100644 index 0000000..28c8b88 --- /dev/null +++ b/migrations/create_translations.php @@ -0,0 +1,28 @@ +_fields = [ + ['field' => 'id', 'type' => 'INTEGER', 'autoincrement' => true, 'primary' => true], + ['field'=>'domain', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'60'], + ['field'=>'keyid', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'255'], + ['field'=>'locale', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'10'], + ['field'=>'translation', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'255'], + ['field' => 'created_at', 'type' => 'INTEGER', 'null' => FALSE, 'default' => '0'], + ['field' => 'updated_at', 'type' => 'INTEGER', 'null' => FALSE, 'default' => '0'] + ]; + } + + public function up() { + $this->Create_Table(); + $this->Add_Single_Index('keyid'); + $this->Add_Single_Index('domain'); + $this->Add_Single_Index('locale'); + } + + public function down() { + $this->Drop_Table(); + $this->Remove_Index('keyid'); + $this->Remove_Index('domain'); + $this->Remove_Index('locale'); + } +} diff --git a/migrations/create_users.php b/migrations/create_users.php index 2106a35..df2511e 100644 --- a/migrations/create_users.php +++ b/migrations/create_users.php @@ -2,14 +2,14 @@ class CreateUser extends Migrations{ function _init_() { $this->_fields = [ - ['field' => 'id', 'type' => 'INT AUTO_INCREMENT PRIMARY KEY'], + ['field' => 'id', 'type' => 'INTEGER', 'autoincrement' => true, 'primary' => true], ['field'=>'email', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'255'], ['field'=>'firstname', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'75'], ['field'=>'lastname', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'75'], - ['field'=>'password', 'type'=>'VARCHAR', 'null'=>'false', 'limit'=>'255'], - ['field' => 'status', 'type' => 'INT', 'null' => FALSE, 'default'=>'0'], - ['field' => 'created_at', 'type' => 'INT', 'null' => FALSE, 'default'=>'0'], - ['field' => 'updated_at', 'type' => 'INT', 'null' => FALSE, 'default'=>'0'] + ['field'=>'password', 'type'=>'VARCHAR', 'null'=>'true', 'limit'=>'255'], + ['field' => 'status', 'type' => 'INTEGER', 'null' => FALSE, 'default'=>'0'], + ['field' => 'created_at', 'type' => 'INTEGER', 'null' => FALSE, 'default'=>'0'], + ['field' => 'updated_at', 'type' => 'INTEGER', 'null' => FALSE, 'default'=>'0'] ]; } function up(){ diff --git a/tests/integrations/testTables.php b/tests/integrations/testTables.php new file mode 100644 index 0000000..2dc4b41 --- /dev/null +++ b/tests/integrations/testTables.php @@ -0,0 +1,49 @@ +describe('Verifying Fields'); + $this->assertHasFields($this->Attachment); + $this->assertHasFields($this->Issue); + $this->assertHasFields($this->Param); + $this->assertHasFields($this->Project); + $this->assertHasFields($this->User); + $this->assertHasFields($this->Translation); + + $this->describe('Verifying Field types'); + $this->assertHasFieldTypes($this->Attachment); + $this->assertHasFieldTypes($this->Issue); + $this->assertHasFieldTypes($this->Param); + $this->assertHasFieldTypes($this->Project); + $this->assertHasFieldTypes($this->User); + $this->assertHasFieldTypes($this->Translation); + } + + public function relationsTest() { + $this->describe('Verifying object relations'); + } + /** + * Force to renew connection for test proceed + * + * @return void + */ + public function _end_() { + $GLOBALS['Connection'] = null; + unset($GLOBALS['Connection']); + $GLOBALS['driver'] = null; + unset($GLOBALS['driver']); + } +} diff --git a/tests/testAttachmentModel.php b/tests/testAttachmentModel.php new file mode 100644 index 0000000..16122ee --- /dev/null +++ b/tests/testAttachmentModel.php @@ -0,0 +1,18 @@ +_migrateTables([ + 'attachments' + ]); + } + + public function modelExistTest() { + $this->describe('Should exists the attachment Model'); + $attachment = $this->Attachment->Niu(); + + $this->assertFalse(empty($attachment), 'Assert there is a attachment model instance'); + $this->assertTrue(is_a($attachment, 'ActiveRecord'), 'Assert the instance is an ActiveRecord instance'); + } +} +?> \ No newline at end of file diff --git a/tests/testIndexController.php b/tests/testIndexController.php new file mode 100644 index 0000000..8620fdd --- /dev/null +++ b/tests/testIndexController.php @@ -0,0 +1,132 @@ +_migrateTables([ + 'users' + ]); + http_response_code(HTTP_200); + $_SESSION = []; + } + + public function _init_() { + $this->_controller = new IndexController(); + } + + public function controllerExistTest() { + $this->describe('Should exists the Controller'); + + $this->assertFalse(empty($this->_controller), 'Assert there is a controller instance'); + $this->assertTrue(is_a($this->_controller, 'Page'), 'Assert the instance is a Controller instance'); + } + + public function indexActionTest() { + $this->describe('Should handle the index action'); + $_SESSION['user'] = 1; + $result = $this->_runAction('/index/index'); + $this->assertTrue(is_array($result->menuLinks) and sizeof($result->menuLinks) > 0, 'Should existe menuLinks entries.'); + } + + public function loginActionTest() { + $this->describe('Should test login action.'); + + $_SESSION = null; + $result = $this->_runAction('/index/login'); + $code = http_response_code(); + $this->assertTrue($code === HTTP_200, 'Should exist the action and the answer is 200.'); + + $_SESSION['user'] = 1; + $result = $this->_runAction('/index/login'); + $code = http_response_code(); + $this->assertTrue($code === HTTP_302, 'Should redirect when a session is active.'); + } + + public function logoutActionTest() { + $this->describe('Should test logout action.'); + + $result = $this->_runAction('/index/logout'); + $code = http_response_code(); + $this->assertTrue($code !== HTTP_404, 'Should exist the action and the answer is not 404.'); + + $_SESSION['user'] = '1'; + $result = $this->_runAction('/index/logout'); + $code = http_response_code(); + $this->assertTrue(empty($_SESSION['user']), 'Should there is no any data in session.'); + $this->assertTrue($code === HTTP_302, 'Should set a redirect.'); + } + + public function signinActionTest() { + $this->describe('Should test signin action.'); + + $_POST = null; + $result = $this->_runAction('/index/signin'); + $obj = json_decode($result->_outputContent); + $code = http_response_code(); + $this->assertTrue($code !== HTTP_404, 'Should exist the action and the answer is not 404.'); + $this->assertTrue(is_object($obj), 'Should respond with a JSON.'); + $this->assertTrue($code === HTTP_401, 'Should set a 401 response code on signin try with no params.'); + + $_POST['e'] = ''; + $_POST['p'] = ''; + + $result = $this->_runAction('/index/signin'); + $code = http_response_code(); + $this->assertTrue($code === HTTP_401, 'Should set a 401 response code on signin try with empty post values.'); + + $_POST['e'] = 'user'; + $_POST['p'] = ''; + + $result = $this->_runAction('/index/signin'); + $code = http_response_code(); + $this->assertTrue($code === HTTP_401, 'Should set a 401 response code on signin try with empty password value.'); + + $_POST['e'] = ''; + $_POST['p'] = 'password'; + + $result = $this->_runAction('/index/signin'); + $code = http_response_code(); + $this->assertTrue($code === HTTP_401, 'Should set a 401 response code on signin try with empty user value.'); + + $_POST['e'] = 'user'; + $_POST['p'] = 'password'; + + $result = $this->_runAction('/index/signin'); + $code = http_response_code(); + $this->assertTrue($code === HTTP_401, 'Should set a 401 response code on signin try for wrong user.'); + + $testUser = [ + 'id' => 1, + 'firstname' => 'test', + 'lastname' => 'test', + 'identification_kind_id' => '1', + 'identification' => '123456789', + 'email' => 'email@test.com', + 'password' => 'password', + 'created_at' => 0, + 'updated_at' => 0 + ]; + + $user = $this->User->Niu($testUser); + $result = $user->Save(); + $errors = $user->_error->errFields(); + + //validations to ensure the user is set properly before + $this->assertEquals(sizeof($errors), 0, 'Assert the number of errors must be 0.'); + $this->assertTrue($result, 'Assert the result sould be true.'); + + $_POST['e'] = 'email@test.com'; + $_POST['p'] = 'password'; + + $result = $this->_runAction('/index/signin'); + $code = http_response_code(); + + $this->assertTrue($code === HTTP_202, 'Should return 202 response code on signin try for proper user and proper password.'); + $this->assertTrue($_SESSION['user'] === 1, 'Should set the user id in the session'); + } + +} + +?> \ No newline at end of file diff --git a/tests/testIssueModel.php b/tests/testIssueModel.php new file mode 100644 index 0000000..8a56b99 --- /dev/null +++ b/tests/testIssueModel.php @@ -0,0 +1,18 @@ +_migrateTables([ + 'issues' + ]); + } + + public function modelExistTest() { + $this->describe('Should exists the issue Model'); + $issue = $this->Issue->Niu(); + + $this->assertFalse(empty($issue), 'Assert there is a issue model instance'); + $this->assertTrue(is_a($issue, 'ActiveRecord'), 'Assert the instance is an ActiveRecord instance'); + } +} +?> \ No newline at end of file diff --git a/tests/testParamModel.php b/tests/testParamModel.php new file mode 100644 index 0000000..970c71e --- /dev/null +++ b/tests/testParamModel.php @@ -0,0 +1,18 @@ +_migrateTables([ + 'params' + ]); + } + + public function modelExistTest() { + $this->describe('Should exists the Param Model'); + $param = $this->Param->Niu(); + + $this->assertFalse(empty($param), 'Assert there is a param model instance'); + $this->assertTrue(is_a($param, 'ActiveRecord'), 'Assert the instance is an ActiveRecord instance'); + } +} +?> \ No newline at end of file diff --git a/tests/testProjectModel.php b/tests/testProjectModel.php new file mode 100644 index 0000000..533e673 --- /dev/null +++ b/tests/testProjectModel.php @@ -0,0 +1,18 @@ +_migrateTables([ + 'projects' + ]); + } + + public function modelExistTest() { + $this->describe('Should exists the Project Model'); + $project = $this->Project->Niu(); + + $this->assertFalse(empty($project), 'Assert there is a project model instance'); + $this->assertTrue(is_a($project, 'ActiveRecord'), 'Assert the instance is an ActiveRecord instance'); + } +} +?> \ No newline at end of file diff --git a/tests/testUserModel.php b/tests/testUserModel.php new file mode 100644 index 0000000..b71362b --- /dev/null +++ b/tests/testUserModel.php @@ -0,0 +1,128 @@ + 1, + 'firstname' => 'test', + 'lastname' => 'test', + 'identification_kind_id' => '1', + 'identification' => '123456789', + 'email' => 'email@test.com', + 'password' => null, + 'created_at' => 0, + 'updated_at' => 0, + ]; + + public function beforeEach() { + $this->_migrateTables([ + 'users' + ]); + } + + public function modelExistTest() { + $this->describe('Should exists the User Model'); + $user = $this->User->Niu(); + + $this->assertFalse(empty($user), 'Assert there is a User model instance'); + $this->assertTrue(is_a($user, 'ActiveRecord'), 'Assert the instance is an ActiveRecord instance'); + } + + public function triggerErrorsOnInsertTest() { + $this->describe('Should have errors trying to insert new reg: mandatory fields'); + $testUser = [ + 'firstname' => 'test', + 'lastname' => 'test', + 'identification_kind_id' => '1', + 'identification' => '123456789', + 'email' => 'notemail', + ]; + $user = $this->User->Niu(); + $result = $user->Save(); + $errors = $user->_error->errFields(); + + $this->assertEquals(sizeof($errors), 3, 'Assert the number of errors must be 3.'); + $this->assertEquals($result, false, 'Assert the result sould be false.'); + $this->assertEquals(in_array('email', $errors), true, 'Assert if the field email is in the errors.'); + $this->assertEquals(in_array('firstname', $errors), true, 'Assert if the field firstname is in the errors.'); + $this->assertEquals(in_array('lastname', $errors), true, 'Assert if the field lastname is in the errors.'); + + $user = $this->User->Niu($testUser); + $result = $user->Save(); + $errors = $user->_error->errFields(); + + $this->describe('Should have errors trying to insert new reg: email address should be proper'); + $this->assertEquals($result, false, 'Assert the result sould be false.'); + $this->assertEquals(sizeof($errors), 1, 'Assert the number of errors must be 1.'); + $this->assertEquals(in_array('email', $errors), true, 'Assert if the field email is in the errors.'); + } + + public function saveOkTest() { + $this->describe('Should have no errors trying to insert new reg'); + $user = $this->User->Niu($this->_testFullUser); + $result = $user->Save(); + $errors = $user->_error->errFields(); + + $this->assertEquals(sizeof($errors), 0, 'Assert the number of errors must be 0.'); + $this->assertEquals($result, true, 'Assert the result sould be true.'); + } + + public function sanitizationTest() { + $this->describe('Should have sanitize first and last name on trying to insert new reg'); + $this->_testFullUser['firstname'] = 'niño'; + $this->_testFullUser['lastname'] = 'nuñez'; + $user = $this->User->Niu($this->_testFullUser); + $result = $user->Save(); + $errors = $user->_error->errFields(); + + $this->assertEquals(sizeof($errors), 0, 'Assert the number of errors must be 0.'); + $this->assertEquals($result, true, 'Assert the result sould be true.'); + $this->assertEquals($user->firstname, 'niño', 'Assert the firstname sanitization.'); + $this->assertEquals($user->lastname, 'nuñez', 'Assert the lastname sanitization.'); + } + + public function passwordEncryptTest() { + $this->describe('Should encrypt password on trying to insert new reg'); + $this->_testFullUser['password'] = $this->_pass; + + $user = $this->User->Niu($this->_testFullUser); + $result = $user->Save(); + $errors = $user->_error->errFields(); + + $this->assertEquals(sizeof($errors), 0, 'Assert the number of errors must be 0.'); + $this->assertEquals($result, true, 'Assert the result sould be true.'); + $this->assertEquals($user->password, sha1($this->_pass), 'Assert password is encrypted.'); + } + + + public function loginTest() { + $this->describe('Should Rejects a wrong login attempts and allows to login with the proper credentials'); + $GLOBALS['env'] = 'test'; + $this->_migrateTables([ + 'users' + ]); + + $this->_testFullUser['password'] = sha1($this->_pass); + $user = $this->User->Niu($this->_testFullUser); + $result = $user->Save(); + $errors = $user->_error->errFields(); + $this->assertEquals($result, true, 'Assert there is no errors inserting data for testing.'); + $this->assertEquals(sizeof($errors), 0, 'Assert the number of errors must be 0.'); + + try { + $this->User->login(); + } catch (Throwable $e) { + $this->assertEquals('ArgumentCountError', get_class($e), 'Should throw an exception for no params'); + } + + try { + $this->User->login('a param'); + } catch (Throwable $e) { + $this->assertEquals('ArgumentCountError', get_class($e), 'Should throw an exception for not enough params'); + } + + $this->assertEquals($this->User->login('any', 'any'), 0, 'Should not allow to login if email or/and password not match, returning 0'); + $this->assertEquals($this->User->login($user->email, 'not password'), 0, 'Should not allow to login if email or/and password not match, returning 0'); + $this->assertTrue(is_integer($this->User->login($user->email, $this->_pass)), 'Should allow to login, returning the user id'); + } +} +?> \ No newline at end of file diff --git a/ui-sources/components/dmb-button-action/dmb-button-action.directive.js b/ui-sources/components/dmb-button-action/dmb-button-action.directive.js index 62196b4..cc32f7a 100644 --- a/ui-sources/components/dmb-button-action/dmb-button-action.directive.js +++ b/ui-sources/components/dmb-button-action/dmb-button-action.directive.js @@ -11,21 +11,26 @@ class DmbButtonAction extends DumboDirective { this.classList.add('button'); switch(action) { - case 'edit': - icon = 'icon-edit-pencil'; - break; - case 'delete': - icon = 'icon-trashcan'; - break; - case 'new': - icon = 'icon-plus1'; - break; - case 'search': - icon = 'icon-filter'; - break; - case 'execute': - icon = 'icon-chevron-right'; - break; + case 'edit': + icon = 'icon-edit-pencil'; + break; + case 'delete': + icon = 'icon-trashcan'; + break; + case 'new': + icon = 'icon-plus1'; + break; + case 'search': + icon = 'icon-filter'; + break; + case 'execute': + icon = 'icon-chevron-right'; + break; + case 'attachment': + let type = this.getAttribute('file-type') || 'text2'; + console.log(type); + icon = `icon-file-${type}`; + break; } if (icon.length) { @@ -39,32 +44,43 @@ class DmbButtonAction extends DumboDirective { handleClick() { let panel = null; + let form = null; const url = this.getAttribute('url'); + const target = this.getAttribute('target'); + const formToExec = this.getAttribute('form'); const pageLoader = document.querySelector('#page-loader'); switch (this.getAttribute('behavior')) { - case 'open-panel': - panel = document.querySelector(this.getAttribute('panel')); - if(url) panel.setAttribute('source', url); - panel.open(); - break; - case 'launch-url': - location.href = url; - break; - case 'ajax': - if(pageLoader) pageLoader.open(); - fetch(new Request(url)) - .then(response => { - return response.json(); - }) - .then(() => { - window.location.reload(); - }) - .catch(error => { - window.dmbDialogService.closeAll(); - window.dmbDialogService.error(error); - }); - break; + case 'exec-form': + if(formToExec) { + form = document.querySelector(formToExec); + if(url) form.setAttribute('action', url); + if(target) form.setAttribute('target', target); + form.submit(); + } + break; + case 'open-panel': + panel = document.querySelector(this.getAttribute('panel')); + if(url) panel.setAttribute('source', url); + panel.open(); + break; + case 'launch-url': + location.href = url; + break; + case 'ajax': + if(pageLoader) pageLoader.open(); + fetch(new Request(url)) + .then(response => { + return response.json(); + }) + .then(() => { + window.location.reload(); + }) + .catch(error => { + window.dmbDialogService.closeAll(); + window.dmbDialogService.error(error); + }); + break; } } } diff --git a/ui-sources/components/dmb-button-action/dmb-button-action.scss b/ui-sources/components/dmb-button-action/dmb-button-action.scss index 79555a0..2ba4df8 100644 --- a/ui-sources/components/dmb-button-action/dmb-button-action.scss +++ b/ui-sources/components/dmb-button-action/dmb-button-action.scss @@ -1,4 +1,12 @@ -muy-button-action { +dmb-button-action { + &.icon { + width: auto; + + &:before { + align-items: center; + font-size: 1.2em; + } + } &.main-add { align-items: center; diff --git a/ui-sources/components/dmb-card/dmb-card-directive.spec.js b/ui-sources/components/dmb-card/dmb-card-directive.spec.js new file mode 100644 index 0000000..c59a7e3 --- /dev/null +++ b/ui-sources/components/dmb-card/dmb-card-directive.spec.js @@ -0,0 +1,10 @@ +describe('DmbCard Directive', () => { + let element = null; + + element = document.createElement('dmb-card'); + document.body.append(element); + + it('Should render element', () => { + expect(element).toBeDefined(); + }); +}); \ No newline at end of file diff --git a/ui-sources/components/dmb-card/dmb-card.directive.js b/ui-sources/components/dmb-card/dmb-card.directive.js new file mode 100644 index 0000000..3cd3ae5 --- /dev/null +++ b/ui-sources/components/dmb-card/dmb-card.directive.js @@ -0,0 +1,17 @@ +/** + * @dmbdoc directive + * @name DMB.directive:DmbCard + * + * @description + * This directive only will contains the data, the directive is set to add proper styles and further behaviors. + * + * @example + + */ +class DmbCard extends DumboDirective { + constructor() { + super(); + } +} + +customElements.define('dmb-card', DmbCard); \ No newline at end of file diff --git a/ui-sources/components/dmb-card/dmb-card.scss b/ui-sources/components/dmb-card/dmb-card.scss new file mode 100644 index 0000000..aa8a7b7 --- /dev/null +++ b/ui-sources/components/dmb-card/dmb-card.scss @@ -0,0 +1,179 @@ +dmb-card { + background-color: var(--primary-contrast); + border: none; + border-radius: 0.5em; + box-shadow: 0px 2px 1px -1px #00000099, 0px 1px 1px 0px #00000066, 0px 1px 3px 0px #00000055; + color: var(--primary); + float: left; + margin-bottom: 1em; + margin-right: 1em; + min-height: 12em; + padding: 0.5em; + position: relative; + width: 21em; + word-wrap: break-word; + + .head { + border-bottom: solid 1px var(--default); + padding-bottom: 0.5em; + + .header { + color: var(--primary); + font-weight: bold; + margin: 0; + padding: 0.5em; + } + + h2 { + margin: 0; + } + } + + .body { + margin-top: 0.5em; + + .item { + margin-bottom: 0.5em; + } + + .label { + color: var(--primary); + } + + .content { + color: var(--primary); + font-weight: bold; + overflow-wrap: break-word; + text-align: right; + word-wrap: break-word; + } + } + + &.half-height { + min-height: 6em; + } + + &.icon { + padding-right: 4em; + position: relative; + + &:before { + border-radius: 50%; + font-size: 3em; + padding: 10px; + position: absolute; + right: 0.1em; + top: 0.1em; + } + + .body { + .content { + font-size: 2em; + text-align: center; + width: 100%; + } + .label { + font-size: smaller; + } + } + } + + &.border { + &-start { + border-bottom: 0; + border-left: 4px; + border-right: 0; + border-top: 0; + border-style: solid; + } + + &-primary { + border-color: var(--primary); + + &.icon { + &:before { + background-color: var(--primary); + color: var(--primary-contrast); + } + } + } + + &-secondary { + border-color: var(--secondary); + + &.icon { + &:before { + background-color: var(--secondary); + color: var(--secondary-contrast); + } + } + } + + &-default { + border-color: var(--default); + + &.icon { + &:before { + background-color: var(--default); + color: var(--default-contrast); + } + } + } + + &-error { + border-color: var(--error); + + &.icon { + &:before { + background-color: var(--error); + color: var(--error-contrast); + } + } + } + + &-success { + border-color: var(--success); + + &.icon { + &:before { + background-color: var(--success); + color: var(--success-contrast); + } + } + } + + &-warning { + border-color: var(--warning); + + &.icon { + &:before { + background-color: var(--warning); + color: var(--warning-contrast); + } + } + } + + &-information { + border-color: var(--information); + + &.icon { + &:before { + background-color: var(--information); + color: var(--information-contrast); + } + } + } + } + + &.small { + height: auto; + min-height: 3em; + width: 16em; + } + + &.full { + height: auto; + padding: 2em; + width: 100%; + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-close-panel/dmb-close-panel.scss b/ui-sources/components/dmb-close-panel/dmb-close-panel.scss new file mode 100644 index 0000000..1258060 --- /dev/null +++ b/ui-sources/components/dmb-close-panel/dmb-close-panel.scss @@ -0,0 +1,7 @@ +dmb-close-panel { + top: 0; + + .icon { + font-size: 2em; + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-content/dmb-content.scss b/ui-sources/components/dmb-content/dmb-content.scss new file mode 100644 index 0000000..37a7147 --- /dev/null +++ b/ui-sources/components/dmb-content/dmb-content.scss @@ -0,0 +1,3 @@ +dmb-content { + top: 3em; +} \ No newline at end of file diff --git a/ui-sources/components/dmb-header/dmb-header.scss b/ui-sources/components/dmb-header/dmb-header.scss new file mode 100644 index 0000000..ce445d3 --- /dev/null +++ b/ui-sources/components/dmb-header/dmb-header.scss @@ -0,0 +1,3 @@ +dmb-header { + height: 3em; +} \ No newline at end of file diff --git a/ui-sources/components/dmb-input/dmb-input.scss b/ui-sources/components/dmb-input/dmb-input.scss new file mode 100644 index 0000000..5441704 --- /dev/null +++ b/ui-sources/components/dmb-input/dmb-input.scss @@ -0,0 +1,5 @@ +dmb-input { + input { + background-color: var(--primary-contrast); + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-login/dmb-login.directive.js b/ui-sources/components/dmb-login/dmb-login.directive.js index 6dc5454..c9e5161 100644 --- a/ui-sources/components/dmb-login/dmb-login.directive.js +++ b/ui-sources/components/dmb-login/dmb-login.directive.js @@ -1,30 +1,37 @@ /** - * Component handle login - */ + * Component handle login + */ class DmbLogin extends DumboDirective { + #_form; + constructor() { super(); const template = ''; this.setTemplate(template); this.valids = []; - this.form = null; + this.#_form = null; } init() { const button = this.querySelector('dmb-button'); - this.form = this.querySelector('dmb-form'); + const inputs = this.querySelectorAll('dmb-input'); + const target = this.getAttribute('target'); + //set dialog transparency + this.closest('dmb-view').style.backgroundColor = '#ffffff99'; + this.#_form = this.querySelector('dmb-form'); + inputs[0].setAttribute('label', this.getAttribute('user-label') || ''); + inputs[1].setAttribute('label', this.getAttribute('pass-label') || ''); - this.form.setAttribute('action', `${this.getAttribute('target')}signin`); - button.click((e) => { - e.preventDefault(e); - this.loginClick(); - }); + this.#_form.setAttribute('action', `${target}signin`); + this.#_form.setAttribute('redirect', `${target}index`); + button.innerText = this.getAttribute('button-label') || ''; + this.#_form.callback = this.loginClick; } /** @@ -32,11 +39,25 @@ class DmbLogin extends DumboDirective { */ loginClick() { - const canSend = this.form.submit(); + const target = this.getAttribute('action'); + const redirect = this.getAttribute('redirect'); + const init = { + method: 'POST', + body: this.getFormData() + }; + const loginRequest = new Request(target, init); - if (canSend) { - this.handleLogin(this.getAttribute('target')); - } + fetch(loginRequest) + .then(response => { + if (!response.ok) throw new Error('Usuario o password incorrecto'); + return response.json(); + }) + .then(() => { + window.location = redirect; + }) + .catch(error => { + window.dmbDialogService.error(error); + }); } /** diff --git a/ui-sources/components/dmb-menu-button/dmb-menu-button.scss b/ui-sources/components/dmb-menu-button/dmb-menu-button.scss index 2946787..0e9ae7a 100644 --- a/ui-sources/components/dmb-menu-button/dmb-menu-button.scss +++ b/ui-sources/components/dmb-menu-button/dmb-menu-button.scss @@ -1,6 +1,13 @@ dmb-menu-button { - top: 1em; - left: 1.5em; + display: block; + float: left; + height: 2em; + left: 0; + margin-right: 1em; + margin-top: 0.3em; + position: initial; + top: 0; + transform: translateX(50%); .icon { &:before { diff --git a/ui-sources/components/dmb-menu/dmb-menu.scss b/ui-sources/components/dmb-menu/dmb-menu.scss index 155012c..55c3043 100644 --- a/ui-sources/components/dmb-menu/dmb-menu.scss +++ b/ui-sources/components/dmb-menu/dmb-menu.scss @@ -1,14 +1,18 @@ .dmb-menu { + dmb-header { + background-color: var(--primary); + color: var(--primary-contrast); + } dmb-content { - background: var(--secondary); - color: var(--secondary-contrast); + background: var(--primary-contrast); + color: var(--primary); padding-left: 0; padding-right: 0; text-align: left; .item { box-sizing: border-box; - color: var(--secondary-contrast); + color: var(--primary); cursor: pointer; float: left; height: 4em; @@ -17,10 +21,10 @@ width: 100%; * { - color: var(--secondary-contrast); + color: var(--primary); &:before { - color: var(--secondary-contrast); + color: var(--primary); } } @@ -34,11 +38,11 @@ &.selected, &:hover { - background-color: var(--primary); + background-color: var(--secondary-hover); } &:after { - background-color: var(--secondary-contrast); + background-color: var(--secondary); border: 0 none; bottom: 0; content: ' '; @@ -54,6 +58,27 @@ font-size: 2em; } } + + &-main { + &.icon { + &:before { + font-size: 2.5em; + left: auto; + position: absolute; + right: 0.5em; + } + } + + & ~ .submenu { + display: none; + } + + &.actived { + & ~ .submenu { + display: inline; + } + } + } } .item-secondary { diff --git a/ui-sources/components/dmb-more-option/dmb-more-option.directive.js b/ui-sources/components/dmb-more-option/dmb-more-option.directive.js new file mode 100644 index 0000000..a40bd96 --- /dev/null +++ b/ui-sources/components/dmb-more-option/dmb-more-option.directive.js @@ -0,0 +1,79 @@ +/** + * @dmbdoc directive + * @name DMB.directive:DmbMoreOption + * + * @description + * Will render a DOM element for more option entry for an action + * + * @attribute behavior tells to the component how to perform the action. Valid options: open-panel, launch-url, ajax + * @attribute url URL to link or to load according the behavior + * @attribute panel (Optional) Query selector for the panel to open if the behavior is set to open-panel + * + * @example + + + */ +class DmbMoreOption extends DumboDirective { + constructor() { + super(); + this.url = ''; + this.pageLoader = null; + this.panel = null; + this.behavior = ''; + } + + init() { + this.behavior = this.getAttribute('behavior') || ''; + + if (!this.behavior.length) { + throw 'A behavior attribute must to be defined.'; + } + + this.url = this.getAttribute('url') || ''; + this.pageLoader = document.querySelector('#page-loader'); + this.panel = this.getAttribute('panel'); + + this.addEventListener('click', e => { + e.preventDefault(); + this.handleClick(); + }); + } + + handleClick() { + let panel = null; + switch (this.behavior) { + case 'open-panel': + panel = document.querySelector(this.panel); + if(this.url) panel.setAttribute('source', this.url); + panel.open(); + break; + case 'launch-url': + location.href = this.url; + break; + case 'ajax': + if(this.pageLoader) this.pageLoader.open(); + fetch(new Request(this.url)) + .then(response => { + if(this.pageLoader) this.pageLoader.close(); + return response.json(); + }) + .then((response) => { + window.dmbDialogService.closeAll(); + window.dmbDialogService.info(response.message); + setTimeout(() => { + location.reload(); + }, 1000); + }) + .catch(error => { + window.dmbDialogService.closeAll(); + window.dmbDialogService.error(error.message); + }); + break; + } + } +} + +customElements.define('dmb-more-option', DmbMoreOption); \ No newline at end of file diff --git a/ui-sources/components/dmb-more-option/dmb-more-option.scss b/ui-sources/components/dmb-more-option/dmb-more-option.scss new file mode 100644 index 0000000..415636f --- /dev/null +++ b/ui-sources/components/dmb-more-option/dmb-more-option.scss @@ -0,0 +1,14 @@ +dmb-more-option { + display: inline-block; + padding: 0.3em 0.5em; + border-bottom: solid 1px var(--default); + width: 100%; + + &:last-child { + border-bottom: none; + } + + &:hover { + color: var(--default); + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-more-options/dmb-more-options.directive.js b/ui-sources/components/dmb-more-options/dmb-more-options.directive.js new file mode 100644 index 0000000..6643e9f --- /dev/null +++ b/ui-sources/components/dmb-more-options/dmb-more-options.directive.js @@ -0,0 +1,73 @@ +/** + * @dmbdoc directive + * @name DMB.directive:DmbMoreOptions + * + * @description + * Wrapper handler for the group of muy-option items. Render an icon (three vertical points) and on click display the options. + * + * @example + + + + + + + */ +class DmbMoreOptions extends DumboDirective { + constructor() { + super(); + + const template = '
'; + this.setTemplate(template); + this.wrapper = null; + this.option = document.createElement('dmb-more-option'); + } + + init() { + this.wrapper = this.querySelector('.wrapper'); + this.classList.add('icon'); + this.classList.add('icon-more_vert'); + this.addEventListener('click', (e) => { + e.preventDefault(); + this.wrapper.classList.toggle('active'); + }); + + this.buildOptions(); + } + + setOptions(options) { + if (!Array.isArray(options)) { + throw 'Options must to be an array'; + } + this.options = options; + this.buildOptions(); + } + + buildOptions() { + let size = 0; + let i = 0; + let option = null; + + if (this.options && Array.isArray(this.options)) { + size = this.options.length; + for (i = 0; i < size; i++) { + option = this.option.cloneNode(); + option.innerHTML = this.options[i].text; + + if (this.options[i].behavior) option.setAttribute(this.options[i].behavior); + if (this.options[i].url) option.setAttribute(this.options[i].url); + if (this.options[i].panel) option.setAttribute(this.options[i].panel); + + this.wrapper.appendChild(option); + } + } + } +} + +customElements.define('dmb-more-options', DmbMoreOptions); \ No newline at end of file diff --git a/ui-sources/components/dmb-more-options/dmb-more-options.scss b/ui-sources/components/dmb-more-options/dmb-more-options.scss new file mode 100644 index 0000000..6dd6a4e --- /dev/null +++ b/ui-sources/components/dmb-more-options/dmb-more-options.scss @@ -0,0 +1,38 @@ +dmb-more-options { + color: var(--primary); + cursor: pointer; + display: inline-block; + position: relative; + + .wrapper { + background-color: var(--secondary); + display: none; + padding: 0.2em 0.3em; + position: absolute; + right: 3em; + + &.active { + display: inline-block; + z-index: 1; + } + + &:after { + content: ''; + border: 1em solid var(--secondary); + border-right-color: transparent; + border-bottom-color: transparent; + height: 0; + margin-top: -1em; + margin-bottom: -1em; + margin-right: -3em; + position: absolute; + right: 1em; + top: 1em; + width: 0; + } + + dmb-more-option { + color: var(--secondary-contrast); + } + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-pagination/dmb-pagination.scss b/ui-sources/components/dmb-pagination/dmb-pagination.scss new file mode 100644 index 0000000..040f0de --- /dev/null +++ b/ui-sources/components/dmb-pagination/dmb-pagination.scss @@ -0,0 +1,25 @@ +dmb-pagination { + margin-bottom: 1em; + margin-top: 1em; + padding-bottom: 1em; + padding-top: 1em; + + .paginate-page { + border: solid 1px var(--default-hover); + margin-left: -1px; + margin-right: 0; + padding: 0.375rem 0.75rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + + &:hover:not(.paginate-page-active) { + background-color: var(--secondary-hover); + } + + &-active { + background-color: var(--primary); + border-color: var(--primary); + color: var(--primary-contrast); + cursor: default; + } + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-search/dmb-search.directive.js b/ui-sources/components/dmb-search/dmb-search.directive.js new file mode 100644 index 0000000..46ef720 --- /dev/null +++ b/ui-sources/components/dmb-search/dmb-search.directive.js @@ -0,0 +1,50 @@ +class MuySearch extends DumboDirective { + constructor () { + super(); + const template = '' + + '' + + '' + + ''; + this.setTemplate(template); + } + + init() { + let fields = ''; + let field = ''; + let input = null; + let newinput = null; + let form = null; + let i = 0; + let value = ''; + let id = null; + + if (!this.hasAttribute('fields')) throw new Error('Fields to include in search must be set.'); + fields = this.getAttribute('fields').trim(); + if (!fields.length) throw new Error('Fields to include in search must be set.'); + + form = this.querySelector('form'); + form.setAttribute('action', this.getAttribute('action')); + this.querySelector('dmb-input').setAttribute('label', this.getAttribute('label')); + value = this.getAttribute('dmb-value') || ''; + id = this.getAttribute('dmb-id') || null; + if(id) { + form.id = id; + } + + fields = fields.split(','); + input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + this.querySelector('dmb-input input').value = value; + + while (!!(field = fields.shift())) { + newinput = input.cloneNode(); + newinput.setAttribute('name', `search[fields][${i}]`); + newinput.value = field; + form.prepend(newinput); + i++; + } + + } + +} +customElements.define('dmb-search', MuySearch); \ No newline at end of file diff --git a/ui-sources/components/dmb-search/muy-search.scss b/ui-sources/components/dmb-search/muy-search.scss new file mode 100644 index 0000000..e180971 --- /dev/null +++ b/ui-sources/components/dmb-search/muy-search.scss @@ -0,0 +1,24 @@ +dmb-search { + width: 100%; + + dmb-input { + float: left; + margin-right: 1em; + width: calc(99% - 4em); + + label { + display: none; + } + + input { + height: 2.7em; + } + } + + .col & { + dmb-button.button { + float: left; + width: 3em; + } + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-select/dmb-select.scss b/ui-sources/components/dmb-select/dmb-select.scss new file mode 100644 index 0000000..91c69ec --- /dev/null +++ b/ui-sources/components/dmb-select/dmb-select.scss @@ -0,0 +1,6 @@ +dmb-select { + select { + background-color: var(--primary-contrast); + color: var(--primary); + } +} \ No newline at end of file diff --git a/ui-sources/components/dmb-table/dmb-table.scss b/ui-sources/components/dmb-table/dmb-table.scss index 1d066ff..86ccbd8 100755 --- a/ui-sources/components/dmb-table/dmb-table.scss +++ b/ui-sources/components/dmb-table/dmb-table.scss @@ -1,4 +1,4 @@ -.dmb-table { +dmb-table { clear: both; float: none; margin: auto; @@ -7,7 +7,7 @@ width: 100%; table { - border: solid 0.06em var(--secondary-hover); + border: solid 0.06em var(--secondary); border-radius: 0; border-spacing: 0; clear: both; @@ -15,22 +15,27 @@ width: 100%; thead { - background-color: var(--primary); + background-color: transparent; border: solid 0.06em var(--secondary); tr { - background-color: var(--primary-hover); + background-color: transparent; &:first-child { - background-color: var(--primary); + background-color: transparent; } th { - background-color: var(--primary); + background-color: transparent; + border-right: 0.06em var(--secondary) dashed; border-radius: 0; margin: 0; padding: 0.5em; text-transform: uppercase; + + &:last-child { + border-right: 0 none transparent; + } } } } @@ -39,6 +44,7 @@ tr { td { border-right: 0.06em var(--secondary) dashed; + border-top: 0.06em var(--secondary) dashed; border-radius: 0; padding: 0.5em; margin: 0; @@ -66,7 +72,7 @@ } &:hover { - background-color: var(--success-hover); + background-color: var(--default-hover); } } } @@ -90,7 +96,7 @@ border-radius: 0.2em; box-sizing: border-box; color: var(--primary-contrast); - padding: 0.2em; + padding: 0.2em; width: 2.2em; &:before { @@ -106,7 +112,7 @@ border-radius: 0.2em; box-sizing: border-box; color: var(--secondary); - padding: 0.2em; + padding: 0.2em; &:before { font-size: 1em; diff --git a/ui-sources/libs/dmb-components.min.js b/ui-sources/libs/dmb-components.min.js index 9f5782a..b5d74ee 100644 --- a/ui-sources/libs/dmb-components.min.js +++ b/ui-sources/libs/dmb-components.min.js @@ -1 +1 @@ -class DmbForm extends DumboDirective{constructor(){super();this._valids=0;this.setTemplate('
');this.form=null}get valids(){return this._valids}init(){this.form=this.querySelector("form");this.form.setAttribute("method",this.getAttribute("method")||"POST");this.form.setAttribute("action",this.getAttribute("action")||"#");this.form.setAttribute("name",this.getAttribute("dmb-name")||"");this.form.setAttribute("id",this.getAttribute("dmb-id")||this.generateId());this.form.setAttribute("enctype",this.getAttribute("enctype")||"application/x-www-form-urlencoded");this.form.onSubmit=(e=>{e.preventDefault();return this.submit()})}reset(){this.form.reset()}validate(formElements,parentSelector){let item=null;let parent=null;let hasInvalids=false;while(item=formElements.shift()){if(item.closest(".novalidate")===null){parent=item.closest(parentSelector);parent.resetValidation();parent.setValidation();if(!item.hasAttribute("valid")&&!item.hasAttribute("hidden")){item.reportValidity();item.focus();hasInvalids=true}else{this._valids++}}}return!hasInvalids}submit(){const inputs=[...this.querySelectorAll("dmb-input[validate] input")];const selects=[...this.querySelectorAll("dmb-select[validate] select")];const textAreas=[...this.querySelectorAll("dmb-text-area[validate] textarea")];const isAsync=this.hasAttribute("async");let totalvalidations=0;this._valids=0;totalvalidations=this.validate(inputs,"dmb-input")+this.validate(selects,"dmb-select")+this.validate(textAreas,"dmb-text-area");if(totalvalidations===3){this.dispatchEvent(new Event("onsubmit"));if(isAsync){if(typeof this.callback==="function")this.callback()}else{this.form.submit()}return true}return false}getFormData(){return new FormData(this.form)}}customElements.define("dmb-form",DmbForm);class DmbHeader extends DumboDirective{constructor(){super()}init(){let titleDOM=null;if(this.title){titleDOM=document.createElement("h2");titleDOM.classList.add("dmb-header-title");titleDOM.textContent=this.title;this.prepend(titleDOM)}}}customElements.define("dmb-header",DmbHeader);class DmbSelect extends DumboDirective{static get observedAttributes(){return["valid","values","dmb-name","label","dmb-class","validate","dmb-value"]}constructor(){super();const template=""+"";this.setTemplate(template);this.validations={_required:value=>{let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error=""}return response}};this.isValid=false;this.valueList=[];this.validators=[];this._errorInputClass="_error"}set values(newValues=[]){this.valueList=newValues;this.buildOptions()}init(){const select=this.querySelector("select");let value=null;let options=null;let option=null;let opval=null;this.hasAttribute("label")&&(this.querySelector("label").innerText=this.getAttribute("label"));this.hasAttribute("label")&&select.setAttribute("aria-label",this.getAttribute("label")||"");this.hasAttribute("dmb-class")&&select.setAttribute("dmb-class",this.getAttribute("dmb-class")||"");select.setAttribute("name",this.getAttribute("dmb-name")||"");this.hasAttribute("validate")&&select.setAttribute("validate",this.getAttribute("validate"));select.id=this.getAttribute("dmb-id")||this.generateId();select.multiple=this.hasAttribute("multiple");if(this.hasAttribute("dmb-value")){value=this.getAttribute("dmb-value").trim();value=select.multiple?JSON.parse(value):value}if(select&&this.getAttribute("validate")){this.validators=this.buildValidators(select,this.getAttribute("validate"))}select.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});options=[...select.querySelectorAll("option")];if(options.length){while(option=options.shift()){option.value=(option.getAttribute("value")||"").trim();opval=isNaN(option.value)?option.value:parseInt(option.value);value=isNaN(value)?value:parseInt(value);if(!option.hasAttribute("selected")&&(opval&&opval==value)||Array.isArray(value)&&value.includes(opval)){option.setAttribute("selected",true);option.selected=true}}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let options=element.querySelectorAll("option");let content=[...options].filter(x=>x.selected).map(x=>x.value.trim()||"");let valid=true;let validator=null;let func=null;let result=null;!element.multiple&&(content=content[0]);for(var i=0,len=validators.length;i{const target=e.target;const classes=target.getAttribute("class");const form=document.querySelector(formTarget);if(/paginate-(\w+-)?page/gm.test(classes)){if(form){e.preventDefault();form.setAttribute("action",e.target.getAttribute("href"));form.submit()}}})}}customElements.define("dmb-pagination",DmbPagination);class DmbInfoPop extends DumboDirective{constructor(){super();const template='
';this.setTemplate(template)}init(){const size=this.getAttribute("size")||"small";this.querySelector(".float-content").classList.add(`float-content_${size}`)}}customElements.define("dmb-info-pop",DmbInfoPop);class DmbDialog extends DumboDirective{static get observedAttributes(){return["open"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){this.openValue=newValue!==null}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(new Event("close"));this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(new Event("close-dialog"));return true}open(){this.hasAttribute("open")||this.setAttribute("open","");this.dispatchEvent(new Event("open"))}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}init(){let delay=1e3*this.getAttribute("delay");this.hasAttribute("no-close")||this.setCloseButton();setTimeout(()=>{this.open()},delay)}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=this.querySelector(".close-modal-button");if(!icon||!icon.length){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")});this.querySelector(".wrapper").prepend(icon)}}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}info(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("info");msg=msg||"";this.classList.add("info");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-dialog",fn)}}}customElements.define("dmb-dialog",DmbDialog);class DmbMenuButton extends DumboDirective{constructor(){super();let template=''+'';this.setTemplate(template)}init(){this.addEventListener("click",()=>{let menu=this.getAttribute("menu");if(menu.length){document.querySelector(menu).showModal()}})}}customElements.define("dmb-menu-button",DmbMenuButton);class DmbFooter extends DumboDirective{constructor(){super()}init(){const dmbview=this.parentNode.querySelector("dmb-content");if(dmbview){dmbview.classList.add("padded-footer")}}}customElements.define("dmb-footer",DmbFooter);class DmbInput extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name","label"]}constructor(){super();const template=""+'';this.setTemplate(template);this.isValid=false;this._errorInputClass="_error";this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false}return response},_email:function(value){let response={valid:true,error:null},re=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;if(value&&!re.test(value)){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("input");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":this.buildValidators();break;case"label":if(input){this.querySelector("label").innerText=newValue;input.setAttribute("aria-label",newValue);input.setAttribute("placeholder",newValue)}break}}buildValidators(){let validators=[];let validatorList=(this.getAttribute("validate")||"").split(",");const input=this.querySelector("input");for(let i=0,len=validatorList.length;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};const type=element.getAttribute("type");let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;if(type!=="file")element.value=content;while(validator=validators.shift()){func=this.validations["_"+validator.key]||unknownValidator;result=func(content,validator.param);if(result.valid!==true){valid=false;break}}if(valid===true){element.parentNode.classList.remove(this._errorInputClass)}else{element.parentNode.classList.add(this._errorInputClass)}this.isValid=valid;valid?element.setAttribute("valid",""):element.removeAttribute("valid")}resetValidation(){let elements=this.getElementsByClassName(this._errorInputClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorInputClass)}}setValidation(){this._runValidators(this.querySelector("input"),this.buildValidators())}init(){const input=this.querySelector("input");const labelElement=this.querySelector("label");const label=this.getAttribute("label")||null;const masked=this.getAttribute("masked")||null;const autocomplete=this.getAttribute("autocomplete")||null;const classd=this.getAttribute("dmb-class")||null;const name=this.getAttribute("dmb-name")||null;const validate=this.getAttribute("validate")||null;const pattern=this.getAttribute("pattern")||null;const value=this.getAttribute("value")||null;const type=this.getAttribute("type")||"text";input.id=this.getAttribute("dmb-id")||this.generateId();input.setAttribute("type",type);if(label){this.querySelector("label").innerText=label;input.setAttribute("aria-label",label);input.setAttribute("placeholder",label)}if(labelElement){labelElement.setAttribute("for",input.id)}if(type==="checkbox"){this.insertBefore(input,labelElement)}if(masked)input.setAttribute("masked",masked);if(autocomplete)input.setAttribute("autocomplete",autocomplete);if(classd)input.setAttribute("class",classd);if(name)input.setAttribute("name",name);if(validate)input.setAttribute("validate",validate);if(pattern)input.setAttribute("pattern",pattern);if(value)input.value=value;type==="file"&&this.hasAttribute("accept")&&input.setAttribute("accept",this.getAttribute("accept"));const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};const maskInputAlpha=e=>{var char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{var char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}this.buildValidators();input.addEventListener("blur",()=>{this.setValidation()},true)}}customElements.define("dmb-input",DmbInput);class DmbImageUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbimgInput=this.querySelector('dmb-input[type="file"]');const imgInput=dmbimgInput.querySelector('input[type="file"]');const previewimg=this.querySelector(".preview img");previewimg.setAttribute("alt",this.getAttribute("img-alt")||"Image Preview");this.hasAttribute("validate")&&dmbimgInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbimgInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbimgInput.setAttribute("label",this.getAttribute("label"));imgInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])})}loadFile(file){const previewimg=this.querySelector(".preview img");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();previewimg.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-image-uploader",DmbImageUploader);class DmbToggle extends DumboDirective{static get observedAttributes(){return["value"]}constructor(){super();const template='';this.setTemplate(template);this.val=0}set value(val=0){this.val=val;this.setStatus()}get value(){return this.val}attributeChangedCallback(attr,oldValue,newValue){switch(attr){case"value":this.val=parseInt(newValue);this.setStatus();break}}init(){this.val=parseInt(this.getAttribute("value")||"0");this.setStatus();this.addEventListener("click",()=>{this.val=1*!this.val;this.setStatus()})}setStatus(){if(this.val===1){this.classList.add("on")}else{this.classList.remove("on")}}click(method){if(typeof method==="function"){this.addEventListener("click",method)}}}customElements.define("dmb-toggle",DmbToggle);class DmbClosePanel extends DumboDirective{constructor(){super();const template='';this.setTemplate(template)}init(){const orientation=this.getAttribute("orientation")||"right";const icon=this.querySelector("i.icon");let panel=null;this.classList.add(orientation);icon.classList.add(`icon-chevron-${orientation}`);this.addEventListener("click",()=>{panel=this.closest("dmb-panel");panel.close()})}}customElements.define("dmb-close-panel",DmbClosePanel);class DmbVideoUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbVideoInput=this.querySelector('dmb-input[type="file"]');const videoInput=dmbVideoInput.querySelector('input[type="file"]');const willPreview=this.hasAttribute("preview")&&!!this.getAttribute("preview").length;this.hasAttribute("validate")&&dmbVideoInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbVideoInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbVideoInput.setAttribute("label",this.getAttribute("label"));willPreview&&videoInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])});willPreview||this.querySelector(".preview video").remove()}loadFile(file){const videoComponent=this.querySelector(".preview video");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();videoComponent.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-video-uploader",DmbVideoUploader);class DmbPanel extends DumboDirective{static get observedAttributes(){return["source"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){!!newValue&&newValue.length&&this.loadExternalSource()}loadExternalSource(){const url=this.getAttribute("source");let wrapper=null;let sourceRequest=null;if(url&&url.length){sourceRequest=new Request(url);fetch(sourceRequest).then(res=>res.text()).then(data=>{wrapper=this.querySelector(".wrapper");wrapper.innerHTML=data})}return true}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(new Event("close"));this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(new Event("close-dialog"))}open(){this.setAttribute("open","");this.dispatchEvent(new Event("open"));this.addEventListener("click",e=>{if(this.openValue&&e.target===this){this.close("cancelled")}},true)}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")});this.querySelector(".wrapper").prepend(icon)}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");message.textContent=msg;wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");message.textContent=msg;wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-panel",fn)}}init(){!this.classList.contains("right")&&!this.classList.contains("left")&&this.classList.add("right");!this.classList.contains("small")&&!this.classList.contains("large")&&this.classList.add("small");this.addEventListener("click",e=>{e.target===this&&this.close("cancelled")},true);this.loadExternalSource()}}customElements.define("dmb-panel",DmbPanel);class DmbTextArea extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name"]}constructor(){super();const template=""+"";this.setTemplate(template);this.isValid=false;this.validators=[];this._errorInputClass="_error";this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("textarea");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(input)input.setAttribute("name",newValue);break;case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":if(input)input.setAttribute("validate",newValue);break}}init(){let input=this.getElementsByTagName("textarea").item(0);this.querySelector("label").innerText=this.getAttribute("label");input.setAttribute("aria-label",this.getAttribute("label")||"");input.setAttribute("masked",this.getAttribute("masked")||"");input.setAttribute("autocomplete",this.getAttribute("autocomplete")||"");input.setAttribute("class",this.getAttribute("dmb-class")||"");input.setAttribute("name",this.getAttribute("dmb-name")||"");input.setAttribute("validate",this.getAttribute("validate")||"");input.setAttribute("placeholder",this.getAttribute("placeholder")||"");input.setAttribute("valid","true");input.id=this.getAttribute("dmb-id")||this.generateId();const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};if(input&&this.getAttribute("validate")){this.validators=this.buildValidators(input,this)}input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});const maskInputAlpha=e=>{var char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{var char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("validate")){this.validators=this.buildValidators(input,this);input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},true)}if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;element.value=content;for(var i=0,len=validators.length;i'+'H2'+'H3'+'H4'+'H5'+'H6'+''+''+''+''+''+''+''+''+''+'
'+''+'
'+"
"+'
'+''+'
'+"
"+'Source'+''+""+''+'
'+"
"+''+"";this.setTemplate(template);this.isValid=false;this._errorWysiwygClass="v_error";this.colorPalette=["000000","FF9966","6699FF","99FF66","CC0000","00CC00","0000CC","333333","0066FF","FFFFFF"];this.toolbarElements=[];this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error="Este campo es obligatorio"}return response}}}init(){const forePalette=this.querySelector(".palette .fore-palette");const backPalette=this.querySelector(".back-palette .fore-palette");let hideButtons=null;let showButtons=null;let executeCommand=null;let a=document.createElement("a");let ap=document.createElement("a");let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");this.toolbarElements=this.querySelectorAll(".dmb-wysiwyg__toolbar-button");a.dataset.command="foreColor";ap.dataset.command="backColor";a.setAttribute("href","#");ap.setAttribute("href","#");a.classList.add("palette-item");ap.classList.add("palette-item");a.classList.add("dmb-wysiwyg__toolbar-button");ap.classList.add("dmb-wysiwyg__toolbar-button");for(let i=0;i{for(let j=0;j{for(let j=0;j{const me=e.target;let command=me.dataset.command;let value=me.dataset.value;let url;let textArea;let editArea;e.stopImmediatePropagation();e.stopPropagation();e.preventDefault();switch(command){case"h2":case"h3":case"h4":case"h5":case"h6":case"p":document.execCommand("formatBlock",true,command);break;case"foreColor":case"backColor":document.execCommand(command,true,value);break;case"createlink":case"insertimage":url=prompt("Enter the link here: ","");if(url&&url.length){document.execCommand(command,false,url)}break;case"source":hideButtons(this.toolbarElements);me.parentNode.querySelector(".normal-button").style.display="flex";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");textArea.value=editArea.innerHTML;textArea.setAttribute("hidden",false);textArea.removeAttribute("hidden");editArea.setAttribute("hidden",true);break;case"normal":showButtons(this.toolbarElements);me.style.display="none";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");editArea.innerHTML=textArea.value;editArea.setAttribute("hidden",false);editArea.removeAttribute("hidden");textArea.setAttribute("hidden",true);break;default:document.execCommand(command,false,null);break}});for(let i=0;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=(element.value||element.innerHTML).trim();let valid=true;let validator=null;let func=null;let result=null;let message=null;for(let i=0,len=validators.length;i{this._runValidators(textarea,validators)},true);editarea.addEventListener("blur",()=>{this._runValidators(editarea,validators)},true);document.body.addEventListener(window.dmbEventsService.validate.listener,()=>{this._runValidators(textarea,validators);this._runValidators(editarea,validators)},true);document.body.addEventListener(window.dmbEventsService.resetValidation.listener,()=>{let elements=this.getElementsByClassName(this._errorWysiwygClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorWysiwygClass)}},true)}syncData(){let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");let editArea=this.querySelector("section.dmb-wysiwyg__content-content");if(textArea.hasAttribute("hidden")){textArea.value=editArea.innerHTML}else{editArea.innerHTML=textArea.value}}attributeChangedCallback(attr,oldValue,newValue){const textarea=this.querySelector("textarea.dmb-wysiwyg__content-content");const editarea=this.querySelector("section.dmb-wysiwyg__content-content");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(textarea)textarea.setAttribute("name",newValue);break;case"dmb-name":if(textarea)textarea.setAttribute("name",newValue);break;case"validate":if(textarea){textarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}if(editarea){editarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}break}}}customElements.define("dmb-wysiwyg",DmbWysiwyg);class DmbPageLoader extends DumboDirective{constructor(){super();window.addEventListener("beforeunload",()=>{this.classList.add("active")});document.addEventListener("readystatechange",()=>setTimeout(()=>{document.readyState==="complete"&&this.classList.contains("active")&&this.close()},100));document.addEventListener("DOMContentLoaded",()=>setTimeout(()=>{this.classList.contains("active")&&this.close()},100));window.addEventListener(window.dmbEventsService.pageLoaderClose.listener,()=>this.close());window.addEventListener("load",()=>this.close())}open(){!this.classList.contains("active")&&this.classList.add("active");return true}close(){this.classList.contains("active")&&this.classList.remove("active");return true}}customElements.define("dmb-page-loader",DmbPageLoader);class DmbContent extends DumboDirective{constructor(){super()}}customElements.define("dmb-content",DmbContent);class DmbView extends DumboDirective{constructor(){super()}}customElements.define("dmb-view",DmbView); \ No newline at end of file +class DmbForm extends DumboDirective{constructor(){super();this._valids=0;this.setTemplate('
');this.form=null;this.callback=this.callback||null}get valids(){return this._valids}init(){let inputs=null;let item=null;this.form=this.querySelector("form");this.form.setAttribute("method",this.getAttribute("method")||"POST");this.form.setAttribute("action",this.getAttribute("action")||"#");this.form.setAttribute("autocomplete",this.getAttribute("autocomplete")||"on");this.form.setAttribute("name",this.getAttribute("dmb-name")||"");this.form.setAttribute("target",this.getAttribute("target")||"");this.form.setAttribute("id",this.getAttribute("dmb-id")||this.generateId());this.form.setAttribute("enctype",this.getAttribute("enctype")||"application/x-www-form-urlencoded");inputs=[...this.querySelectorAll('input:not([type="submit"])')];if(this.querySelector('input[type="submit"]')===null||inputs.length>1){while(item=inputs.shift()){item.addEventListener("keypress",e=>{if(13===e.keyCode){this.submit()}})}}}reset(){this.form.reset()}validate(formElements,parentSelector){let item=null;let hasInvalids=false;formElements.forEach(element=>{element.closest(parentSelector).resetValidation()});this.dispatchEvent(window.DmbEvents.formBeforeValidate.event);while(item=formElements.shift()){if(item.closest(".novalidate")===null){item.closest(parentSelector).setValidation();if(!item.hasAttribute("valid")&&!item.hasAttribute("hidden")){item.reportValidity();item.focus();hasInvalids=true}else{this._valids++}}}this.dispatchEvent(window.DmbEvents.formAfterValidate.event);return!hasInvalids}submit(){this.dispatchEvent(window.DmbEvents.formSubmit.event);const inputs=[...this.querySelectorAll("dmb-input[validate] input")];const selects=[...this.querySelectorAll("dmb-select[validate] select")];const textAreas=[...this.querySelectorAll("dmb-text-area[validate] textarea")];const isAsync=this.hasAttribute("async");const form=this.querySelector("form");let totalvalidations=0;this._valids=0;totalvalidations=this.validate(inputs,"dmb-input")+this.validate(selects,"dmb-select")+this.validate(textAreas,"dmb-text-area");if(totalvalidations===3){if(isAsync){if(typeof this.callback==="function"){this.callback(this)}return false}else{form.submit()}return true}return false}getFormData(){return new FormData(this.form)}}customElements.define("dmb-form",DmbForm);class DmbHeader extends DumboDirective{constructor(){super()}init(){let titleDOM=null;if(this.title){titleDOM=document.createElement("h2");titleDOM.classList.add("dmb-header-title");titleDOM.textContent=this.title;this.prepend(titleDOM)}}}customElements.define("dmb-header",DmbHeader);class DmbSelect extends DumboDirective{static get observedAttributes(){return["valid","values","dmb-name","label","dmb-class","validate","dmb-value"]}constructor(){super();const template=""+"";this.setTemplate(template);this.validations={_required:value=>{let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error=""}return response}};this.isValid=false;this.valueList=[];this.validators=[];this._errorInputClass="_error"}set values(newValues=[]){this.valueList=newValues;this.buildOptions()}init(){const select=this.querySelector("select");let value=null;let options=null;let option=null;let opval=null;this.hasAttribute("label")&&(this.querySelector("label").innerText=this.getAttribute("label"));this.hasAttribute("label")&&select.setAttribute("aria-label",this.getAttribute("label"));this.hasAttribute("dmb-class")&&select.setAttribute("class",this.getAttribute("dmb-class"));select.setAttribute("name",this.getAttribute("dmb-name")||"");this.hasAttribute("validate")&&select.setAttribute("validate",this.getAttribute("validate"));select.id=this.getAttribute("dmb-id")||this.generateId();select.multiple=this.hasAttribute("multiple");if(this.hasAttribute("dmb-value")){value=this.getAttribute("dmb-value").trim();value=select.multiple?JSON.parse(value):value}if(select&&this.getAttribute("validate")){this.validators=this.buildValidators(select,this.getAttribute("validate"))}select.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});options=[...select.querySelectorAll("option")];if(options.length){while(option=options.shift()){option.value=(option.getAttribute("value")||"").trim();opval=isNaN(option.value)?option.value:parseInt(option.value);value=isNaN(value)?value:parseInt(value);if(!option.hasAttribute("selected")&&(opval&&opval==value)||Array.isArray(value)&&value.includes(opval)){option.setAttribute("selected",true);option.selected=true}}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let options=element.querySelectorAll("option");let content=[...options].filter(x=>x.selected).map(x=>x.value.trim()||"");let valid=true;let validator=null;let func=null;let result=null;!element.multiple&&(content=content[0]);for(var i=0,len=validators.length;i{const target=e.target;const classes=target.getAttribute("class");if(formTarget){form=document.querySelector(formTarget)}if(/paginate-page(-\w+)?/gm.test(classes)){if(form){e.preventDefault();form.setAttribute("action",e.target.getAttribute("href"));form.submit()}}})}}customElements.define("dmb-pagination",DmbPagination);class DmbInfoPop extends DumboDirective{constructor(){super();const template='
';this.setTemplate(template)}init(){const size=this.getAttribute("size")||"small";this.querySelector(".float-content").classList.add(`float-content_${size}`)}}customElements.define("dmb-info-pop",DmbInfoPop);class DmbDialog extends DumboDirective{static get observedAttributes(){return["open"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){this.openValue=newValue!==null}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(new Event("close"));this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(new Event("close-dialog"));return true}open(){this.hasAttribute("open")||this.setAttribute("open","");this.dispatchEvent(window.DmbEvents.dialogOpen.event)}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}init(){let delay=1e3*this.getAttribute("delay");this.hasAttribute("no-close")||this.setCloseButton();setTimeout(()=>{this.open()},delay)}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=this.querySelector(".close-modal-button");if(!icon||!icon.length){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");this.querySelector(".wrapper").prepend(icon);icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")})}}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}info(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("info");msg=msg||"";this.classList.add("info");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");if(typeof msg==="string"){message.innerHTML=msg}else{message.append(msg)}wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-dialog",fn)}}}customElements.define("dmb-dialog",DmbDialog);class DmbMenuButton extends DumboDirective{constructor(){super();let template=''+'';this.setTemplate(template)}init(){this.addEventListener("click",()=>{let menu=this.getAttribute("menu");if(menu.length){document.querySelector(menu).showModal()}})}}customElements.define("dmb-menu-button",DmbMenuButton);class DmbFooter extends DumboDirective{constructor(){super()}init(){const dmbview=this.parentNode.querySelector("dmb-content");if(dmbview){dmbview.classList.add("padded-footer")}}}customElements.define("dmb-footer",DmbFooter);class DmbInput extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name","label"]}constructor(){super();const template=""+'';this.setTemplate(template);this.isValid=false;this._errorInputClass="_error";this.validations={_required:function(value,param,input){let response={valid:true,error:null};param=null;if(typeof value==="undefined"||value===null||value===""||input.getAttribute("type")==="checkbox"&&!input.checked){response.valid=false}return response},_email:function(value){let response={valid:true,error:null},re=/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/;if(value&&!re.test(value)){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}set value(val){const input=this.querySelector("input");input.value=val}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("input");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":this.buildValidators();break;case"label":if(input){this.querySelector("label").innerText=newValue;input.setAttribute("aria-label",newValue);input.setAttribute("placeholder",newValue)}break}}buildValidators(){let validators=[];let validatorList=(this.getAttribute("validate")||"").split(",");const input=this.querySelector("input");for(let i=0,len=validatorList.length;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};const type=element.getAttribute("type");let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;if(type!=="file")element.value=content;while(validator=validators.shift()){func=this.validations["_"+validator.key]||unknownValidator;result=func(content,validator.param,validator.input);if(result.valid!==true){valid=false;break}}if(valid===true){element.parentNode.classList.remove(this._errorInputClass)}else{element.parentNode.classList.add(this._errorInputClass)}this.isValid=valid;valid?element.setAttribute("valid",""):element.removeAttribute("valid")}resetValidation(){let elements=this.getElementsByClassName(this._errorInputClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorInputClass)}}setValidation(){this._runValidators(this.querySelector("input"),this.buildValidators())}init(){const input=this.querySelector("input");const labelElement=this.querySelector("label");const label=this.getAttribute("label")||null;const placeholder=this.getAttribute("placeholder")||label;const masked=this.getAttribute("masked")||null;const autocomplete=this.getAttribute("autocomplete")||null;const classd=this.getAttribute("dmb-class")||null;const name=this.getAttribute("dmb-name")||null;const validate=this.getAttribute("validate")||null;const pattern=this.getAttribute("pattern")||null;const value=this.getAttribute("value")||this.getAttribute("dmb-value")||null;const step=this.getAttribute("step")||null;const type=this.getAttribute("type")||"text";const checked=this.hasAttribute("checked");input.id=this.getAttribute("dmb-id")||this.generateId();input.setAttribute("type",type);if(label){this.querySelector("label").innerText=label;input.setAttribute("aria-label",label)}if(placeholder){input.setAttribute("placeholder",placeholder)}if(labelElement){labelElement.setAttribute("for",input.id)}if(type==="checkbox"){this.insertBefore(input,labelElement);if(checked){input.setAttribute("checked","on")}}if(masked)input.setAttribute("masked",masked);if(autocomplete)input.setAttribute("autocomplete",autocomplete);if(classd)input.setAttribute("class",classd);if(name)input.setAttribute("name",name);if(validate)input.setAttribute("validate",validate);if(pattern)input.setAttribute("pattern",pattern);if(value)input.value=value;if(step)input.setAttribute("step",step);type==="file"&&this.hasAttribute("accept")&&input.setAttribute("accept",this.getAttribute("accept"));const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};const maskInputAlpha=e=>{const char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{const char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}this.buildValidators();input.addEventListener("blur",()=>{this.setValidation()},true)}}customElements.define("dmb-input",DmbInput);class DmbImageUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbimgInput=this.querySelector('dmb-input[type="file"]');const imgInput=dmbimgInput.querySelector('input[type="file"]');const previewimg=this.querySelector(".preview img");previewimg.setAttribute("alt",this.getAttribute("img-alt")||"Image Preview");this.hasAttribute("validate")&&dmbimgInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbimgInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbimgInput.setAttribute("label",this.getAttribute("label"));imgInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])})}loadFile(file){const previewimg=this.querySelector(".preview img");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();previewimg.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-image-uploader",DmbImageUploader);class DmbToggle extends DumboDirective{static get observedAttributes(){return["value"]}constructor(){super();const template='';this.setTemplate(template);this.val=0}set value(val=0){this.val=val;this.setStatus()}get value(){return this.val}attributeChangedCallback(attr,oldValue,newValue){switch(attr){case"value":this.val=parseInt(newValue);this.setStatus();break}}init(){this.val=parseInt(this.getAttribute("value")||"0");this.setStatus();this.addEventListener("click",()=>{this.val=1*!this.val;this.setStatus()})}setStatus(){if(this.val===1){this.classList.add("on")}else{this.classList.remove("on")}}click(method){if(typeof method==="function"){this.addEventListener("click",method)}}}customElements.define("dmb-toggle",DmbToggle);class DmbClosePanel extends DumboDirective{constructor(){super();const template='';this.setTemplate(template)}init(){const orientation=this.getAttribute("orientation")||"right";const icon=this.querySelector("i.icon");let panel=null;this.classList.add(orientation);icon.classList.add(`icon-chevron-${orientation}`);this.addEventListener("click",()=>{panel=this.closest("dmb-panel");panel.close()})}}customElements.define("dmb-close-panel",DmbClosePanel);class DmbVideoUploader extends DumboDirective{constructor(){super();const template=''+'
';this.setTemplate(template)}init(){const dmbVideoInput=this.querySelector('dmb-input[type="file"]');const videoInput=dmbVideoInput.querySelector('input[type="file"]');const willPreview=this.hasAttribute("preview")&&!!this.getAttribute("preview").length;this.hasAttribute("validate")&&dmbVideoInput.setAttribute("validate",this.getAttribute("validate"));this.hasAttribute("dmb-name")&&dmbVideoInput.setAttribute("dmb-name",this.getAttribute("dmb-name"));this.hasAttribute("label")&&dmbVideoInput.setAttribute("label",this.getAttribute("label"));willPreview&&videoInput.addEventListener("change",e=>{this.loadFile(e.target.files[0])});willPreview||this.querySelector(".preview video").remove()}loadFile(file){const videoComponent=this.querySelector(".preview video");const reader=new FileReader;const promise=new Promise(resolve=>{reader.onload=(()=>{resolve();videoComponent.setAttribute("src",reader.result.toString())})});reader.readAsDataURL(file);return promise}}customElements.define("dmb-video-uploader",DmbVideoUploader);class DmbPanel extends DumboDirective{static get observedAttributes(){return["source"]}constructor(){super();const template=''+"";this.setTemplate(template);this.returnValue=null}attributeChangedCallback(attr,oldValue,newValue){!!newValue&&newValue.length&&this.loadExternalSource()}loadExternalSource(){const url=this.getAttribute("source");let wrapper=null;let sourceRequest=null;if(url&&url.length){sourceRequest=new Request(url);fetch(sourceRequest).then(res=>res.text()).then(data=>{wrapper=this.querySelector(".wrapper");wrapper.innerHTML=data})}return true}close(value){this.returnValue=value;this.removeAttribute("open");this.dispatchEvent(window.DmbEvents.panelClose.event);this.localName==="dmb-dialog"&&this.remove();this.dispatchEvent(window.DmbEvents.dialogClose.event)}open(){this.setAttribute("open","");this.dispatchEvent(window.DmbEvents.panelOpened.event);this.addEventListener("click",e=>{if(this.openValue&&e.target===this){this.close("cancelled")}},true)}showModal(){const buttons=this.querySelectorAll('[type="modal-answer"]');[].forEach.call(buttons,button=>{button.addEventListener("click",e=>{this.close(e.target.getAttribute("value"))})});this.open()}setCloseButton(){let icon=null;if(!this.classList.contains("loader")){icon=document.createElement("i");icon.classList.add("icon");icon.classList.add("icon-cancel");icon.classList.add("close-modal-button");icon.addEventListener("click",e=>{e.target.closest("dmb-dialog").close("cancelled")});this.querySelector(".wrapper").prepend(icon)}}isOpen(){return this.openValue}setIcon(icon){const iconElement=document.createElement("i");const wrapper=this.querySelector(".wrapper");iconElement.classList.add("icon");iconElement.classList.add(`icon-${icon}`);wrapper.prepend(iconElement)}error(msg){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");this.setCloseButton();this.setIcon("alert");msg=msg||"";this.classList.add("error");message.classList.add("message");message.textContent=msg;wrapper.append(message)}prompt(options){const message=document.createElement("span");const wrapper=this.querySelector(".wrapper");let msg=options.message||"";this.classList.add("question");message.classList.add("message");message.textContent=msg;wrapper.append(message)}onClose(fn){if(typeof fn==="function"){this.addEventListener("close-panel",fn)}}init(){!this.classList.contains("right")&&!this.classList.contains("left")&&this.classList.add("right");!this.classList.contains("small")&&!this.classList.contains("large")&&this.classList.add("small");this.addEventListener("click",e=>{e.target===this&&this.close("cancelled")},true);this.loadExternalSource()}}customElements.define("dmb-panel",DmbPanel);class DmbTextArea extends DumboDirective{static get observedAttributes(){return["valid","name","validate","dmb-name"]}constructor(){super();const template=""+"";this.setTemplate(template);this.isValid=false;this.validators=[];this._errorInputClass="_error";this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false}return response},_numeric:function(value){let response={valid:true,error:null},re=/^[0-9]\d*/;if(value&&!re.test(value)){response.valid=false}return response},_min:function(value,param){let response={valid:true,error:null};if(value&&value.lengthparam){response.valid=false}return response}}}attributeChangedCallback(attr,oldValue,newValue){const input=this.querySelector("textarea");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(input)input.setAttribute("name",newValue);break;case"dmb-name":if(input)input.setAttribute("name",newValue);break;case"validate":if(input)input.setAttribute("validate",newValue);break}}init(){let input=this.getElementsByTagName("textarea").item(0);this.querySelector("label").innerText=this.getAttribute("label");input.setAttribute("aria-label",this.getAttribute("label")||"");input.setAttribute("masked",this.getAttribute("masked")||"");input.setAttribute("autocomplete",this.getAttribute("autocomplete")||"");input.setAttribute("class",this.getAttribute("dmb-class")||"");input.setAttribute("name",this.getAttribute("dmb-name")||"");input.setAttribute("validate",this.getAttribute("validate")||"");input.setAttribute("placeholder",this.getAttribute("placeholder")||"");input.setAttribute("valid","true");input.id=this.getAttribute("dmb-id")||this.generateId();const maskInputUppercase=e=>{e.target.value=e.target.value.toUpperCase()};if(input&&this.getAttribute("validate")){this.validators=this.buildValidators(input,this)}input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},{capture:true,passive:true});const maskInputAlpha=e=>{let char=e.which||e.keyCode;if((char<65||char>90)&&(char<97||char>122)){return false}};const maskInputNumeric=e=>{let char=e.which||e.keyCode;if(char<48||char>57){return false}};if(this.getAttribute("validate")){this.validators=this.buildValidators(input,this);input.addEventListener("blur",e=>{this._runValidators(e.target,this.validators)},true)}if(this.getAttribute("masked")){switch(this.getAttribute("masked")){case"alpha":input.onkeypress=maskInputAlpha;break;case"numeric":input.onkeypress=maskInputNumeric;break;case"uppercase":input.oninput=maskInputUppercase;break}}}_runValidators(element,validators){let unknownValidator=()=>{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=element.value.trim();let valid=true;let validator=null;let func=null;let result=null;element.value=content;for(var i=0,len=validators.length;i'+'H2'+'H3'+'H4'+'H5'+'H6'+''+''+''+''+''+''+''+''+''+'
'+''+'
'+"
"+'
'+''+'
'+"
"+'Source'+''+""+''+'
'+"
"+''+"";this.setTemplate(template);this.isValid=false;this._errorWysiwygClass="v_error";this.colorPalette=["000000","FF9966","6699FF","99FF66","CC0000","00CC00","0000CC","333333","0066FF","FFFFFF"];this.toolbarElements=[];this.validations={_required:function(value){let response={valid:true,error:null};if(typeof value==="undefined"||value===null||value===""){response.valid=false;response.error="Este campo es obligatorio"}return response}}}init(){const forePalette=this.querySelector(".palette .fore-palette");const backPalette=this.querySelector(".back-palette .fore-palette");let hideButtons=null;let showButtons=null;let executeCommand=null;let a=document.createElement("a");let ap=document.createElement("a");let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");this.toolbarElements=this.querySelectorAll(".dmb-wysiwyg__toolbar-button");a.dataset.command="foreColor";ap.dataset.command="backColor";a.setAttribute("href","#");ap.setAttribute("href","#");a.classList.add("palette-item");ap.classList.add("palette-item");a.classList.add("dmb-wysiwyg__toolbar-button");ap.classList.add("dmb-wysiwyg__toolbar-button");for(let i=0;i{for(let j=0;j{for(let j=0;j{const me=e.target;let command=me.dataset.command;let value=me.dataset.value;let url;let textArea;let editArea;e.stopImmediatePropagation();e.stopPropagation();e.preventDefault();switch(command){case"h2":case"h3":case"h4":case"h5":case"h6":case"p":document.execCommand("formatBlock",true,command);break;case"foreColor":case"backColor":document.execCommand(command,true,value);break;case"createlink":case"insertimage":url=prompt("Enter the link here: ","");if(url&&url.length){document.execCommand(command,false,url)}break;case"source":hideButtons(this.toolbarElements);me.parentNode.querySelector(".normal-button").style.display="flex";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");textArea.value=editArea.innerHTML;textArea.setAttribute("hidden",false);textArea.removeAttribute("hidden");editArea.setAttribute("hidden",true);break;case"normal":showButtons(this.toolbarElements);me.style.display="none";textArea=me.parentNode.parentNode.querySelector("textarea.dmb-wysiwyg__content-content");editArea=me.parentNode.parentNode.querySelector("section.dmb-wysiwyg__content-content");editArea.innerHTML=textArea.value;editArea.setAttribute("hidden",false);editArea.removeAttribute("hidden");textArea.setAttribute("hidden",true);break;default:document.execCommand(command,false,null);break}});for(let i=0;i{return{valid:false,error:'Unknown validator type: "'+(validator||{}).key+'"'}};let content=(element.value||element.innerHTML).trim();let valid=true;let validator=null;let func=null;let result=null;let message=null;for(let i=0,len=validators.length;i{this._runValidators(textarea,validators)},true);editarea.addEventListener("blur",()=>{this._runValidators(editarea,validators)},true);document.body.addEventListener(window.DmbEvents.validate.listener,()=>{this._runValidators(textarea,validators);this._runValidators(editarea,validators)},true);document.body.addEventListener(window.DmbEvents.resetValidation.listener,()=>{let elements=this.getElementsByClassName(this._errorWysiwygClass);for(let i=0;elements.length;i++){elements.item(0).classList.remove(this._errorWysiwygClass)}},true)}syncData(){let textArea=this.querySelector("textarea.dmb-wysiwyg__content-content");let editArea=this.querySelector("section.dmb-wysiwyg__content-content");if(textArea.hasAttribute("hidden")){textArea.value=editArea.innerHTML}else{editArea.innerHTML=textArea.value}}attributeChangedCallback(attr,oldValue,newValue){const textarea=this.querySelector("textarea.dmb-wysiwyg__content-content");const editarea=this.querySelector("section.dmb-wysiwyg__content-content");switch(attr){case"valid":this.isValid=newValue!==null;break;case"name":if(textarea)textarea.setAttribute("name",newValue);break;case"dmb-name":if(textarea)textarea.setAttribute("name",newValue);break;case"validate":if(textarea){textarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}if(editarea){editarea.setAttribute("validate",newValue);if(newValue&&newValue.length){this.setValidation()}}break}}}customElements.define("dmb-wysiwyg",DmbWysiwyg);class DmbPageLoader extends DumboDirective{constructor(){super();window.addEventListener("beforeunload",()=>{this.classList.add("active")});document.addEventListener("readystatechange",()=>setTimeout(()=>{document.readyState==="complete"&&this.classList.contains("active")&&this.close()},100));document.addEventListener("DOMContentLoaded",()=>setTimeout(()=>{this.classList.contains("active")&&this.close()},100));window.addEventListener(window.DmbEvents.pageLoaderClose.listener,()=>this.close());window.addEventListener("load",()=>this.close())}open(){!this.classList.contains("active")&&this.classList.add("active");return true}close(){this.classList.contains("active")&&this.classList.remove("active");return true}}customElements.define("dmb-page-loader",DmbPageLoader);class DmbContent extends DumboDirective{constructor(){super()}}customElements.define("dmb-content",DmbContent);class DmbView extends DumboDirective{constructor(){super()}}customElements.define("dmb-view",DmbView); \ No newline at end of file diff --git a/ui-sources/libs/dmb-factories.min.js b/ui-sources/libs/dmb-factories.min.js index c0713a0..c0d3bbd 100644 --- a/ui-sources/libs/dmb-factories.min.js +++ b/ui-sources/libs/dmb-factories.min.js @@ -1 +1 @@ -Window.prototype.dmbEventsService={panelClose:{event:new Event("dmb-panel.close"),listener:"dmb-panel.close"},panelOpen:{event:new Event("dmb-panel.open"),listener:"dmb-panel.open"},panelClosed:{event:new Event("dmb-panel.closed"),listener:"dmb-panel.closed"},panelOpened:{event:new Event("dmb-panel.opened"),listener:"dmb-panel.opened"},resetValidation:{event:new Event("dmb-validation.reset"),listener:"dmb-validation.reset"},validate:{event:new Event("dmb-validation.validate"),listener:"dmb-validation.validate"},pageLoaderClose:{event:new Event("dmb-page-loader.close"),listener:"dmb-page-loader.close"}};class DmbDialogService{setMessage(e,n){const d=document.createElement("span");return d.classList.add("message"),d.textContent=n,e.append(d),!0}open(){const e=document.createElement("dmb-dialog",{is:"dmb-dialog"});return document.body.append(e),e.showModal(),e}error(e){const n=document.createElement("dmb-dialog");return document.body.append(n),n.error(e),n.showModal(),n}info(e){const n=document.createElement("dmb-dialog");return document.body.append(n),n.info(e),n.showModal(),n}loader(){const e=document.createElement("dmb-dialog",{is:"dmb-dialog"});return e.classList.add("loader"),document.body.append(e),e.showModal(),e}drawer(e,n="small"){const d=document.createElement("dmb-dialog",{is:"dmb-dialog"});return d.classList.add("drawer"),d.classList.add(n),document.body.append(d),"string"==typeof e?d.querySelector(".wrapper").innerHTML=e:d.querySelector(".wrapper").append(e),d.setCloseButton(),d.showModal(),d}closeAll(){const e=document.querySelectorAll("dmb-dialog"),n=e.length;if(n)for(let d=0;d_cleanJS($file); file_put_contents(INST_PATH.'app/webroot/js/components.min.js', file_get_contents($file)."\n", FILE_APPEND); endwhile; + chmod(INST_PATH.'app/webroot/js/components.min.js', 0664); endif; }