aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hackl <hackl@data-quest.de>2025-01-27 15:52:02 +0000
committerThomas Hackl <hackl@data-quest.de>2025-01-27 15:52:02 +0000
commit9b2411a078a279cb4e24c0cc2ca78c032ad55e94 (patch)
tree58a7cb651133c20280d1d7253276feb8a92e2e01
parente4bf27a6e37efa3d7fd5decabacfd2dc94823aa6 (diff)
Resolve "Fehler bei der Anmeldeset-Verwaltung"
Closes #5086 Merge request studip/studip!3823
-rw-r--r--app/controllers/admin/courses.php1
-rw-r--r--app/controllers/admission/courseset.php13
-rw-r--r--app/controllers/admission/rule.php152
-rw-r--r--app/controllers/admission/ruleadministration.php1
-rw-r--r--app/controllers/admission/userlist.php1
-rw-r--r--app/controllers/course/admission.php105
-rw-r--r--app/controllers/course/details.php1
-rw-r--r--app/views/admission/rule/configure.php11
-rw-r--r--app/views/admission/rule/save.php23
-rw-r--r--app/views/admission/rule/select_type.php37
-rw-r--r--app/views/admission/rule/validate.php8
-rw-r--r--app/views/course/admission/instant_course_set.php5
-rw-r--r--lib/admissionrules/conditionaladmission/ConditionalAdmission.php20
-rw-r--r--lib/admissionrules/conditionaladmission/templates/configure.php3
-rw-r--r--lib/admissionrules/connectedcourseadmission/ConnectedcourseAdmission.class.php14
-rw-r--r--lib/admissionrules/connectedcourseadmission/templates/configure.php5
-rw-r--r--lib/admissionrules/coursememberadmission/CourseMemberAdmission.php21
-rw-r--r--lib/admissionrules/coursememberadmission/templates/configure.php3
-rw-r--r--lib/admissionrules/limitedadmission/LimitedAdmission.php17
-rw-r--r--lib/admissionrules/limitedadmission/templates/configure.php3
-rw-r--r--lib/admissionrules/lockedadmission/LockedAdmission.php13
-rw-r--r--lib/admissionrules/lockedadmission/templates/configure.php3
-rw-r--r--lib/admissionrules/participantrestrictedadmission/ParticipantRestrictedAdmission.php14
-rw-r--r--lib/admissionrules/participantrestrictedadmission/templates/configure.php5
-rw-r--r--lib/admissionrules/passwordadmission/PasswordAdmission.php10
-rw-r--r--lib/admissionrules/passwordadmission/templates/configure.php3
-rw-r--r--lib/admissionrules/preferentialadmission/PreferentialAdmission.php14
-rw-r--r--lib/admissionrules/preferentialadmission/templates/configure.php3
-rw-r--r--lib/admissionrules/termsadmission/TermsAdmission.php15
-rw-r--r--lib/admissionrules/termsadmission/templates/configure.php3
-rw-r--r--lib/admissionrules/timedadmission/TimedAdmission.php13
-rw-r--r--lib/admissionrules/timedadmission/templates/configure.php3
-rw-r--r--lib/classes/admission/AdmissionRule.php10
-rw-r--r--resources/assets/javascripts/bootstrap/admission.js19
-rw-r--r--resources/assets/javascripts/entry-admission.js1
-rw-r--r--resources/assets/javascripts/entry-base.js1
-rw-r--r--resources/assets/javascripts/lib/admission.js172
-rw-r--r--resources/assets/javascripts/studip-ui.js4
-rw-r--r--resources/assets/stylesheets/scss/admission.scss31
-rw-r--r--resources/vue/components/Quicksearch.vue3
-rw-r--r--resources/vue/components/StudipDialog.vue14
-rw-r--r--resources/vue/components/admission/AdmissionRuleConfig.vue20
-rw-r--r--resources/vue/components/admission/ConfigureCourseSet.vue37
-rw-r--r--resources/vue/components/admission/CourseMemberAdmission.vue7
-rw-r--r--resources/vue/components/admission/InstantCourseSet.vue102
-rw-r--r--resources/vue/components/admission/ParticipantRestrictedAdmission.vue37
-rw-r--r--resources/vue/components/admission/TimedAdmission.vue3
-rw-r--r--resources/vue/components/admission/ValidityTime.vue8
-rw-r--r--resources/vue/mixins/AdmissionRuleMixin.js2
-rw-r--r--templates/admission/rules/configure.php37
-rw-r--r--templates/admission/rules/input_end.php1
-rw-r--r--templates/admission/rules/input_start.php1
-rw-r--r--templates/forms/quicksearch_input.php2
-rw-r--r--webpack.common.js1
54 files changed, 253 insertions, 803 deletions
diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php
index 2ff2a9e..0d65e13 100644
--- a/app/controllers/admin/courses.php
+++ b/app/controllers/admin/courses.php
@@ -298,7 +298,6 @@ class Admin_CoursesController extends AuthenticatedController
PageLayout::setHelpKeyword('Basis.Veranstaltungen');
PageLayout::setTitle(_('Verwaltung von Veranstaltungen und Einrichtungen'));
// Add admission functions.
- PageLayout::addScript('studip-admission.js');
$this->max_show_courses = Config::get()->MAX_SHOW_ADMIN_COURSES;
}
diff --git a/app/controllers/admission/courseset.php b/app/controllers/admission/courseset.php
index 90ae5f5..c13791f 100644
--- a/app/controllers/admission/courseset.php
+++ b/app/controllers/admission/courseset.php
@@ -34,8 +34,6 @@ class Admission_CoursesetController extends AuthenticatedController
throw new AccessDeniedException();
}
- PageLayout::addScript('studip-admission.js');
-
$views = new ActionsWidget();
$views->addLink(
_('Anmeldeset anlegen'),
@@ -293,7 +291,8 @@ class Admission_CoursesetController extends AuthenticatedController
$this->myUserlists
)
),
- 'institute-search' => (string) $this->isearch
+ 'institute-search' => (string) $this->isearch,
+ 'instant-course-set-view' => $this->instant_course_set_view
];
if ($this->courseset) {
@@ -374,9 +373,9 @@ class Admission_CoursesetController extends AuthenticatedController
}
PageLayout::postSuccess(sprintf(_('Das Anmeldeset: %s wurde gespeichert'), htmlReady($courseset->getName())));
if ($this->instant_course_set_view) {
- $this->redirect($this->url_for('course/admission'));
+ $this->relocate('course/admission');
} else {
- $this->redirect($this->url_for('admission/courseset/configure', $courseset->getId()));
+ $this->relocate('admission/courseset/configure', $courseset->getId());
}
}
}
@@ -398,7 +397,7 @@ class Admission_CoursesetController extends AuthenticatedController
$this->courseset->delete();
}
- $this->redirect($this->url_for('admission/courseset'));
+ $this->relocate('admission/courseset');
}
/**
@@ -607,7 +606,7 @@ class Admission_CoursesetController extends AuthenticatedController
if ($ok) {
PageLayout::postSuccess(_('Die zugeordneten Veranstaltungen wurden konfiguriert.'));
}
- $this->redirect($this->url_for('admission/courseset/configure/' . $courseset->getId()));
+ $this->relocate('admission/courseset/configure/' . $courseset->getId());
return;
}
}
diff --git a/app/controllers/admission/rule.php b/app/controllers/admission/rule.php
deleted file mode 100644
index 2a41db4..0000000
--- a/app/controllers/admission/rule.php
+++ /dev/null
@@ -1,152 +0,0 @@
-<?php
-
-/**
- * Admission_RuleController - Admission rules
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * @author Thomas Hackl <thomas.hackl@uni-passau.de>
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @category Stud.IP
- * @since 3.0
- */
-
-class Admission_RuleController extends AuthenticatedController
-{
- /**
- * @see AuthenticatedController::before_filter
- */
- public function before_filter(&$action, &$args)
- {
- parent::before_filter($action, $args);
-
- if ($GLOBALS['perm']->have_perm('admin') || ($GLOBALS['perm']->have_perm('dozent') && Config::get()->ALLOW_DOZENT_COURSESET_ADMIN)) {
- Navigation::activateItem('/browse/coursesets');
- }
- PageLayout::setTitle(_('Anmeldesets'));
-
- }
-
- /**
- * Gets the template for the rule configuration form.
- *
- * @param String $ruleType Class name of the rule to configure.
- * @param String $ruleId Optional ID of an existing rule.
- */
- public function configure_action($ruleType = '', $ruleId = '')
- {
- $this->ruleTypes = AdmissionRule::getAvailableAdmissionRules();
- UserFilterField::getAvailableFilterFields();
- $this->ruleType = $ruleType;
- // Check if rule data has been given via request.
- if (Request::getArray('rules')) {
- $rule_siblings = [];
- foreach (Request::getManyObjects('rules', 'AdmissionRule') as $rule) {
- if ($ruleType == get_class($rule) && $rule->getId() == Request::get('ruleId')) {
- $this->rule = $rule;
- } else {
- $rule_siblings[$rule->getId()] = $rule;
- }
- }
- if (!$this->rule && in_array($ruleType, array_keys($this->ruleTypes))) {
- $this->rule = new $ruleType($ruleId);
- }
- $this->rule->setSiblings($rule_siblings);
- } elseif (Request::get('rule')) {
- $rule = Request::getObject('rule', 'AdmissionRule');
- if ($ruleType == get_class($rule)) {
- $this->rule = $rule;
- }
- } elseif (in_array($ruleType, array_keys($this->ruleTypes))) {
- $this->rule = new $ruleType($ruleId);
- }
- if ($this->rule) {
- $this->ruleTemplate = $this->rule->getTemplate();
- }
- }
-
- /**
- * Shows a form for selecting which rule type to use.
- *
- * @param String $cs_id ID of a courseset the rule shall belong to.
- */
- public function select_type_action($cs_id = '')
- {
- $this->ruleTypes = AdmissionRule::getAvailableAdmissionRules();
- $this->courseset = new CourseSet($cs_id);
- $this->courseset->clearAdmissionRules();
- foreach (Request::getManyObjects('rules', 'AdmissionRule') as $rule) {
- $this->courseset->addAdmissionRule($rule);
- }
- }
-
- /**
- * Saves the given rule.
- *
- * @param String $ruleType The class name of the configured rule.
- * @param String $ruleId ID of the rule to save, or empty if this is a new rule.
- */
- public function save_action($ruleType, $ruleId = '')
- {
- CSRFProtection::verifyUnsafeRequest();
-
- $this->rule = $this->loadRule($ruleType, $ruleId);
- $requestData = Request::getInstance();
- // Check for start and end date and parse the String values to timestamps.
- if (!empty($requestData['start_date'])) {
- $parsed = date_parse($requestData['start_date']);
- $timestamp = mktime($parsed['hour'], $parsed['minute'], 0,
- $parsed['month'], $parsed['day'], $parsed['year']);
- $requestData['start_time'] = $timestamp;
- }
- if (!empty($requestData['end_date'])) {
- $parsed = date_parse($requestData['end_date']);
- $timestamp = mktime($parsed['hour'], $parsed['minute'], 0,
- $parsed['month'], $parsed['day'], $parsed['year']);
- $requestData['end_time'] = $timestamp;
- }
- $this->rule->setAllData($requestData);
- }
-
- /**
- * Validates if the values given in the current request are sufficient to
- * configure a rule of the given type.
- *
- * @param String $ruleType Class name of the rule to check.
- * @param String $ruleId ID of the rule to save, or empty if this is a new rule.
- */
- public function validate_action($ruleType, $ruleId = '')
- {
- $rule = $this->loadRule($ruleType, $ruleId);
- $this->errors = $rule->validate(Request::getInstance());
- }
-
- /**
- * Loads a rule by string and ensures that it is a subclass of the abstract
- * admission rule.
- *
- * @param string $rule_type
- * @param string $rule_id
- * @return AdmissionRule
- */
- private function loadRule(string $rule_type, string $rule_id = ''): AdmissionRule
- {
- static $initialized = false;
-
- if (!$initialized) {
- // This is neccessary so that all admission rules are correctly
- // loaded and known to the system
- AdmissionRule::getAvailableAdmissionRules();
- $initialized = true;
- }
-
- if (!is_a($rule_type, AdmissionRule::class, true)) {
- throw new InvalidArgumentException('Rule type must be a subclass of ' . AdmissionRule::class);
- }
-
- return new $rule_type($rule_id);
- }
-}
diff --git a/app/controllers/admission/ruleadministration.php b/app/controllers/admission/ruleadministration.php
index 1a16910..a012aeb 100644
--- a/app/controllers/admission/ruleadministration.php
+++ b/app/controllers/admission/ruleadministration.php
@@ -27,7 +27,6 @@ class Admission_RuleadministrationController extends AuthenticatedController
$GLOBALS['perm']->check('root');
Navigation::activateItem('/admin/config/admissionrules');
- PageLayout::addScript('studip-admission.js');
$sidebar = Sidebar::Get();
diff --git a/app/controllers/admission/userlist.php b/app/controllers/admission/userlist.php
index 3192a50..25ad0ec 100644
--- a/app/controllers/admission/userlist.php
+++ b/app/controllers/admission/userlist.php
@@ -26,7 +26,6 @@ class Admission_UserlistController extends AuthenticatedController
PageLayout::setTitle(_('Personenlisten'));
Navigation::activateItem('/browse/coursesets/userlists');
- PageLayout::addScript('studip-admission.js');
Sidebar::get()->addWidget(new ActionsWidget())->addLink(
_('Personenliste anlegen'),
diff --git a/app/controllers/course/admission.php b/app/controllers/course/admission.php
index 94f8415..5b22c82 100644
--- a/app/controllers/course/admission.php
+++ b/app/controllers/course/admission.php
@@ -48,7 +48,6 @@ class Course_AdmissionController extends AuthenticatedController
$this->is_locked['write_level'] = 'disabled readonly';
}
AdmissionApplication::addMembers($this->course->id);
- PageLayout::addScript('studip-admission.js');
URLHelper::addLinkParam('return_to_dialog', Request::get('return_to_dialog'));
}
@@ -208,7 +207,7 @@ class Course_AdmissionController extends AuthenticatedController
}
}
if (empty($question)) {
- $this->redirect($this->action_url('index'));
+ $this->relocate($this->action_url('index'));
} else {
$this->button_yes = 'change_admission_prelim_yes';
$this->button_no = 'change_admission_prelim_no';
@@ -249,7 +248,7 @@ class Course_AdmissionController extends AuthenticatedController
PageLayout::postSuccess(_("Zugriff für externe Nutzer wurde geändert."));
}
}
- $this->redirect($this->action_url('index'));
+ $this->relocate($this->action_url('index'));
}
function change_admission_turnout_action()
@@ -313,7 +312,7 @@ class Course_AdmissionController extends AuthenticatedController
}
}
if (empty($question)) {
- $this->redirect($this->action_url('index'));
+ $this->relocate($this->action_url('index'));
} else {
$this->request = $request;
$this->button_yes = 'change_admission_turnout_yes';
@@ -338,7 +337,7 @@ class Course_AdmissionController extends AuthenticatedController
PageLayout::postSuccess(_('Die zugelassenen Nutzerdomänen wurden geändert.'));
}
}
- $this->redirect($this->action_url('index'));
+ $this->relocate($this->action_url('index'));
}
function change_course_set_action()
@@ -402,7 +401,7 @@ class Course_AdmissionController extends AuthenticatedController
}
}
if (empty($question)) {
- $this->redirect($this->action_url('index'));
+ $this->relocate($this->action_url('index'));
} else {
$this->request = ['change_course_set_unassign' => 1];
$this->button_yes = 'change_course_set_unassign_yes';
@@ -437,66 +436,40 @@ class Course_AdmissionController extends AuthenticatedController
$rule_types = AdmissionRule::getAvailableAdmissionRules(true);
if (isset($rule_types[$type])) {
$rule = new $type($rule_id);
- $another_rule = null;
- if (isset($rule_types[$another_type])) {
- $another_rule = new $another_type($another_rule_id);
- }
- $course_set = CourseSet::getSetForRule($rule_id) ?: new CourseSet();
- if ((Request::isPost() && Request::submitted('save')) || $rule instanceof LockedAdmission) {
- if ($rule instanceof LockedAdmission) {
- $course_set_id = CourseSet::getGlobalLockedAdmissionSetId();
- CourseSet::addCourseToSet($course_set_id, $this->course_id);
- PageLayout::postSuccess(_('Die Veranstaltung wurde gesperrt.'));
- $this->redirect($this->action_url('index'));
- return;
- } else {
- CSRFProtection::verifyUnsafeRequest();
- $errors = $rule->validate(Request::getInstance());
- if (empty($errors)) {
- $rule->setAllData(Request::getInstance());
- }
- if ($another_rule) {
- $another_errors = $another_rule->validate(Request::getInstance());
- if (empty($another_errors)) {
- $another_rule->setAllData(Request::getInstance());
- }
- $errors = array_merge($errors, $another_errors);
- }
- if (!mb_strlen(trim(Request::get('instant_course_set_name')))) {
- $errors[] = _("Bitte geben Sie einen Namen für die Anmelderegel ein!");
- } else {
- $course_set->setName(trim(Request::get('instant_course_set_name')));
- }
- if (count($errors)) {
- PageLayout::postError(_('Speichern fehlgeschlagen'), array_map('htmlready', $errors));
- } else {
- $rule->store();
- $course_set->setPrivate(true);
- $course_set->addAdmissionRule($rule);
- $course_set->setAlgorithm(new RandomAlgorithm());//TODO
- $course_set->setCourses([$this->course_id]);
- if ($another_rule) {
- $course_set->addAdmissionRule($another_rule);
- }
- $course_set->store();
- PageLayout::postSuccess(_("Die Anmelderegel wurde erzeugt und der Veranstaltung zugewiesen."));
- $this->redirect($this->action_url('index'));
- return;
- }
+
+ if ($type === 'LockedAdmission') {
+
+ $courseset = CourseSet::getGlobalLockedAdmissionSetId();
+ CourseSet::addCourseToSet($courseset, $this->course_id);
+
+ PageLayout::postSuccess(_('Die Veranstaltung wurde gesperrt.'));
+ $this->relocate('course/admission');
+
+ } else {
+
+ $another_rule = null;
+ if (isset($rule_types[$another_type])) {
+ $another_rule = new $another_type($another_rule_id);
}
+ $course_set = CourseSet::getSetForRule($rule_id) ?: new CourseSet();
+ $types = [$type];
+ if ($another_rule) {
+ $types[] = $another_type;
+ }
+ $course_set_name = $rule->getName() . ': ' . $this->course->name;
+
+ $props = [
+ 'rule-types' => $types,
+ 'course-set-name' => $course_set_name,
+ 'course-id' => $this->course_id
+ ];
+
+ $this->render_vue_app(
+ Studip\VueApp::create('admission/InstantCourseSet')
+ ->withProps($props)
+ );
+
}
- if (!$course_set->getId()) {
- $course_set->setName($rule->getName() . ': ' . $this->course->name);
- }
- $this->rule_template = $rule->getTemplate();
- $this->type = $type;
- $this->rule_id = $rule_id;
- if ($another_rule) {
- $this->type = $this->type . '_' . $another_type;
- $this->rule_id = $this->rule_id . '_' . $another_rule->getId();
- $this->rule_template = $this->rule_template . $another_rule->getTemplate();
- }
- $this->course_set_name = $course_set->getName();
} else {
throw new Trails\Exception(400);
}
@@ -510,7 +483,7 @@ class Course_AdmissionController extends AuthenticatedController
$response = $this->relay('admission/courseset/configure/' . $cs->getId());
$this->body = $response->body;
if (!empty($response->headers['Location'])) {
- $this->redirect($response->headers['Location']);
+ $this->relocate($response->headers['Location']);
}
} else {
throw new Trails\Exception(403);
@@ -525,7 +498,7 @@ class Course_AdmissionController extends AuthenticatedController
$response = $this->relay('admission/courseset/save/' . $cs->getId());
$this->body = $response->body;
if ($response->headers['Location']) {
- $this->redirect($response->headers['Location']);
+ $this->relocate($response->headers['Location']);
}
} else {
throw new Trails\Exception(403);
diff --git a/app/controllers/course/details.php b/app/controllers/course/details.php
index ab1c2a6..d8ac254 100644
--- a/app/controllers/course/details.php
+++ b/app/controllers/course/details.php
@@ -196,7 +196,6 @@ class Course_DetailsController extends AuthenticatedController
} else {
PageLayout::setHelpKeyword('Basis.InVeranstaltungDetails');
PageLayout::setTitle($this->title . ' - ' . _('Details'));
- PageLayout::addScript('studip-admission.js');
$sidebar = Sidebar::Get();
diff --git a/app/views/admission/rule/configure.php b/app/views/admission/rule/configure.php
deleted file mode 100644
index 64908ee..0000000
--- a/app/views/admission/rule/configure.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-use Studip\Button, Studip\LinkButton;
-
-/**
- * @var Admission_CoursesetController $controller
- * @var AdmissionRule $class
- * @var string $ruleTemplate
- */
-?>
-<div id="errormessage"></div>
- <?= $ruleTemplate ?>
diff --git a/app/views/admission/rule/save.php b/app/views/admission/rule/save.php
deleted file mode 100644
index 0f6e8d8..0000000
--- a/app/views/admission/rule/save.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/**
- * @var AdmissionRule $rule
- * @var Admission_CoursesetController $controller
- */
-?>
-<div class="hover_box admissionrule" id="rule_<?= $rule->getId() ?>">
- <div id="rule_data_<?= $rule->getId() ?>" class="col-3" style="margin-top: unset">
- <?= $rule->toString() ?>
- <input type="hidden" name="rules[]" value="<?= htmlReady(ObjectBuilder::exportAsJson($rule)) ?>"/>
- </div>
- <div class="action_icons col-1" id="rule_actions_<?= $rule->getId() ?>" style="margin-top: unset">
- <a href="#" onclick="return STUDIP.Admission.configureRule('<?= get_class($rule) ?>', '<?=
- $controller->url_for('admission/rule/configure', get_class($rule), $rule->getId()) ?>', '<?=
- $rule->getId() ?>')">
- <?= Icon::create('edit') ?>
- </a>
- <a href="javascript:STUDIP.Admission.removeRule('rule_<?= $rule->getId() ?>', 'rules')"
- data-confirm="<?= _('Soll die Anmelderegel wirklich gelöscht werden?') ?>">
- <?= Icon::create('trash') ?>
- </a>
- </div>
-</div>
diff --git a/app/views/admission/rule/select_type.php b/app/views/admission/rule/select_type.php
deleted file mode 100644
index 1a72a75..0000000
--- a/app/views/admission/rule/select_type.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<?php
-/**
- * @var AdmissionRule[] $ruleTypes
- * @var CourseSet $courseset
- * @var Admission_CoursesetController $controller
- */
-?>
-<form name="select_rule_type" class="default" action="<?= $controller->url_for('admission/rule/configure') ?>" method="post">
- <fieldset>
- <legend><?= _('Anmelderegel konfigurieren') ?></legend>
- <?php
- use Studip\Button, Studip\LinkButton;
-
- foreach ($ruleTypes as $className => $classDetail) {
- $disabled = $courseset && !$courseset->isAdmissionRuleAllowed($className) ? 'disabled' : '';
- ?>
- <section id="<?= $className ?>">
- <label>
- <input <?=$disabled ?> type="radio" name="ruletype" value="<?= $className ?>"/>
- <span <?=($disabled ? 'style="text-decoration:line-through"' : '')?>><?=$classDetail['name'] ?></span>
- <?= Icon::create('question-circle')->asImg(['title' => $classDetail['description']]) ?>
- </label>
- </section>
-
- <?php
- }
- ?>
- </fieldset>
-
- <footer data-dialog-button>
- <?= CSRFProtection::tokenTag() ?>
- <?= Button::create(_('Weiter >>'), 'configure', [
- 'onclick' => "return $('input[name=ruletype]:checked').val() ? STUDIP.Admission.configureRule($('input[name=ruletype]:checked').val(), '".
- $controller->url_for('admission/rule/configure')."') : false"]) ?>
- <?= LinkButton::createCancel(_('Abbrechen'), $controller->url_for('admission/courseset/configure'), ['onclick' => "STUDIP.Admission.closeDialog('configurerule'); return false;"]) ?>
- </footer>
-</form>
diff --git a/app/views/admission/rule/validate.php b/app/views/admission/rule/validate.php
deleted file mode 100644
index 4311d8d..0000000
--- a/app/views/admission/rule/validate.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-/**
- * @var array $errors
- */
-if ($errors) {
- echo MessageBox::error(_('Fehler:'), $errors);
-}
-?>
diff --git a/app/views/course/admission/instant_course_set.php b/app/views/course/admission/instant_course_set.php
index fdd9702..01409b3 100644
--- a/app/views/course/admission/instant_course_set.php
+++ b/app/views/course/admission/instant_course_set.php
@@ -8,8 +8,9 @@
<input type="hidden" name="rule_id" value="<?=htmlReady($rule_id)?>">
<fieldset>
<legend><?= _('Neue Anmelderegel erstellen') ?></legend>
- <?= $rule_template ?>
- <br>
+ <? foreach ($types as $type) : ?>
+ <admission-rule-config type="<?= htmlReady($type) ?>"></admission-rule-config>
+ <? endforeach ?>
<label class="caption"><?= _("Name für diese Anmelderegel")?></label>
<input type="text" name="instant_course_set_name" size="70" value="<?= htmlReady($course_set_name) ?>">
</fieldset>
diff --git a/lib/admissionrules/conditionaladmission/ConditionalAdmission.php b/lib/admissionrules/conditionaladmission/ConditionalAdmission.php
index 10bcb99..55aa317 100644
--- a/lib/admissionrules/conditionaladmission/ConditionalAdmission.php
+++ b/lib/admissionrules/conditionaladmission/ConditionalAdmission.php
@@ -198,24 +198,6 @@ class ConditionalAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate()
- {
- // Open generic admission rule template.
- $tpl = $GLOBALS['template_factory']->open('admission/rules/configure');
- $tpl->set_attribute('rule', $this);
- $factory = new Flexi\Factory(__DIR__ . '/templates/');
- // Now open specific template for this rule and insert base template.
- $tpl2 = $factory->open('configure');
- $tpl2->set_attribute('rule', $this);
- $tpl2->set_attribute('tpl', $tpl->render());
- return $tpl2->render();
- }
-
- /**
* Helper function for loading data from DB. Generic AdmissionRule data is
* loaded with the parent load() method.
*/
@@ -371,7 +353,7 @@ class ConditionalAdmission extends AdmissionRule
$obj->setValue($field['attributes']['value']);
$condition->addField($obj);
}
- $this->addCondition($condition, $data['conditiongroup_'.$condition->getId()], $data['quota_'.$data['conditiongroup_'.$condition->getId()]] ?? 0);
+ $this->addCondition($condition);
}
foreach ($data['grouped-conditions'] as $group) {
diff --git a/lib/admissionrules/conditionaladmission/templates/configure.php b/lib/admissionrules/conditionaladmission/templates/configure.php
deleted file mode 100644
index d4e7a14..0000000
--- a/lib/admissionrules/conditionaladmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div data-admission-rule="ConditionalAdmission">
- <conditional-admission></conditional-admission>
-</div>
diff --git a/lib/admissionrules/connectedcourseadmission/ConnectedcourseAdmission.class.php b/lib/admissionrules/connectedcourseadmission/ConnectedcourseAdmission.class.php
index 40f32ac..2bc8557 100644
--- a/lib/admissionrules/connectedcourseadmission/ConnectedcourseAdmission.class.php
+++ b/lib/admissionrules/connectedcourseadmission/ConnectedcourseAdmission.class.php
@@ -47,20 +47,6 @@ class ConnectedcourseAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate()
- {
- $factory = new Flexi\Factory(dirname(__FILE__).'/templates/');
- // Now open specific template for this rule and insert base template.
- $tpl = $factory->open('configure');
- $tpl->set_attribute('rule', $this);
- return $tpl->render();
- }
-
- /**
* Internal helper function for loading rule definition from database.
*/
public function load()
diff --git a/lib/admissionrules/connectedcourseadmission/templates/configure.php b/lib/admissionrules/connectedcourseadmission/templates/configure.php
deleted file mode 100644
index 4a60973..0000000
--- a/lib/admissionrules/connectedcourseadmission/templates/configure.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<h3><?= $rule->getName() ?></h3>
-<label for="message" class="caption">
- <?= _('Nachricht bei fehlgeschlagener Anmeldung') ?>:
-</label>
-<textarea name="message" rows="4" cols="50"><?= $rule->getMessage() ?></textarea> \ No newline at end of file
diff --git a/lib/admissionrules/coursememberadmission/CourseMemberAdmission.php b/lib/admissionrules/coursememberadmission/CourseMemberAdmission.php
index 00bccee..c1a4cb0 100644
--- a/lib/admissionrules/coursememberadmission/CourseMemberAdmission.php
+++ b/lib/admissionrules/coursememberadmission/CourseMemberAdmission.php
@@ -78,27 +78,6 @@ class CourseMemberAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate()
- {
- // Open generic admission rule template.
- $tpl = $GLOBALS['template_factory']->open('admission/rules/configure');
- $tpl->set_attribute('rule', $this);
-
- $search = new StandardSearch('Seminar_id');
-
- return $this->getTemplateFactory()->render('configure', [
- 'rule' => $this,
- 'tpl' => $tpl->render(),
- 'courses' => $this->getDecodedCourses(),
- 'search' => $search
- ]);
- }
-
- /**
* Helper function for loading rule definition from database.
*/
public function load()
diff --git a/lib/admissionrules/coursememberadmission/templates/configure.php b/lib/admissionrules/coursememberadmission/templates/configure.php
deleted file mode 100644
index a86150b..0000000
--- a/lib/admissionrules/coursememberadmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div data-admission-rule="CourseMemberAdmission">
- <course-member-admission></course-member-admission>
-</div>
diff --git a/lib/admissionrules/limitedadmission/LimitedAdmission.php b/lib/admissionrules/limitedadmission/LimitedAdmission.php
index c0339cc..20893d7 100644
--- a/lib/admissionrules/limitedadmission/LimitedAdmission.php
+++ b/lib/admissionrules/limitedadmission/LimitedAdmission.php
@@ -118,23 +118,6 @@ class LimitedAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate() {
- // Open generic admission rule template.
- $tpl = $GLOBALS['template_factory']->open('admission/rules/configure');
- $tpl->set_attribute('rule', $this);
- $factory = new Flexi\Factory(dirname(__FILE__).'/templates/');
- // Now open specific template for this rule and insert base template.
- $tpl2 = $factory->open('configure');
- $tpl2->set_attribute('rule', $this);
- $tpl2->set_attribute('tpl', $tpl->render());
- return $tpl2->render();
- }
-
- /**
* Internal helper function for loading rule definition from database.
*/
public function load() {
diff --git a/lib/admissionrules/limitedadmission/templates/configure.php b/lib/admissionrules/limitedadmission/templates/configure.php
deleted file mode 100644
index 5a2e0a9..0000000
--- a/lib/admissionrules/limitedadmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div data-admission-rule="LimitedAdmission">
- <limited-admission></limited-admission>
-</div>
diff --git a/lib/admissionrules/lockedadmission/LockedAdmission.php b/lib/admissionrules/lockedadmission/LockedAdmission.php
index afef13a..4330220 100644
--- a/lib/admissionrules/lockedadmission/LockedAdmission.php
+++ b/lib/admissionrules/lockedadmission/LockedAdmission.php
@@ -67,19 +67,6 @@ class LockedAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate() {
- $factory = new Flexi\Factory(dirname(__FILE__).'/templates/');
- // Now open specific template for this rule and insert base template.
- $tpl = $factory->open('configure');
- $tpl->set_attribute('rule', $this);
- return $tpl->render();
- }
-
- /**
* Internal helper function for loading rule definition from database.
*/
public function load() {
diff --git a/lib/admissionrules/lockedadmission/templates/configure.php b/lib/admissionrules/lockedadmission/templates/configure.php
deleted file mode 100644
index 5be3f66..0000000
--- a/lib/admissionrules/lockedadmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div data-admission-rule="LockedAdmission">
- <locked-admission></locked-admission>
-</div>
diff --git a/lib/admissionrules/participantrestrictedadmission/ParticipantRestrictedAdmission.php b/lib/admissionrules/participantrestrictedadmission/ParticipantRestrictedAdmission.php
index 2954602..924ce4f 100644
--- a/lib/admissionrules/participantrestrictedadmission/ParticipantRestrictedAdmission.php
+++ b/lib/admissionrules/participantrestrictedadmission/ParticipantRestrictedAdmission.php
@@ -101,20 +101,6 @@ class ParticipantRestrictedAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate()
- {
- $factory = new Flexi\Factory(dirname(__FILE__).'/templates/');
- // Open specific template for this rule and insert base template.
- $tpl = $factory->open('configure');
- $tpl->set_attribute('rule', $this);
- return $tpl->render();
- }
-
- /**
* Helper function for loading rule definition from database.
*/
public function load()
diff --git a/lib/admissionrules/participantrestrictedadmission/templates/configure.php b/lib/admissionrules/participantrestrictedadmission/templates/configure.php
deleted file mode 100644
index c2b50f3..0000000
--- a/lib/admissionrules/participantrestrictedadmission/templates/configure.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<div data-admission-rule="ParticipantRestrictedAdmission">
- <participant-restricted-admission :distribution="<?= $rule->getDistributionTime() ?>"
- :fcfs="<?= $rule->isFCFSAllowed() ? 'true' : 'false'?>"
- :hasPrios="false"></participant-restricted-admission>
-</div>
diff --git a/lib/admissionrules/passwordadmission/PasswordAdmission.php b/lib/admissionrules/passwordadmission/PasswordAdmission.php
index 85c6e2d..f94f1b4 100644
--- a/lib/admissionrules/passwordadmission/PasswordAdmission.php
+++ b/lib/admissionrules/passwordadmission/PasswordAdmission.php
@@ -175,10 +175,11 @@ class PasswordAdmission extends AdmissionRule
* @param Array $data
* @return AdmissionRule This object.
*/
- public function setAllData($data) {
+ public function setAllData($data)
+ {
parent::setAllData($data);
- if ($this->new || $data['password1'] !== '') {
- $this->setPassword($data['password1']);
+ if ($this->new || $data['password'] !== '') {
+ $this->setPassword($data['password']);
}
return $this;
}
@@ -189,7 +190,8 @@ class PasswordAdmission extends AdmissionRule
* @param String $clearText The clear text password to be set.
* @return PasswordAdmission
*/
- public function setPassword($clearText) {
+ public function setPassword($clearText)
+ {
$this->password = $this->hasher->HashPassword($clearText);
return $this;
}
diff --git a/lib/admissionrules/passwordadmission/templates/configure.php b/lib/admissionrules/passwordadmission/templates/configure.php
deleted file mode 100644
index 5a95b85..0000000
--- a/lib/admissionrules/passwordadmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div data-admission-rule="PasswordAdmission">
- <password-admission></password-admission>
-</div>
diff --git a/lib/admissionrules/preferentialadmission/PreferentialAdmission.php b/lib/admissionrules/preferentialadmission/PreferentialAdmission.php
index 9617f2b..c92677a 100644
--- a/lib/admissionrules/preferentialadmission/PreferentialAdmission.php
+++ b/lib/admissionrules/preferentialadmission/PreferentialAdmission.php
@@ -329,20 +329,6 @@ class PreferentialAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate()
- {
- $factory = new Flexi\Factory(__DIR__.'/templates/');
- // Now open specific template for this rule and insert base template.
- $tpl = $factory->open('configure');
- $tpl->set_attribute('rule', $this);
- return $tpl->render();
- }
-
- /**
* Helper function for loading data from DB. Generic AdmissionRule data is
* loaded with the parent load() method.
*/
diff --git a/lib/admissionrules/preferentialadmission/templates/configure.php b/lib/admissionrules/preferentialadmission/templates/configure.php
deleted file mode 100644
index 240e12c..0000000
--- a/lib/admissionrules/preferentialadmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div data-admission-rule="PreferentialAdmission">
- <preferential-admission></preferential-admission>
-</div>
diff --git a/lib/admissionrules/termsadmission/TermsAdmission.php b/lib/admissionrules/termsadmission/TermsAdmission.php
index 5e98513..3fda619 100644
--- a/lib/admissionrules/termsadmission/TermsAdmission.php
+++ b/lib/admissionrules/termsadmission/TermsAdmission.php
@@ -79,21 +79,6 @@ class TermsAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- * @throws Flexi\TemplateNotFoundException
- */
- public function getTemplate()
- {
- $factory = new Flexi\Factory(__DIR__ . '/templates');
- $template = $factory->open('configure');
- $template->rule = $this;
-
- return $template->render();
- }
-
- /**
* Does the current rule allow the given user to register as participant
* in the given course?
*
diff --git a/lib/admissionrules/termsadmission/templates/configure.php b/lib/admissionrules/termsadmission/templates/configure.php
deleted file mode 100644
index 48d4dfd..0000000
--- a/lib/admissionrules/termsadmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div data-admission-rule="TermsAdmission">
- <terms-admission terms="<?= htmlReady($rule->terms) ?>" id="<?= htmlReady($rule->getId()) ?>"></terms-admission>
-</div>
diff --git a/lib/admissionrules/timedadmission/TimedAdmission.php b/lib/admissionrules/timedadmission/TimedAdmission.php
index 69a828e..dad423f 100644
--- a/lib/admissionrules/timedadmission/TimedAdmission.php
+++ b/lib/admissionrules/timedadmission/TimedAdmission.php
@@ -96,19 +96,6 @@ class TimedAdmission extends AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate() {
- $factory = new Flexi\Factory(dirname(__FILE__).'/templates/');
- // Open specific template for this rule and insert base template.
- $tpl = $factory->open('configure');
- $tpl->set_attribute('rule', $this);
- return $tpl->render();
- }
-
- /**
* Helper function for loading rule definition from database.
*/
public function load() {
diff --git a/lib/admissionrules/timedadmission/templates/configure.php b/lib/admissionrules/timedadmission/templates/configure.php
deleted file mode 100644
index d39f6ab..0000000
--- a/lib/admissionrules/timedadmission/templates/configure.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<div id="admission-rule" data-admission-rule="TimedAdmission">
- <timed-admission :start="<?= $startTime ?: time() ?>" :end="<?= $endTime ?: (time() + 3600) ?>"></timed-admission>
-</div>
diff --git a/lib/classes/admission/AdmissionRule.php b/lib/classes/admission/AdmissionRule.php
index 9855165..28adfec 100644
--- a/lib/classes/admission/AdmissionRule.php
+++ b/lib/classes/admission/AdmissionRule.php
@@ -310,16 +310,6 @@ abstract class AdmissionRule
}
/**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate()
- {
- return '';
- }
-
- /**
* Internal helper function for loading rule definition from database.
*/
public function load()
diff --git a/resources/assets/javascripts/bootstrap/admission.js b/resources/assets/javascripts/bootstrap/admission.js
index c04ff24..2fff6cf 100644
--- a/resources/assets/javascripts/bootstrap/admission.js
+++ b/resources/assets/javascripts/bootstrap/admission.js
@@ -22,32 +22,15 @@ STUDIP.ready(function () {
components[ruleType] = result.default;
STUDIP.Vue.load().then(({ createApp }) => {
- createApp({
- el: container,
- components: components
- });
+ createApp({components}).mount(container);
});
});
}
});
- $(document).on('change', 'tr.course input', function() {
- STUDIP.Admission.toggleNotSavedAlert();
- });
-
$('a.userlist-delete-user').on('click', function() {
$(this).closest('tr').remove();
return false;
});
-
- $('#courseset-form .autosave').on('click', () => {
- STUDIP.Admission.autosaveCourseset();
- });
-
- STUDIP.ready(() => {
- $('#toggle-date-link').on('click', () => {
- $('#admissionrule-valid-date').toggleClass('hidden-js');
- });
- });
});
diff --git a/resources/assets/javascripts/entry-admission.js b/resources/assets/javascripts/entry-admission.js
deleted file mode 100644
index 5454d08..0000000
--- a/resources/assets/javascripts/entry-admission.js
+++ /dev/null
@@ -1 +0,0 @@
-import "./bootstrap/admission.js"
diff --git a/resources/assets/javascripts/entry-base.js b/resources/assets/javascripts/entry-base.js
index 2210471..db3d1f6 100644
--- a/resources/assets/javascripts/entry-base.js
+++ b/resources/assets/javascripts/entry-base.js
@@ -78,6 +78,7 @@ import "./bootstrap/oer.js"
import "./bootstrap/courseware.js"
import "./bootstrap/external_pages.js"
import "./bootstrap/vips.js"
+import "./bootstrap/admission.js"
import "./mvv_course_wizard.js"
import "./mvv.js"
diff --git a/resources/assets/javascripts/lib/admission.js b/resources/assets/javascripts/lib/admission.js
index 8c0413a..c735cb2 100644
--- a/resources/assets/javascripts/lib/admission.js
+++ b/resources/assets/javascripts/lib/admission.js
@@ -2,7 +2,6 @@
* Anmeldeverfahren und -sets
* ------------------------------------------------------------------------ */
import { $gettext } from './gettext';
-import Dialog from './dialog.js';
const Admission = {
@@ -46,143 +45,6 @@ const Admission = {
return false;
},
- configureRule: function(ruleType, targetUrl, ruleId) {
- var urlparts = targetUrl.split('?');
- targetUrl = urlparts[0] + '/' + ruleType;
- if (urlparts[1]) {
- targetUrl += '?' + urlparts[1];
- }
-
- Dialog.fromURL(targetUrl, {
- method: 'post',
- size: 'auto',
- title: $gettext('Anmelderegel konfigurieren'),
- id: 'configurerule',
- data: { ruleId: ruleId, rules: _.map($('#rules input[name="rules[]"]'), 'value') }
- });
-
- return false;
- },
-
- selectRuleType: function(source) {
- Dialog.fromURL(source, {
- title: $gettext('Anmelderegel konfigurieren'),
- size: 'auto',
- data: { rules: _.map($('#rules input[name="rules[]"]'), 'value') },
- method: 'post',
- id: 'configurerule'
- });
- return false;
- },
-
- saveRule: function(ruleId, targetId, targetUrl) {
- if ($('#action').val() !== 'cancel') {
- $.ajax({
- type: 'post',
- url: targetUrl,
- data: $('#ruleform').serialize(),
- dataType: 'html',
- success: function(data) {
- if (data !== '') {
- var result = '';
- if ($('#norules').length > 0) {
- $('#norules').remove();
- $('#' + targetId).prepend('<div id="rulelist"></div>');
- }
- result += data;
- if ($('#rule_' + ruleId).length !== 0) {
- $('#rule_' + ruleId).replaceWith(result);
- } else {
- $('#rulelist').append(result);
- }
- }
- },
- error: function(jqXHR, textStatus, errorThrown) {
- alert('Status: ' + textStatus + '\nError: ' + errorThrown);
- }
- });
- }
- Admission.closeDialog('configurerule');
- Admission.toggleNotSavedAlert();
- return false;
- },
-
- removeRule: function(targetId, containerId) {
- var parent = $('#' + targetId).parent();
- $('#' + targetId).remove();
- if (parent.children('div').length === 0) {
- parent.remove();
- var norules = $gettext('Sie haben noch keine Anmelderegeln festgelegt.');
- $('#' + containerId).prepend('<span id="norules">' + '<i>' + norules + '</i></span>');
- }
- Admission.toggleNotSavedAlert();
- },
-
- toggleRuleDescription: function(targetId) {
- $('#' + targetId).toggle();
- return false;
- },
-
- toggleDetails: function(arrowId, detailId) {
- var oldSrc = $('#' + arrowId).attr('src');
- var newSrc = $('#' + arrowId).attr('rel');
- $('#' + arrowId).attr('src', newSrc);
- $('#' + arrowId).attr('rel', oldSrc);
- $('#' + detailId).slideToggle();
- return false;
- },
-
- /**
- *
- * @param String ruleId The rule to save.
- * @param String errorTarget Target element ID where error messages will be
- * shown.
- * @param String validateUrl URL to call for validation.
- * @param String savedTarget Target element ID where the saved rule will be
- * displayed.
- * @param String saveUrl URL to save the rule.
- */
- checkAndSaveRule: function(ruleId, errorTarget, validateUrl, savedTarget, saveUrl) {
- if (Admission.validateRuleConfig(errorTarget, validateUrl)) {
- Admission.saveRule(ruleId, savedTarget, saveUrl);
- Dialog.close({ id: 'configurerule' });
- }
- return false;
- },
-
- validateRuleConfig: function(containerId, targetUrl) {
- var valid = true;
- var error = $.ajax({
- type: 'post',
- async: false,
- url: targetUrl,
- data: $('#ruleform').serialize(),
- dataType: 'html',
-
- error: function(jqXHR, textStatus, errorThrown) {
- alert('Status: ' + textStatus + '\nError: ' + errorThrown);
- }
- }).responseText;
- error = error.replace(/(\r\n|\n|\r)/gm, '');
- if ($.trim(error) != '') {
- $('#' + containerId).html(error);
- valid = false;
- }
- return valid;
- },
-
- removeUserFromUserlist: function(userId) {
- var parent = $('#user_' + userId).parent();
- $('#user_' + userId).remove();
- if (parent.children('li').length === 0) {
- var nousers = $gettext('Sie haben noch niemanden hinzugefügt.');
- $(parent)
- .parent()
- .append('<span id="nousers">' + '<i>' + nousers + '</i></span>');
- }
- return false;
- },
-
updateInstitutes: function(elementId, instURL, courseURL, mode) {
if (elementId !== '') {
var query = '';
@@ -208,26 +70,6 @@ const Admission = {
}
},
- checkRuleActivation: function(target) {
- var form = $('#' + target);
- var globalActivation = form.find('input[name=enabled]');
- if (globalActivation.prop('checked')) {
- $('#activation').show();
- if (form.find('input[name=activated]:checked').val() === 'studip') {
- $('#institutes_activation').hide();
- } else {
- $('#institutes_activation').show();
- }
- } else {
- $('#activation').hide();
- $('#institutes_activation').hide();
- }
- },
-
- closeDialog: function(elementId) {
- $('#' + elementId).remove();
- },
-
checkUncheckAll: function(inputName, mode) {
switch (mode) {
case 'check':
@@ -251,20 +93,6 @@ const Admission = {
toggleNotSavedAlert: function() {
$('.hidden-alert').show();
- },
-
- autosaveCourseset: function() {
- $.post({
- url: $('#courseset-form').attr('action'),
- data: $('#courseset-form').serialize() + '&submit=1',
- dataType: 'html',
- success: function() {
- $('.hidden-alert').hide();
- },
- error: function(jqXHR, textStatus, errorThrown) {
- alert('Status: ' + textStatus + '\nError: ' + errorThrown);
- }
- });
}
};
diff --git a/resources/assets/javascripts/studip-ui.js b/resources/assets/javascripts/studip-ui.js
index d6483f3..f563b31 100644
--- a/resources/assets/javascripts/studip-ui.js
+++ b/resources/assets/javascripts/studip-ui.js
@@ -11,7 +11,9 @@ import RestrictedDatesHelper from './lib/RestrictedDatesHelper';
$.widget( "ui.dialog", $.ui.dialog, {
_allowInteraction: function( event ) {
- return hasParentWhich(isCKBodyWrapper)(event.target) || this._super( event );
+ return hasParentWhich(isCKBodyWrapper)(event.target)
+ || event.target.closest('.studip-dialog') !== null
+ || this._super( event );
},
});
diff --git a/resources/assets/stylesheets/scss/admission.scss b/resources/assets/stylesheets/scss/admission.scss
index d9d978c..50fce65 100644
--- a/resources/assets/stylesheets/scss/admission.scss
+++ b/resources/assets/stylesheets/scss/admission.scss
@@ -1,17 +1,3 @@
-#rulelist div.admissionrule {
- display: list-item;
- list-style-type: disc;
- margin-left: 25px;
-}
-
-#toggle-date-container {
- margin-top: 10px;
-
- img, svg {
- vertical-align: text-bottom;
- }
-}
-
.hover_box {
div {
display: inline;
@@ -88,23 +74,6 @@ form.default {
}
}
-#userlists {
- div {
- margin-bottom: 10px;
-
- a {
- &.userlist-action {
- margin-left: 2px;
- margin-right: 2px;
- }
-
- img {
- vertical-align: bottom;
- }
- }
- }
-}
-
form {
fieldset {
section {
diff --git a/resources/vue/components/Quicksearch.vue b/resources/vue/components/Quicksearch.vue
index 1a61513..9177ae5 100644
--- a/resources/vue/components/Quicksearch.vue
+++ b/resources/vue/components/Quicksearch.vue
@@ -32,7 +32,7 @@
<script>
export default {
name: 'quicksearch',
- emits: ['update:modelValue'],
+ emits: ['update:modelValue', 'input'],
props: {
searchtype: {
type: String,
@@ -125,6 +125,7 @@ export default {
this.results = [];
this.$emit('update:modelValue', this.returnValue, this.inputValue);
+ this.$emit('input', this.returnValue, this.inputValue);
if (!this.keepValue) {
this.inputValue = '';
diff --git a/resources/vue/components/StudipDialog.vue b/resources/vue/components/StudipDialog.vue
index ab42f48..94f95ed 100644
--- a/resources/vue/components/StudipDialog.vue
+++ b/resources/vue/components/StudipDialog.vue
@@ -1,7 +1,7 @@
<template>
<Teleport to="body">
<focus-trap v-model="trap">
- <div class="studip-dialog" @keydown.esc="closeDialog">
+ <div class="studip-dialog" @keydown.esc="closeDialog" :style="{zIndex: zIndex}">
<transition name="dialog-fade">
<div class="studip-dialog-backdrop" v-if="true">
<vue-resizeable
@@ -170,6 +170,8 @@ export default {
handlers: ["r", "rb", "b", "lb", "l", "lt", "t", "rt"],
fit: false,
footerHeight: 68,
+
+ zIndex: null,
};
},
computed: {
@@ -279,6 +281,16 @@ export default {
this.$refs.buttonB.focus();
});
}
+ },
+ created() {
+ const maxZIndex = Array.from(document.querySelectorAll('.studip-dialog')).reduce(
+ (acc, el) => {
+ const style = getComputedStyle(el);
+ return Math.max(acc, Number.parseInt(style.zIndex, 10));
+ },
+ 1
+ );
+ this.zIndex = maxZIndex + 1;
}
};
</script>
diff --git a/resources/vue/components/admission/AdmissionRuleConfig.vue b/resources/vue/components/admission/AdmissionRuleConfig.vue
index 921a6c2..d6d6e65 100644
--- a/resources/vue/components/admission/AdmissionRuleConfig.vue
+++ b/resources/vue/components/admission/AdmissionRuleConfig.vue
@@ -1,5 +1,5 @@
<template>
- <studip-dialog v-if="component !== null"
+ <studip-dialog v-if="useDialog && component !== null"
:title="$gettext('Anmelderegel bearbeiten')"
:close-text="$gettext('Abbrechen')"
@close="cancel"
@@ -25,6 +25,18 @@
</button>
</template>
</studip-dialog>
+ <div v-if="!useDialog && component !== null">
+ <studip-message-box v-if="invalidData?.length"
+ type="error"
+ :details="invalidData"
+ :hide-close="true"
+ :hide-details="false"
+ :aria-description="errorText"
+ role="alert">
+ {{ $gettext('Es sind ungültige Daten angegeben worden:') }}
+ </studip-message-box>
+ <component :is="component" v-bind="props" @submit="submit" @error="error"></component>
+ </div>
</template>
<script>
@@ -32,7 +44,7 @@ import {shallowRef} from "vue";
export default {
name: 'AdmissionRuleConfig',
- emits: ['cancel', 'submit'],
+ emits: ['cancel', 'submit', 'error'],
props: {
type: {
type: String,
@@ -45,6 +57,10 @@ export default {
assignedRuleTypes: {
type: Array,
default: () => []
+ },
+ useDialog: {
+ type: Boolean,
+ default: true
}
},
data() {
diff --git a/resources/vue/components/admission/ConfigureCourseSet.vue b/resources/vue/components/admission/ConfigureCourseSet.vue
index 226de37..8bd46f3 100644
--- a/resources/vue/components/admission/ConfigureCourseSet.vue
+++ b/resources/vue/components/admission/ConfigureCourseSet.vue
@@ -327,7 +327,7 @@
</button>
<button class="button cancel"
type="button"
- data-dialog="close"
+ data-dialog-close
@click.prevent="cancel"
>
{{ $gettext('Abbrechen') }}
@@ -382,6 +382,10 @@ export default {
myUserLists: {
type: Array,
default: () => []
+ },
+ instantCourseSetView: {
+ type: Boolean,
+ default: false
}
},
data() {
@@ -413,7 +417,7 @@ export default {
computed: {
isStorable() {
return this.name !== ''
- && this.institutes.length > 0
+ && (this.courseSetId !== '' || this.courseSetId === '' && this.institutes.length > 0)
&& this.rules.length > 0;
},
hasConfigurableCourses() {
@@ -498,7 +502,7 @@ export default {
this.showRuleConfig = true;
},
addRuleConfiguration(data) {
- if (!this.ruleId) {
+ if (!this.ruleId || this.ruleId === data.type + '_') {
STUDIP.jsonapi.withPromises().post(
'admission-rules/' + data.type,
{
@@ -566,7 +570,7 @@ export default {
}
},
addInstitute(returnValue, inputValue) {
- if (!this.institutes.some(i => i.id === returnValue)) {
+ if (inputValue && !this.institutes.some(i => i.id === returnValue)) {
this.institutes.push({ id: returnValue, name: inputValue });
}
},
@@ -594,7 +598,11 @@ export default {
{ data: data }
).then(() => {
this.$refs.courseSetForm.dataset.secure = 'false';
- window.location = STUDIP.URLHelper.getURL('dispatch.php/admission/courseset');
+ if (!this.instantCourseSetView) {
+ window.location = STUDIP.URLHelper.getURL('dispatch.php/admission/courseset');
+ } else {
+ window.location.reload();
+ }
});
} else {
@@ -604,28 +612,31 @@ export default {
{ data: data}
).then(() => {
this.$refs.courseSetForm.dataset.secure = 'false';
- window.location = STUDIP.URLHelper.getURL('dispatch.php/admission/courseset');
+ if (!this.instantCourseSetView) {
+ window.location = STUDIP.URLHelper.getURL('dispatch.php/admission/courseset');
+ } else {
+ window.location.reload();
+ }
});
}
},
cancel() {
- window.location = STUDIP.URLHelper.getURL('dispatch.php/admission/courseset');
+ if (!this.instantCourseSetView) {
+ window.location = STUDIP.URLHelper.getURL('dispatch.php/admission/courseset');
+ }
},
- configureCourses()
- {
+ configureCourses() {
STUDIP.Dialog.fromURL(
STUDIP.URLHelper.getURL('dispatch.php/admission/courseset/configure_courses/' + this.courseSetId)
);
},
- getApplicants()
- {
+ getApplicants() {
STUDIP.Dialog.fromURL(
STUDIP.URLHelper.getURL('dispatch.php/admission/courseset/applications_list/' + this.courseSetId)
);
},
- messageApplicants()
- {
+ messageApplicants() {
STUDIP.Dialog.fromURL(
STUDIP.URLHelper.getURL('dispatch.php/admission/courseset/applicants_message/' + this.courseSetId)
);
diff --git a/resources/vue/components/admission/CourseMemberAdmission.vue b/resources/vue/components/admission/CourseMemberAdmission.vue
index 9e689c5..3684eb3 100644
--- a/resources/vue/components/admission/CourseMemberAdmission.vue
+++ b/resources/vue/components/admission/CourseMemberAdmission.vue
@@ -24,8 +24,7 @@
<quicksearch v-if="courseSearch !== null"
:searchtype="courseSearch"
name="course"
- :key="NaN"
- @input="addCourse"
+ @update:model-value="addCourse"
id="csearch"
ref="courseSearch"></quicksearch>
<ul v-if="courseList.length > 0">
@@ -89,7 +88,7 @@ export default {
return this.invalidData.length === 0;
},
},
- mounted() {
+ created() {
// Get a new rule instance so we can use quicksearch.
if (!this.id || this.id === '') {
STUDIP.jsonapi.withPromises().post('admission-rules/CourseMemberAdmission', {
@@ -97,7 +96,7 @@ export default {
data: {
attributes: {
payload: {
- mode: 0,
+ modus: 0,
courses: [],
message: ''
}
diff --git a/resources/vue/components/admission/InstantCourseSet.vue b/resources/vue/components/admission/InstantCourseSet.vue
new file mode 100644
index 0000000..ec555c6
--- /dev/null
+++ b/resources/vue/components/admission/InstantCourseSet.vue
@@ -0,0 +1,102 @@
+<template>
+ <form v-if="!working" class="default">
+ <section v-for="(type, index) in ruleTypes" :key="index">
+ <admission-rule-config :type="type"
+ :use-dialog="false"
+ @submit="ruleData"></admission-rule-config>
+ </section>
+ <section>
+ <label class="caption">
+ {{ $gettext("Name für diese Anmelderegel") }}
+ <input type="text" name="instant_course_set_name" size="70" v-model="name">
+ </label>
+ </section>
+ <footer data-dialog-button>
+ <button class="button accept" @click.prevent="triggerRules">
+ {{ $gettext('Speichern') }}
+ </button>
+ <button class="button cancel" data-dialog-close>
+ {{ $gettext('Abbrechen') }}
+ </button>
+ </footer>
+ </form>
+</template>
+
+<script>
+import AdmissionRuleConfig from './AdmissionRuleConfig';
+
+export default {
+ name: 'InstantCourseSet',
+ components: { AdmissionRuleConfig },
+ props: {
+ ruleTypes: {
+ type: Array,
+ required: true
+ },
+ courseSetName: {
+ type: String,
+ required: true
+ },
+ courseId: {
+ type: String,
+ required: true
+ }
+ },
+ data() {
+ return {
+ name: this.courseSetName,
+ rules: [],
+ working: false
+ }
+ },
+ methods: {
+ ruleData(data) {
+ this.working = true;
+ this.rules.push(data);
+
+ // Check if all rultTypes have some data. If yes, the whole courseset can be stored.
+ let canStore = true;
+ for (let i = 0 ; i < this.ruleTypes.length ; i++) {
+ if (this.rules.filter(rule => rule.type === this.ruleTypes[i]).length === 0) {
+ canStore = false;
+ }
+ }
+
+ if (canStore) {
+ this.store();
+ }
+ },
+ triggerRules() {
+ STUDIP.eventBus.emit('getRuleConfiguration');
+ },
+ store() {
+ const data = {
+ data: {
+ attributes: {
+ name: this.name,
+ private: true,
+ infotext: '',
+ institutes: [],
+ courses: [ this.courseId ],
+ rules: this.rules.map((rule) => { return { attributes: rule } } ),
+ userlists: []
+ }
+ }
+ };
+
+ STUDIP.jsonapi.withPromises().post(
+ 'course-sets',
+ { data: data }
+ ).then(() => {
+ STUDIP.Report.success(this.$gettext('Die Zugangsberechtigungen wurden gespeichert.'));
+ window.location = STUDIP.URLHelper.getURL('dispatch.php/course/admission', {cid: this.courseId});
+ });
+ }
+ },
+ created() {
+ for (let i = 0 ; i < this.ruleTypes.length ; i++) {
+ this.rules[this.ruleTypes[i]] = {};
+ }
+ }
+}
+</script>
diff --git a/resources/vue/components/admission/ParticipantRestrictedAdmission.vue b/resources/vue/components/admission/ParticipantRestrictedAdmission.vue
index 9f75b9a..96b6cfb 100644
--- a/resources/vue/components/admission/ParticipantRestrictedAdmission.vue
+++ b/resources/vue/components/admission/ParticipantRestrictedAdmission.vue
@@ -1,4 +1,4 @@
-<template>
+ <template>
<form class="default">
<section>
<label>
@@ -16,7 +16,7 @@
<section v-if="!fcfsAllowed || !fcfsEnabled">
<label>
{{ $gettext('Zeitpunkt der automatischen Platzverteilung') }}
- <datetimepicker v-if="loaded" :value="distributionTime" v-model="distributionTime"></datetimepicker>
+ <datetimepicker v-model="distributionTime"></datetimepicker>
</label>
</section>
</form>
@@ -24,17 +24,17 @@
<script>
import { AdmissionRuleMixin } from '../../mixins/AdmissionRuleMixin';
-import Datetimepicker from '../Datetimepicker.vue';
+import datetimepicker from '../Datetimepicker.vue';
import StudipTooltipIcon from '../StudipTooltipIcon.vue';
export default {
name: 'ParticipantRestrictedAdmission',
- components: { StudipTooltipIcon, Datetimepicker },
+ components: { StudipTooltipIcon, datetimepicker },
mixins: [AdmissionRuleMixin],
props: {
distribution: {
type: Number,
- default: Math.floor(new Date().getTime() / 1000 + 86400)
+ default: 0
},
fcfs: {
type: Boolean,
@@ -54,8 +54,7 @@ export default {
messageText: this.message,
fcfsAllowed: true,
fcfsEnabled: this.distributionTime === 0,
- distributionTime: this.distribution,
- loaded: false
+ distributionTime: this.distribution !== 0 ? this.distribution : Math.floor(Date.now() / 1000 + 7 * 86400)
}
},
computed: {
@@ -78,13 +77,23 @@ export default {
? data.attributes.payload['distribution-time']
: Math.floor(Date.now() / 1000 + 7 * 86400);
this.fcfsEnabled = data.attributes.payload['distribution-time'] === 0;
- this.loaded = true;
- }
- },
- created() {
- if (!this.id) {
- this.distributionTime = Math.floor(new Date().getTime() / 1000 + 86400);
- this.loaded = true;
+ },
+ validate() {
+ // Earliest possible date for seat distribution is 2 hours from now.
+ const earliest = new Date();
+ earliest.setHours( earliest.getHours() + 2);
+
+ if (!this.fcfsEnabled && this.distributionTime <= Math.floor(earliest.getTime() / 1000)) {
+ this.invalidData.push(
+ this.$gettext(
+ 'Geben Sie für die Platzverteilung ein Datum an, das weiter in der Zukunft liegt. ' +
+ 'Das frühestmögliche Datum ist %{earliest}.',
+ {earliest: earliest.toLocaleString('de-de')}
+ )
+ );
+ }
+
+ return this.invalidData.length === 0;
}
}
}
diff --git a/resources/vue/components/admission/TimedAdmission.vue b/resources/vue/components/admission/TimedAdmission.vue
index ebdc397..2437d7e 100644
--- a/resources/vue/components/admission/TimedAdmission.vue
+++ b/resources/vue/components/admission/TimedAdmission.vue
@@ -23,9 +23,10 @@
<script>
import { AdmissionRuleMixin } from '../../mixins/AdmissionRuleMixin';
-
+import datetimepicker from "../Datetimepicker.vue";
export default {
name: 'TimedAdmission',
+ components: { datetimepicker },
mixins: [ AdmissionRuleMixin ],
props: {
start: {
diff --git a/resources/vue/components/admission/ValidityTime.vue b/resources/vue/components/admission/ValidityTime.vue
index 067567c..32efd04 100644
--- a/resources/vue/components/admission/ValidityTime.vue
+++ b/resources/vue/components/admission/ValidityTime.vue
@@ -16,24 +16,24 @@
<section v-if="configureTime" class="col-3">
<label>
{{ $gettext('Diese Regel gilt von') }}
- <datetimepicker :value="startTime"></datetimepicker>
+ <datetimepicker v-model="startTime"></datetimepicker>
</label>
</section>
<section v-if="configureTime" class="col-3">
<label>
{{ $gettext('bis') }}
- <datetimepicker :value="endTime"></datetimepicker>
+ <datetimepicker v-model="endTime"></datetimepicker>
</label>
</section>
</div>
</template>
<script>
-import Datetimepicker from '../Datetimepicker.vue';
+import datetimepicker from '../Datetimepicker.vue';
export default {
name: 'ValidityTime',
- components: { Datetimepicker },
+ components: { datetimepicker },
props: {
start: {
type: Number,
diff --git a/resources/vue/mixins/AdmissionRuleMixin.js b/resources/vue/mixins/AdmissionRuleMixin.js
index 0badb1a..80f6ec5 100644
--- a/resources/vue/mixins/AdmissionRuleMixin.js
+++ b/resources/vue/mixins/AdmissionRuleMixin.js
@@ -42,7 +42,7 @@ export const AdmissionRuleMixin = {
}
}
},
- mounted() {
+ created() {
if (this.id && this.id !== '' && !this.ruleData) {
this.loadRuleData();
}
diff --git a/templates/admission/rules/configure.php b/templates/admission/rules/configure.php
deleted file mode 100644
index 4a74c1d..0000000
--- a/templates/admission/rules/configure.php
+++ /dev/null
@@ -1,37 +0,0 @@
-<label for="message" class="caption">
- <?= _('Nachricht bei fehlgeschlagener Anmeldung') ?>:
- <?= (mb_strpos($rule->getMessage(),'%s') ? tooltipicon(_("Die Zeichen %s sind ein Platzhalter für änderbare Bedingungen")) : '')?>
-</label>
-<textarea name="message" rows="4" cols="50"><?= htmlReady($rule->getMessage()) ?></textarea>
-<br/>
-<div id="toggle-date-container">
- <a href="#" id="toggle-date-link">
- <?= Icon::create('date') ?>
- <?= _('Gültigkeitszeitraum dieser Regel festlegen') ?>
- </a>
-</div>
-<div id="admissionrule-valid-date"<?= $rule->getStartTime() || $rule->getEndTime() ?
- '' : ' class="hidden-js"' ?>>
- <b><?= _('Hiermit verändern Sie nur, wann die in dieser Regel getroffenen ' .
- 'Einstellungen gelten sollen, und nicht den generellen Anmeldezeitraum!') ?></b>
- <section class="form_group hgroup">
- <label>
- <?= _('von') ?>
- <input type="text" maxlength="16" name="start_date" class="size-s no-hint"
- id="start_date" value="<?= $rule->getStartTime() ?
- date('d.m.Y H:i', $rule->getStartTime()) : '' ?>"
- placeholder="tt.mm.jjjj --:--" data-datetime-picker>
- </label>
- <label>
- <?= _('bis') ?>
- <input type="text" maxlength="16" name="end_date" class="size-s no-hint"
- id="end_date" value="<?= $rule->getEndTime() ?
- date('d.m.Y H:i', $rule->getEndTime()) : '' ?>"
- placeholder="tt.mm.jjjj --:--" data-datetimepicker='{">":"#start_date"}'>
- </label>
- <script>
- $('#start_date').datetimepicker();
- $('#end_date').datetimepicker();
- </script>
- </section>
-</div>
diff --git a/templates/admission/rules/input_end.php b/templates/admission/rules/input_end.php
deleted file mode 100644
index 26f0516..0000000
--- a/templates/admission/rules/input_end.php
+++ /dev/null
@@ -1 +0,0 @@
-</form> \ No newline at end of file
diff --git a/templates/admission/rules/input_start.php b/templates/admission/rules/input_start.php
deleted file mode 100644
index 8450192..0000000
--- a/templates/admission/rules/input_start.php
+++ /dev/null
@@ -1 +0,0 @@
-<form action="" method="post" class="default">
diff --git a/templates/forms/quicksearch_input.php b/templates/forms/quicksearch_input.php
index 46680a1..4788c69 100644
--- a/templates/forms/quicksearch_input.php
+++ b/templates/forms/quicksearch_input.php
@@ -10,7 +10,7 @@
<span>
<quicksearch value="<?= htmlReady($value) ?>"
name="<?= htmlReady($name) ?>"
- @update:modelValue="(new_id, new_item_name) => { console.log(new_id); this.<?= htmlReady($name) ?> = new_id; }"
+ @update:modelValue="(new_id, new_item_name) => { this.<?= htmlReady($name) ?> = new_id; }"
id="<?= $id ?>"
<?= ($this->required ? 'required aria-required="true"' : '') ?>
<?= $attributes ?>>
diff --git a/webpack.common.js b/webpack.common.js
index bded2cf..c18818d 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -11,7 +11,6 @@ const assetsPath = path.resolve(__dirname, "resources/assets/javascripts");
module.exports = {
entry: {
"studip-base": assetsPath + "/entry-base.js",
- "studip-admission": assetsPath + "/entry-admission.js",
"studip-statusgroups": assetsPath + "/entry-statusgroups.js",
"studip-wysiwyg": assetsPath + "/entry-wysiwyg.js",
"studip-installer": assetsPath + "/entry-installer.js",