From 502e6a104f200acc2f8ff81ba09257a6035406e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michaela=20Br=C3=BCckner?= Date: Tue, 2 Jan 2024 08:55:04 +0000 Subject: new registry formular, re #1559 Closes #3533 Merge request studip/studip!1141 --- app/controllers/registration.php | 133 ++++++++++++++++ app/views/registration/index.php | 1 + app/views/registration/save.php | 15 ++ .../5.5.19_update_username_regular_expression.php | 27 ++++ lib/classes/forms/ConfirmInput.php | 18 +++ lib/classes/forms/DatalistInput.php | 21 +++ lib/classes/forms/Form.php | 71 ++++++++- lib/classes/forms/Input.php | 30 +++- lib/classes/forms/Part.php | 4 + lib/classes/forms/PasswordInput.php | 18 +++ lib/classes/forms/RadioInput.php | 22 +++ lib/classes/forms/RangeInput.php | 3 + lib/navigation/LoginNavigation.php | 4 +- public/register1.php | 59 ------- public/register2.php | 49 ------ resources/assets/javascripts/bootstrap/forms.js | 154 ++++++++++++------ resources/assets/stylesheets/scss/forms.scss | 8 + templates/forms/confirm_password_input.php | 16 ++ templates/forms/datalist_input.php | 22 +++ templates/forms/form.php | 12 +- templates/forms/password_input.php | 16 ++ templates/forms/radio_input.php | 16 ++ templates/forms/range_input.php | 5 +- templates/forms/text_input.php | 13 +- templates/register/form.php | 175 --------------------- templates/register/step1.php | 6 - templates/register/success.php | 15 -- 27 files changed, 563 insertions(+), 370 deletions(-) create mode 100644 app/controllers/registration.php create mode 100644 app/views/registration/index.php create mode 100644 app/views/registration/save.php create mode 100644 db/migrations/5.5.19_update_username_regular_expression.php create mode 100644 lib/classes/forms/ConfirmInput.php create mode 100644 lib/classes/forms/DatalistInput.php create mode 100644 lib/classes/forms/PasswordInput.php create mode 100644 lib/classes/forms/RadioInput.php delete mode 100644 public/register1.php delete mode 100644 public/register2.php create mode 100644 templates/forms/confirm_password_input.php create mode 100644 templates/forms/datalist_input.php create mode 100644 templates/forms/password_input.php create mode 100644 templates/forms/radio_input.php delete mode 100644 templates/register/form.php delete mode 100644 templates/register/step1.php delete mode 100644 templates/register/success.php diff --git a/app/controllers/registration.php b/app/controllers/registration.php new file mode 100644 index 0000000..edb6b42 --- /dev/null +++ b/app/controllers/registration.php @@ -0,0 +1,133 @@ +registrationform = \Studip\Forms\Form::fromSORM( + $new_user, + [ + 'legend' => _('Herzlich willkommen!'), + 'fields' => [ + 'username' => [ + 'label' => _('Benutzername'), + 'required' => true, + 'maxlength' => '63', + 'validate' => function ($value, $input) { + if (!preg_match(Config::get()->USERNAME_REGULAR_EXPRESSION, $value)) { + return Config::get()->getMetadata('USERNAME_REGULAR_EXPRESSION')['comment'] ?: + _('Benutzername muss mindestens 4 Zeichen lang sein und darf nur aus Buchstaben, ' + . 'Ziffern, Unterstrich, @, Punkt und Minus bestehen.'); + } + $user = User::findByUsername($value); + $context = $input->getContextObject(); + if ($user && ($user->id !== $context->getId())) { + return _('Benutzername ist schon vergeben.'); + } + return true; + } + ], + 'password' => [ + 'label' => _('Passwort'), + 'type' => 'password', + 'required' => true, + 'maxlength' => '31', + 'minlength' => '8', + 'mapper' => function($value) { + $hasher = UserManagement::getPwdHasher(); + return $hasher->HashPassword($value); + } + ], + 'confirm_password' => [ + 'label' => _('Passwortbestätigung'), + 'type' => 'password', + 'required' => true, + 'maxlength' => '31', + 'minlength' => '8', + ':pattern' => "password.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&')", //mask special chars + 'data-validation_requirement' => _('Passwörter stimmen nicht überein.'), + 'store' => function() {} + ], + 'title_front' => [ + 'label' => _('Titel'), + 'type' => 'datalist', + 'options' => $GLOBALS['TITLE_FRONT_TEMPLATE'] + ], + 'title_rear' => [ + 'label' => _('Titel nachgestellt'), + 'type' => 'datalist', + 'options' => $GLOBALS['TITLE_REAR_TEMPLATE'], + ], + 'vorname' => [ + 'label' => _('Vorname'), + 'required' => true + ], + 'nachname' => [ + 'label' => _('Nachname'), + 'required' => true + ], + 'geschlecht' => [ + 'name' => 'geschlecht', + 'label' => _('Geschlecht'), + 'type' => 'radio', + 'orientation' => 'horizontal', + 'options' => [ + '0' => _('keine Angabe'), + '1' => _('männlich'), + '2' => _('weiblich'), + '3' => _('divers'), + ], + ], + 'email' => [ + 'label' => _('E-Mail'), + 'required' => true, + 'validate' => function ($value, $input) { + $user = User::findOneByEmail($value); + $context = $input->getContextObject(); + if ($user && ($user->id !== $context->getId())) { + return _('Diese Emailadresse ist bereits registriert.'); + } + return true; + } + ], + ] + ] + ); + $this->registrationform->setSaveButtonText(_('Registrierung abschließen')); + $this->registrationform->setCancelButtonText(_('Abbrechen')); + $this->registrationform->setCancelButtonName(URLHelper::getURL('index.php?cancel_login=1')); + + $this->registrationform->addStoreCallback( + function ($form) { + $new_user = $form->getLastPart()->getContextObject(); + + $GLOBALS['sess']->regenerate_session_id(['auth']); + $GLOBALS['auth']->unauth(); + $GLOBALS['auth']->auth['jscript'] = true; + $GLOBALS['auth']->auth['perm'] = $new_user['perms']; + $GLOBALS['auth']->auth['uname'] = $new_user['username']; + $GLOBALS['auth']->auth['auth_plugin'] = $new_user['auth_plugin']; + $GLOBALS['auth']->auth_set_user_settings($new_user->user_id); + $GLOBALS['auth']->auth['uid'] = $new_user['user_id']; + $GLOBALS['auth']->auth['exp'] = time() + (60 * $GLOBALS['auth']->lifetime); + $GLOBALS['auth']->auth['refresh'] = time() + (60 * $GLOBALS['auth']->refresh); + + Seminar_Register_Auth::sendValidationMail($new_user); + + return 1; + } + ); + + $this->registrationform->autoStore()->setURL(URLHelper::getURL('dispatch.php/start')); + } +} diff --git a/app/views/registration/index.php b/app/views/registration/index.php new file mode 100644 index 0000000..b253987 --- /dev/null +++ b/app/views/registration/index.php @@ -0,0 +1 @@ +render() ?> diff --git a/app/views/registration/save.php b/app/views/registration/save.php new file mode 100644 index 0000000..92eca8e --- /dev/null +++ b/app/views/registration/save.php @@ -0,0 +1,15 @@ +
+
+

+
+
+

+

+
+ +

+

+ ", "");?> +

+
+
diff --git a/db/migrations/5.5.19_update_username_regular_expression.php b/db/migrations/5.5.19_update_username_regular_expression.php new file mode 100644 index 0000000..cdcbc9d --- /dev/null +++ b/db/migrations/5.5.19_update_username_regular_expression.php @@ -0,0 +1,27 @@ +prepare("UPDATE `config` + SET `description` = 'Regulärer Ausdruck für erlaubte Zeichen in Benutzernamen. Das Kommentarfeld kann genutzt werden, um eine Fehlermeldung anzugeben, die zum Beispiel im Registrierungsformular ausgegeben wird, wenn der Ausdruck nicht erfüllt wird.' + WHERE `field` = 'USERNAME_REGULAR_EXPRESSION'"); + $stmt->execute(); + } + + public function down() + { + $db = DBManager::get(); + $stmt = $db->prepare("UPDATE `config` + SET `description` = 'Regex for allowed characters in usernames' + WHERE `field` = 'USERNAME_REGULAR_EXPRESSION'"); + $stmt->execute(); + + } +} diff --git a/lib/classes/forms/ConfirmInput.php b/lib/classes/forms/ConfirmInput.php new file mode 100644 index 0000000..13e3634 --- /dev/null +++ b/lib/classes/forms/ConfirmInput.php @@ -0,0 +1,18 @@ +open('forms/confirm_password_input'); + $template->title = $this->title; + $template->name = $this->name; + $template->value = $this->value; + $template->id = md5(uniqid()); + $template->required = $this->required; + $template->attributes = arrayToHtmlAttributes($this->attributes); + return $template->render(); + } +} diff --git a/lib/classes/forms/DatalistInput.php b/lib/classes/forms/DatalistInput.php new file mode 100644 index 0000000..06cc9e0 --- /dev/null +++ b/lib/classes/forms/DatalistInput.php @@ -0,0 +1,21 @@ +extractOptionsFromAttributes($this->attributes); + + $template = $GLOBALS['template_factory']->open('forms/datalist_input'); + $template->title = $this->title; + $template->name = $this->name; + $template->value = $this->value; + $template->id = md5(uniqid()); + $template->required = $this->required; + $template->attributes = arrayToHtmlAttributes($this->attributes); + $template->options = $options; + return $template->render(); + } +} diff --git a/lib/classes/forms/Form.php b/lib/classes/forms/Form.php index 49713b7..3b29552 100644 --- a/lib/classes/forms/Form.php +++ b/lib/classes/forms/Form.php @@ -17,6 +17,8 @@ class Form extends Part protected $save_button_text = ''; protected $save_button_name = ''; + protected $cancel_button_text = ''; + protected $cancel_button_name = ''; protected $autoStore = false; protected $debugmode = false; protected $success_message = ''; @@ -207,6 +209,31 @@ class Form extends Part return $this->save_button_name ?: $this->getSaveButtonText(); } + public function setCancelButtonText(string $text): Form + { + $this->cancel_button_text = $text; + return $this; + } + + /** + * @return string The text for the "save" button in the form. + */ + public function getCancelButtonText() : string + { + return $this->cancel_button_text ?: _('Abbrechen'); + } + + public function setCancelButtonName(string $name): Form + { + $this->cancel_button_name = $name; + return $this; + } + + public function getCancelButtonName() : string + { + return $this->cancel_button_name ?: $this->getCancelButtonText(); + } + public function setSuccessMessage(string $success_message): Form { $this->success_message = $success_message; @@ -250,12 +277,35 @@ class Form extends Part { $this->autoStore = true; if (\Request::isPost() && \Request::isAjax() && !\Request::isDialog()) { - $this->store(); - if ($this->success_message) { - \PageLayout::postSuccess($this->success_message); + if (\Request::submitted('STUDIPFORM_SERVERVALIDATION')) { + //verify the user input: + $output = []; + foreach ($this->getAllInputs() as $input) { + if ($input->validate) { + $callback = $input->getValidationCallback(); + $value = $this->getStorableValueFromRequest($input); + $valid = $callback($value, $input); + if ($valid !== true) { + $output[$input->getName()] = [ + 'name' => $input->getName(), + 'label' => $input->getTitle(), + 'error' => $callback($value, $input) + ]; + } + } + } + echo json_encode($output); + page_close(); + die(); + } else { + //storing the input + $this->store(); + if ($this->success_message) { + \PageLayout::postSuccess($this->success_message); + } + page_close(); + die(); } - page_close(); - die(); } return $this; } @@ -325,6 +375,17 @@ class Form extends Part $stored = 0; + foreach ($this->getAllInputs() as $input) { + if ($input->validate) { + $callback = $input->getValidationCallback(); + $value = $this->getStorableValueFromRequest($input); + $valid = $callback($value, $input); + if ($valid !== true) { + return $stored; + } + } + } + //store by each input $all_values = []; foreach ($this->getAllInputs() as $input) { diff --git a/lib/classes/forms/Input.php b/lib/classes/forms/Input.php index aa3069b..9d2ad32 100644 --- a/lib/classes/forms/Input.php +++ b/lib/classes/forms/Input.php @@ -11,6 +11,7 @@ abstract class Input protected $parent = null; public $mapper = null; public $store = null; + public $validate = null; public $if = null; public $permission = true; public $required = false; @@ -133,6 +134,21 @@ abstract class Input return $this->name; } + public function getTitle() + { + return $this->title; + } + + public function hasValidation() + { + return $this->validate !== null; + } + + public function getValidationCallback() + { + return $this->validate; + } + /** * Returns the value of this input. * @return null @@ -216,6 +232,18 @@ abstract class Input } /** + * Sets the server-side verify function of this input. The callable returns true if the given value is okay, or + * false or a textstring representing the error. + * @param callable $verify + * @return $this + */ + public function setValidationFunction(Callable $validate) + { + $this->validate = $validate; + return $this; + } + + /** * Sets a condition to display this input. The condition is a javascript condition which is used by vue to * hide the input if the condition is not satisfies. * @param string $if @@ -261,7 +289,7 @@ abstract class Input protected function extractOptionsFromAttributes(array &$attributes) { - $options = null; + $options = []; if (isset($attributes['options'])) { $options = $attributes['options']; unset($attributes['options']); diff --git a/lib/classes/forms/Part.php b/lib/classes/forms/Part.php index 3609eb4..fdca8f5 100644 --- a/lib/classes/forms/Part.php +++ b/lib/classes/forms/Part.php @@ -235,6 +235,7 @@ abstract class Part $attributes['type'], $attributes['mapper'], $attributes['store'], + $attributes['validate'], $attributes['if'], $attributes['permission'], $attributes['required'], @@ -257,6 +258,9 @@ abstract class Part if (isset($data['store']) && is_callable($data['store'])) { $input->store = $data['store']; } + if (isset($data['validate']) && is_callable($data['validate'])) { + $input->validate = $data['validate']; + } if (!empty($data['if'])) { $input->if = $data['if']; } diff --git a/lib/classes/forms/PasswordInput.php b/lib/classes/forms/PasswordInput.php new file mode 100644 index 0000000..68e4718 --- /dev/null +++ b/lib/classes/forms/PasswordInput.php @@ -0,0 +1,18 @@ +open('forms/password_input'); + $template->title = $this->title; + $template->name = $this->name; + $template->value = $this->value; + $template->id = md5(uniqid()); + $template->required = $this->required; + $template->attributes = arrayToHtmlAttributes($this->attributes); + return $template->render(); + } +} diff --git a/lib/classes/forms/RadioInput.php b/lib/classes/forms/RadioInput.php new file mode 100644 index 0000000..1945d87 --- /dev/null +++ b/lib/classes/forms/RadioInput.php @@ -0,0 +1,22 @@ +extractOptionsFromAttributes($this->attributes); + $template = $GLOBALS['template_factory']->open('forms/radio_input'); + $template->title = $this->title; + $template->name = $this->name; + $template->value = $this->value; + $template->id = md5(uniqid()); + $template->required = $this->required; + $template->options = $options; + $template->attributes = arrayToHtmlAttributes($this->attributes); + $template->orientation = $this->attributes['orientation']; + return $template->render(); + + } +} diff --git a/lib/classes/forms/RangeInput.php b/lib/classes/forms/RangeInput.php index 9f99d59..7a69e9e 100644 --- a/lib/classes/forms/RangeInput.php +++ b/lib/classes/forms/RangeInput.php @@ -11,6 +11,9 @@ class RangeInput extends Input $template->name = $this->name; $template->value = $this->value; $template->id = md5(uniqid()); + $template->min = $this->attributes['min']; + $template->max = $this->attributes['max']; + $template->step = $this->attributes['step']; $template->required = $this->required; $template->attributes = arrayToHtmlAttributes($this->attributes); return $template->render(); diff --git a/lib/navigation/LoginNavigation.php b/lib/navigation/LoginNavigation.php index 96ec90e..bb63a03 100644 --- a/lib/navigation/LoginNavigation.php +++ b/lib/navigation/LoginNavigation.php @@ -43,9 +43,9 @@ class LoginNavigation extends Navigation } if (Config::get()->ENABLE_SELF_REGISTRATION) { - $navigation = new Navigation(_('Registrieren'), 'register1.php'); + $navigation = new Navigation(_('Registrieren'), 'dispatch.php/registration'); $navigation->setDescription(_('um das System erstmalig zu nutzen')); - $this->addSubNavigation('register', $navigation); + $this->addSubNavigation('registration', $navigation); } if (Config::get()->ENABLE_FREE_ACCESS) { diff --git a/public/register1.php b/public/register1.php deleted file mode 100644 index 7b4740f..0000000 --- a/public/register1.php +++ /dev/null @@ -1,59 +0,0 @@ - - * @author Oliver Brakel - * @copyright 2000 authors - * @license GPL2 or any later version - */ - -require '../lib/bootstrap.php'; - -page_open([ - 'sess' => 'Seminar_Session', - 'auth' => 'Seminar_Default_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User', -]); - -include 'lib/seminar_open.php'; // initialise Stud.IP-Session - -if (!Config::get()->ENABLE_SELF_REGISTRATION) { - PageLayout::postError(_('Registrierung ausgeschaltet'), [ - _('In dieser Installation ist die Möglichkeit zur Registrierung ausgeschaltet.'), - sprintf( - '%s', - URLHelper::getLink('index.php'), - _('Hier geht es zur Startseite.') - ) - ]); - - echo $GLOBALS['template_factory']->render('layouts/base.php', [ - 'content_for_layout' => '', - ]); -} elseif (Config::get()->SHOW_TERMS_ON_FIRST_LOGIN) { - header('Location: ' . URLHelper::getURL('register2.php')); -} elseif ($GLOBALS['auth']->is_authenticated() && $GLOBALS['user']->id !== 'nobody') { - PageLayout::postError(_('Sie sind schon als BenutzerIn am System angemeldet!'), [ - sprintf( - '%s', - URLHelper::getLink('index.php'), - _('Hier geht es zur Startseite.') - ) - ]); - echo $GLOBALS['template_factory']->render('layouts/base.php', [ - 'content_for_layout' => '', - ]); -} else { - PageLayout::setHelpKeyword('Basis.AnmeldungRegistrierung'); - PageLayout::setTitle(_('Nutzungsbedingungen')); - echo $GLOBALS['template_factory']->render( - 'register/step1.php', - [], - $GLOBALS['template_factory']->open('layouts/base.php') - ); - $auth->logout(); -} - -page_close(); diff --git a/public/register2.php b/public/register2.php deleted file mode 100644 index 8d73c81..0000000 --- a/public/register2.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @author Oliver Brakel - * @copyright 2000 authors - * @license GPL2 or any later version - */ - -require '../lib/bootstrap.php'; - -page_open([ - 'sess' => 'Seminar_Session', - 'auth' => Config::get()->ENABLE_SELF_REGISTRATION ? 'Seminar_Register_Auth' : 'Seminar_Default_Auth', - 'perm' => 'Seminar_Perm', - 'user' => 'Seminar_User', -]); - -if (!Config::get()->ENABLE_SELF_REGISTRATION){ - PageLayout::postError(_('Registrierung ausgeschaltet'), [ - _('In dieser Installation ist die Möglichkeit zur Registrierung ausgeschaltet.'), - sprintf( - '%s', - URLHelper::getLink('index.php'), - _('Hier geht es zur Startseite.') - ) - ]); - - echo $GLOBALS['template_factory']->render('layouts/base.php', [ - 'content_for_layout' => '', - ]); -} elseif ($GLOBALS['auth']->auth['uid'] === 'nobody') { - $GLOBALS['auth']->logout(); - header('Location: ' . URLHelper::getURL('register2.php')); -} else { - include 'lib/seminar_open.php'; // initialise Stud.IP-Session - - PageLayout::setHelpKeyword('Basis.AnmeldungRegistrierung'); - PageLayout::setTitle(_('Registrierung erfolgreich')); - echo $GLOBALS['template_factory']->render( - 'register/success.php', - [], - $GLOBALS['template_factory']->open('layouts/base.php') - ); - $GLOBALS['auth']->logout(); -} - -page_close(); diff --git a/resources/assets/javascripts/bootstrap/forms.js b/resources/assets/javascripts/bootstrap/forms.js index b0e66d3..2cbac9e 100644 --- a/resources/assets/javascripts/bootstrap/forms.js +++ b/resources/assets/javascripts/bootstrap/forms.js @@ -250,12 +250,15 @@ STUDIP.ready(function () { data() { let params = JSON.parse(f.dataset.inputs); params.STUDIPFORM_REQUIRED = f.dataset.required ? JSON.parse(f.dataset.required) : []; + params.STUDIPFORM_SERVERVALIDATION = f.dataset.server_validation > 0; params.STUDIPFORM_DISPLAYVALIDATION = false; params.STUDIPFORM_VALIDATIONNOTES = []; params.STUDIPFORM_AUTOSAVEURL = f.dataset.autosave; params.STUDIPFORM_REDIRECTURL = f.dataset.url; - params.STUDIPFORM_SELECTEDLANGUAGES = {}; - params.STUDIPFORM_DEBUGMODE = JSON.parse(f.dataset.debugmode); + params.STUDIPFORM_INPUTS_ORDER = []; + for (let i in JSON.parse(f.dataset.inputs)) { + params.STUDIPFORM_INPUTS_ORDER.push(i); + } return params; }, methods: { @@ -265,31 +268,31 @@ STUDIP.ready(function () { this.STUDIPFORM_DISPLAYVALIDATION = true; //validation: - let validated = this.validate(); - - if (!validated) { - e.preventDefault(); - v.$el.scrollIntoView({ - "behavior": "smooth" - }); - return; - } - - if (this.STUDIPFORM_AUTOSAVEURL) { - let params = this.getFormValues(); + let validation_promise = this.validate(); + validation_promise.then(function (validated) { + if (!validated) { + v.$el.scrollIntoView({ + behavior: 'smooth' + }); + return; + } - $.ajax({ - url: this.STUDIPFORM_AUTOSAVEURL, - data: params, - type: 'post', - success() { - if (v.STUDIPFORM_REDIRECTURL && !v.STUDIPFORM_DEBUGMODE) { - window.location.href = v.STUDIPFORM_REDIRECTURL; + if (v.STUDIPFORM_AUTOSAVEURL) { + let params = v.getFormValues(); + + $.ajax({ + url: v.STUDIPFORM_AUTOSAVEURL, + data: params, + type: 'post', + success() { + if (v.STUDIPFORM_REDIRECTURL) { + window.location.href = v.STUDIPFORM_REDIRECTURL + } } - } - }); - e.preventDefault(); - } + }); + } + }); + e.preventDefault(); }, getFormValues() { let v = this; @@ -311,32 +314,74 @@ STUDIP.ready(function () { let v = this; this.STUDIPFORM_VALIDATIONNOTES = []; - let validated = this.$el.checkValidity(); - - $(this.$el).find('input, select, textarea').each(function () { - if (!this.validity.valid) { - let note = { - name: $(this.labels[0]).find('.textlabel').text(), - description: $gettext('Fehler!'), - describedby: this.id - }; - if (this.validity.tooShort) { - note.description = $gettextInterpolate( - $gettext('Geben Sie mindestens %{min} Zeichen ein.'), - {min: this.minLength} - ); - } - if (this.validity.valueMissing) { - if (this.type === 'checkbox') { - note.description = $gettext('Dieses Feld muss ausgewählt sein.'); - } else { - note.description = $gettext('Hier muss ein Wert eingetragen werden.'); + let validation_promise = new Promise(function (resolve, reject) { + let validated = v.$el.checkValidity(); + + $(v.$el).find('input, select, textarea').each(function () { + let name = $(this).attr('name'); + if (!this.validity.valid) { + let note = { + name: this.name, + label: $(this.labels[0]).find('.textlabel').text(), + description: $gettext('Fehler!'), + describedby: this.id + }; + if ($(this).data('validation_requirement')) { + note.description = $(this).data('validation_requirement'); + } + if (this.validity.tooShort) { + note.description = $gettextInterpolate( + $gettext('Geben Sie mindestens %{min} Zeichen ein.'), + {min: this.minLength} + ); + } + if (this.validity.valueMissing) { + if (this.type === 'checkbox') { + note.description = $gettext('Dieses Feld muss ausgewählt sein.'); + } else { + if (this.minLength > 0) { + note.description = $gettextInterpolate( + $gettext('Hier muss ein Wert mit mindestens %{min} Zeichen eingetragen werden.'), + {min: this.minLength} + ); + } else { + note.description = $gettext('Hier muss ein Wert eingetragen werden.'); + } + + } } + v.STUDIPFORM_VALIDATIONNOTES.push(note); } - v.STUDIPFORM_VALIDATIONNOTES.push(note); + }); + if (v.STUDIPFORM_SERVERVALIDATION) { + + let params = v.getFormValues(); + params.STUDIPFORM_SERVERVALIDATION = 1; + + $.ajax({ + url: v.STUDIPFORM_AUTOSAVEURL, + data: params, + type: 'post', + dataType: 'json', + success(output) { + for (let i in output) { + let note = { + name: output[i].name, + label: output[i].label, + description: output[i].error, + describedby: null + }; + v.STUDIPFORM_VALIDATIONNOTES.push(note); + } + validated = v.STUDIPFORM_VALIDATIONNOTES.length < 1; + resolve(validated); + } + }); + } else { + resolve(validated); } }); - return validated; + return validation_promise; }, setInputs(inputs) { for (const [key, value] of Object.entries(inputs)) { @@ -353,6 +398,19 @@ STUDIP.ready(function () { this.STUDIPFORM_SELECTEDLANGUAGES = languages; } }, + computed: { + ordererValidationNotes: function () { + let orderedNotes = []; + for (let i in this.STUDIPFORM_INPUTS_ORDER) { + for (let k in this.STUDIPFORM_VALIDATIONNOTES) { + if (this.STUDIPFORM_VALIDATIONNOTES[k].name === this.STUDIPFORM_INPUTS_ORDER[i]) { + orderedNotes.push(this.STUDIPFORM_VALIDATIONNOTES[k]); + } + } + } + return orderedNotes; + } + }, mounted () { $(this.$el).addClass("vueified"); } @@ -362,7 +420,7 @@ STUDIP.ready(function () { } // Well, this is really nasty: Select2 can't determine the select - // element's width if it is hidden (by itself or by it's parent). + // element's width if it is hidden (by itself or by its parent). // This is due to the fact that elements are not rendered when hidden // (which seems pretty obvious when you think about it) but elements // only have a width when they are rendered (pretty obvious as well). diff --git a/resources/assets/stylesheets/scss/forms.scss b/resources/assets/stylesheets/scss/forms.scss index 72e2d26..0b43f04 100644 --- a/resources/assets/stylesheets/scss/forms.scss +++ b/resources/assets/stylesheets/scss/forms.scss @@ -70,6 +70,14 @@ form.default { } } + input[list] { + @include background-icon(arr_1down, clickable); + + background-repeat: no-repeat; + background-position: center right 4px; + padding-right: 24px + } + textarea:not(.size-l) + .ck-editor { max-width: $max-width-m; } diff --git a/templates/forms/confirm_password_input.php b/templates/forms/confirm_password_input.php new file mode 100644 index 0000000..e2e2583 --- /dev/null +++ b/templates/forms/confirm_password_input.php @@ -0,0 +1,16 @@ +
+ +
diff --git a/templates/forms/datalist_input.php b/templates/forms/datalist_input.php new file mode 100644 index 0000000..7958c33 --- /dev/null +++ b/templates/forms/datalist_input.php @@ -0,0 +1,22 @@ +
+ + +
+ + diff --git a/templates/forms/form.php b/templates/forms/form.php index 05b0b30..96cd2c0 100644 --- a/templates/forms/form.php +++ b/templates/forms/form.php @@ -2,14 +2,17 @@ $inputs = []; $allinputs = $form->getAllInputs(); $required_inputs = []; +$server_validation = false; foreach ($allinputs as $input) { foreach ($input->getAllInputNames() as $name) { $inputs[$name] = $input->getValue(); } - if ($input->required) { $required_inputs[] = $input->getName(); } + if ($input->hasValidation()) { + $server_validation = true; + } } $form_id = md5(uniqid()); ?>
@submit="submit" + @cancel="" novalidate getDataSecure() ? 'data-secure' : '' ?> id="" data-inputs="" data-debugmode="getDebugMode())) ?>" data-required="" + data-server_validation="" class="default studipformisCollapsable() ? ' collapsable' : '' ?>"> 'securityToken']) ?> @@ -52,7 +57,7 @@ $form_id = md5(uniqid());
    -
  • {{ note.name + ": " + note.description }}
  • +
  • {{ note.label.trim() + ": " + note.description }}
@@ -64,7 +69,8 @@ $form_id = md5(uniqid());
- getSaveButtonText(), $form->getSaveButtonName(), ['form' => $form_id]) ?> + getSaveButtonText(), $form->getSaveButtonName(), ['form' => $form_id]) ?> + getCancelButtonText(), $form->getCancelButtonName()) ?>
diff --git a/templates/forms/password_input.php b/templates/forms/password_input.php new file mode 100644 index 0000000..e2e2583 --- /dev/null +++ b/templates/forms/password_input.php @@ -0,0 +1,16 @@ +
+ +
diff --git a/templates/forms/radio_input.php b/templates/forms/radio_input.php new file mode 100644 index 0000000..37170c9 --- /dev/null +++ b/templates/forms/radio_input.php @@ -0,0 +1,16 @@ +
+
orientation == 'horizontal' ? 'class="hgroup"' : '' ?> for=""> + + title) ?> + + + $option) : ?> + + +
+
diff --git a/templates/forms/range_input.php b/templates/forms/range_input.php index c85b02d..07bd934 100644 --- a/templates/forms/range_input.php +++ b/templates/forms/range_input.php @@ -10,4 +10,7 @@ name="" value="" id="" - > + min="" + max="" + step="" + > diff --git a/templates/forms/text_input.php b/templates/forms/text_input.php index ae93758..3104ee8 100644 --- a/templates/forms/text_input.php +++ b/templates/forms/text_input.php @@ -6,11 +6,12 @@ required) : ?> + required ? 'required aria-required="true"' : '') ?> + > - required ? 'required aria-required="true"' : '') ?> - > + diff --git a/templates/register/form.php b/templates/register/form.php deleted file mode 100644 index 137cd05..0000000 --- a/templates/register/form.php +++ /dev/null @@ -1,175 +0,0 @@ -EMAIL_DOMAIN_RESTRICTION; -?> - - - - - - -

- -
- - - -
- - -

- - - - - - - - -
- - - -
- - -
- - - -
- - - - - -
- -
- -
- - - - - - - -
- - - - - -
- - -
- -
- -
- - -
-
diff --git a/templates/register/step1.php b/templates/register/step1.php deleted file mode 100644 index b67116e..0000000 --- a/templates/register/step1.php +++ /dev/null @@ -1,6 +0,0 @@ -render('terms.php') ?> - -
- - -
diff --git a/templates/register/success.php b/templates/register/success.php deleted file mode 100644 index 92eca8e..0000000 --- a/templates/register/success.php +++ /dev/null @@ -1,15 +0,0 @@ -
-
-

-
-
-

-

-
- -

-

- ", "");?> -

-
-
-- cgit v1.0