aboutsummaryrefslogtreecommitdiff
path: root/app/views/course/statusgroups
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+github@gmail.com>2021-07-22 16:07:19 +0200
committerJan-Hendrik Willms <tleilax+github@gmail.com>2021-07-22 16:19:12 +0200
commita3da1483a9e689846179159355badfec8073dbec (patch)
tree770dcca6bdf5f6f2a11b0e7fcbbeda6919a3fc52 /app/views/course/statusgroups
current code from svn, revision 62608
Diffstat (limited to 'app/views/course/statusgroups')
-rw-r--r--app/views/course/statusgroups/_askcancel_members.php16
-rw-r--r--app/views/course/statusgroups/_askdelete_groups.php22
-rw-r--r--app/views/course/statusgroups/_askdelete_members.php17
-rw-r--r--app/views/course/statusgroups/_copy_members.php25
-rw-r--r--app/views/course/statusgroups/_edit_groups_selfassign.php42
-rw-r--r--app/views/course/statusgroups/_edit_groups_size.php24
-rw-r--r--app/views/course/statusgroups/_group.php142
-rw-r--r--app/views/course/statusgroups/_member.php85
-rw-r--r--app/views/course/statusgroups/_move_members.php25
-rw-r--r--app/views/course/statusgroups/batch_action.php28
-rw-r--r--app/views/course/statusgroups/create_groups.php146
-rw-r--r--app/views/course/statusgroups/edit.php117
-rw-r--r--app/views/course/statusgroups/getgroup.php134
-rw-r--r--app/views/course/statusgroups/groupinfo.php101
-rw-r--r--app/views/course/statusgroups/index.php43
-rw-r--r--app/views/course/statusgroups/joinables.php18
-rw-r--r--app/views/course/statusgroups/move_member.php2
17 files changed, 987 insertions, 0 deletions
diff --git a/app/views/course/statusgroups/_askcancel_members.php b/app/views/course/statusgroups/_askcancel_members.php
new file mode 100644
index 0000000..7c03836
--- /dev/null
+++ b/app/views/course/statusgroups/_askcancel_members.php
@@ -0,0 +1,16 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_cancel_members') ?>" method="post">
+ <section>
+ <?= sprintf(ngettext('Soll %u Person wirklich aus %s ausgetragen werden?',
+ 'Sollen %u Personen wirklich aus %s ausgetragen werden?',
+ count($members)), count($members), htmlReady($course_title)) ?>
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ </section>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Austragen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_askdelete_groups.php b/app/views/course/statusgroups/_askdelete_groups.php
new file mode 100644
index 0000000..33ec794
--- /dev/null
+++ b/app/views/course/statusgroups/_askdelete_groups.php
@@ -0,0 +1,22 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_delete_groups') ?>" method="post">
+ <header>
+ <h1>
+ <?= ngettext('Soll die folgende Gruppe wirklich gelöscht werden?',
+ 'Sollen die folgenden Gruppen wirklich gelöscht werden?', count($groups)) ?>
+ </h1>
+ <ul>
+ <?php foreach ($groups as $g) : ?>
+ <li>
+ <input type="hidden" name="groups[]" value="<?= $g->id ?>">
+ <?= htmlReady($g->name) ?>
+ </li>
+ <?php endforeach ?>
+ </ul>
+ </header>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Löschen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_askdelete_members.php b/app/views/course/statusgroups/_askdelete_members.php
new file mode 100644
index 0000000..5023ffd
--- /dev/null
+++ b/app/views/course/statusgroups/_askdelete_members.php
@@ -0,0 +1,17 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_delete_members',
+ $source_group->id) ?>" method="post">
+ <section>
+ <?= sprintf(ngettext('Soll %u Person wirklich aus %s entfernt werden?',
+ 'Sollen %u Personen wirklich aus %s entfernt werden?',
+ count($members)), count($members), htmlReady($source_group->name)) ?>
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ </section>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Entfernen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_copy_members.php b/app/views/course/statusgroups/_copy_members.php
new file mode 100644
index 0000000..d30308a
--- /dev/null
+++ b/app/views/course/statusgroups/_copy_members.php
@@ -0,0 +1,25 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_copy_members') ?>" method="post">
+ <label for="target_group">
+ <?= sprintf(ngettext(
+ 'In welche Gruppe soll die gewählte Person kopiert werden?',
+ 'In welche Gruppe sollen die %u gewählten Personen kopiert werden?',
+ count($members)),
+ count($members)) ?>
+ <select name="target_group">
+ <?php foreach ($target_groups as $g) : ?>
+ <option value="<?= $g->id ?>"><?= htmlReady($g->name) ?></option>
+ <?php endforeach ?>
+ </select>
+ </label>
+
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ <input type="hidden" name="source" value="<?= $source_group ?>"/>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Kopieren'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/_edit_groups_selfassign.php b/app/views/course/statusgroups/_edit_groups_selfassign.php
new file mode 100644
index 0000000..d5c31d1
--- /dev/null
+++ b/app/views/course/statusgroups/_edit_groups_selfassign.php
@@ -0,0 +1,42 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_save_groups_selfassign') ?>" method="post">
+ <label>
+ <input type="checkbox" name="selfassign" value="1"<?= $selfassign == 1 ? ' checked' : '' ?>>
+ <?= _('Selbsteintrag erlaubt') ?>
+ <?= $selfassign == -1 ? '<br>(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="exclusive" value="1"<?= $exclusive == 1 ? ' checked' : '' ?>>
+ <?= _('Exklusiver Selbsteintrag (in nur eine Gruppe)') ?>
+ <?= $exclusive == -1 ? '<br>(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <label class="col-3" style="vertical-align: top">
+ <?= _('Selbsteintrag erlaubt ab') ?>
+ <input type="text" class="size-s" data-datetime-picker id="selfassign_start" size="20" name="selfassign_start" value="<?= $selfassign_start != -1 ?
+ $selfassign_start : '' ?>">
+ <?= $selfassign_start == -1 ? '(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <label class="col-3" style="vertical-align: top">
+ <?= _('Selbsteintrag erlaubt bis') ?>
+ <input type="text" class="size-s" data-datetime-picker='{">":"#selfassign_start"}' size="20" name="selfassign_end" value="<?= $selfassign_end != -1 ?
+ $selfassign_end : '' ?>">
+ <?= $selfassign_end == -1 ? '(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <?php foreach ($groups as $g) : ?>
+ <input type="hidden" name="groups[]" value="<?= $g->id ?>">
+ <?php endforeach ?>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript">
+ //<!--
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/_edit_groups_size.php b/app/views/course/statusgroups/_edit_groups_size.php
new file mode 100644
index 0000000..786ff56
--- /dev/null
+++ b/app/views/course/statusgroups/_edit_groups_size.php
@@ -0,0 +1,24 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_save_groups_size') ?>" method="post">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <label>
+ <?= _('Gruppengröße') ?>
+ <input type="number" name="size" value="<?= intval($size) ?>" min="0">
+ <?= $different_sizes ? '(' . _('verschiedene Werte') . ')' : '' ?>
+ </label>
+
+ <?php foreach ($groups as $g) : ?>
+ <input type="hidden" name="groups[]" value="<?= $g->id ?>">
+ <?php endforeach ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript">
+ //<!--
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/_group.php b/app/views/course/statusgroups/_group.php
new file mode 100644
index 0000000..35f8a90
--- /dev/null
+++ b/app/views/course/statusgroups/_group.php
@@ -0,0 +1,142 @@
+<article class="<?= ContentBoxHelper::classes($group->id) ?> <? if ($group->id != 'nogroup' && $is_tutor && !$is_locked) echo 'draggable'; ?> <?= $open_group ? 'open' : '' ?>" id="<?= $group->id ?>">
+ <header>
+ <? if ($group->id != 'nogroup' && $is_tutor && !$is_locked) : ?>
+ <span class="sg-sortable-handle"></span>
+ <? endif ?>
+ <h1>
+ <?php if ($group->id != 'nogroup' && $is_tutor && !$is_locked) : ?>
+ <input aria-label="<?= _('Gruppe auswählen') ?>"
+ type="checkbox" name="groups[]"
+ class="groupselector" value="<?= $group->id ?>"
+ id="<?= $group->id ?>"/>
+ <?php endif ?>
+ <a href="<?= ContentBoxHelper::href($group->id) ?>" class="get-group-members"
+ data-group-id="<?= $group->id ?>"
+ data-get-members-url="<?= $controller->url_for('course/statusgroups/getgroup', $group->id) ?>">
+ <?= htmlReady($group->name) ?> (<?= $membercount .
+ ($group->size ? '/' . $group->size : '') ?>)
+ </a>
+ <?php if ($group->id != 'nogroup') : ?>
+ <a class="no-contentbox-link"
+ href="<?= $controller->url_for('course/statusgroups/groupinfo', $group->id) ?>"
+ data-dialog="size=auto">
+ <?= Icon::create('info-circle')->asImg([
+ 'title' => sprintf(_('Informationen zu %s'), $group->name)
+ ]) ?>
+ </a>
+ <?php endif ?>
+ </h1>
+ <nav>
+ <?php if ($is_autor && !$is_tutor && $group->id != 'nogroup' && $group->isMember($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->link_for('messages/write', [
+ 'group_id' => $group->id,
+ 'default_subject' => htmlReady($course_title . ' (' . $group->name . ')'),
+ ]) ?>" data-dialog="size=auto">
+ <?= Icon::create('mail', 'clickable', ['title' => sprintf(
+ _('Nachricht an alle Mitglieder der Gruppe %s schicken'),
+ $group->name
+ ),
+ ]) ?>
+ </a>
+ <?php endif ?>
+ <?php if (!$GLOBALS['perm']->have_perm('admin')) : ?>
+ <?php if ($group->id != 'nogroup' && $joinable) : ?>
+ <a href="<?= $controller->url_for('course/statusgroups/join', $group->id) ?>">
+ <?= Icon::create('door-enter', 'clickable',
+ ['title' => sprintf(_('Mitglied von Gruppe %s werden'),
+ htmlReady($group->name))]) ?></a>
+ <?php elseif ($group->id != 'nogroup' && $group->selfassign &&
+ $group->selfassign_start > time()) : ?>
+ <?= Icon::create('door-enter', 'inactive',
+ ['title' => sprintf(_('Der Eintrag in diese Gruppe ist möglich ab %s.'),
+ date('d.m.Y H:i', $group->selfassign_start))]) ?>
+ <?php elseif ($group->id != 'nogroup' && $group->selfassign &&
+ $group->selfassign_end && $group->selfassign_end < time()) : ?>
+ <?= Icon::create('door-enter', 'inactive',
+ ['title' => sprintf(_('Der Eintrag in diese Gruppe war möglich bis %s.'),
+ date('d.m.Y H:i', $group->selfassign_end))]) ?>
+ <?php elseif ($group->id != 'nogroup' && $group->userMayLeave($GLOBALS['user']->id)) : ?>
+ <a href="<?= $controller->url_for('course/statusgroups/leave', $group->id) ?>" data-confirm="<?= sprintf(_('Aus Gruppe %s austragen'),htmlReady($group->name)) . '?' ?>">
+ <?= Icon::create('door-leave', 'attention',
+ ['title' => sprintf(_('Aus Gruppe %s austragen'),
+ htmlReady($group->name))]) ?></a>
+ <?php endif ?>
+ <?php endif ?>
+ <?php if ($is_tutor) : ?>
+ <?php if ($group->id != 'nogroup') : ?>
+ <?= ActionMenu::get()
+ ->addLink(
+ $controller->url_for('messages/write', [
+ 'group_id' => $group->id,
+ 'default_subject' => htmlReady($course_title . ' (' . $group->name . ')'),
+ ]),
+ _('Nachricht schicken'),
+ Icon::create('mail', 'clickable', [
+ 'title' => sprintf(
+ _('Nachricht an alle Mitglieder der Gruppe %s schicken'),
+ $group->name
+ ),
+ ]),
+ ['data-dialog' => 'size=auto']
+ )
+ ->condition(!($is_participants_locked || $is_locked))
+ ->addMultiPersonSearch(
+ MultiPersonSearch::get('add_statusgroup_member' . $group->id)
+ ->setTitle(sprintf(_('Personen zu Gruppe %s hinzufügen'), $group->name))
+ ->setLinkText(_('Personen hinzufügen'))
+ ->setSearchObject($memberSearch)
+ ->setDefaultSelectedUser($group->members->pluck('user_id'))
+ ->setDataDialogStatus(Request::isXhr())
+ ->setJSFunctionOnSubmit(Request::isXhr() ?
+ 'STUDIP.Dialog.close();' : false)
+ ->setExecuteURL($controller->url_for('course/statusgroups/add_member/' .
+ $group->id))
+ ->addQuickfilter(_('Veranstaltungsteilnehmende'),
+ $allmembers ? $allmembers->pluck('user_id') : [])
+ ->addQuickfilter(_('Teilnehmende ohne Gruppenzuordnung'),
+ $nogroupmembers)
+ )
+ ->conditionAll(!$is_locked)
+ ->addLink(
+ $controller->url_for('course/statusgroups/edit', $group->id),
+ _('Bearbeiten'),
+ Icon::create('edit', 'clickable', [
+ 'title' => sprintf(
+ _('Gruppe %s bearbeiten'),
+ $group->name
+ )
+ ]),
+ ['data-dialog' => '']
+ )
+ ->addLink(
+ $controller->url_for('course/statusgroups/delete', $group->id),
+ _('Löschen'),
+ Icon::create('trash', 'clickable', [
+ 'title' => sprintf(
+ _('Gruppe %s löschen'),
+ $group->name
+ )
+ ]),
+ ['data-confirm' => _('Soll die Gruppe wirklich gelöscht werden?')]
+ ) ?>
+ <?php else : ?>
+ <a href="<?= $controller->url_for('messages/write', [
+ 'filter' => 'not_grouped',
+ 'course_id' => $course_id,
+ 'default_subject' => htmlReady($course_title).' ('.htmlReady($group->name).')'
+ ]) ?>" data-dialog="size=auto;">
+ <?= Icon::create('mail', 'clickable', [
+ 'title' => _('Nachricht an alle nicht zugeordneten Personen schicken')
+ ])->asImg(20) ?></a>
+ <?php endif ?>
+ <?php endif ?>
+ </nav>
+ </header>
+ <section>
+ <article id="group-members-<?= $group->id ?>"<?= $load ? ' class="open"' : ''?>>
+ <?php if ($load) : ?>
+ <?= $this->render_partial('course/statusgroups/getgroup', compact('members is_tutor is_locked group order sort_by')) ?>
+ <?php endif ?>
+ </article>
+ </section>
+</article>
diff --git a/app/views/course/statusgroups/_member.php b/app/views/course/statusgroups/_member.php
new file mode 100644
index 0000000..a874e6b
--- /dev/null
+++ b/app/views/course/statusgroups/_member.php
@@ -0,0 +1,85 @@
+<? $user_fullname = $m->getUserFullname('full_rev') ?>
+<tr>
+<? if ($is_tutor && !$is_locked) : ?>
+ <td>
+ <input aria-label="<?= _('Mitglieder auswählen') ?>"
+ type="checkbox" name="group[<?= $group->id ?>][<?= $m->user_id ?>]"
+ class="groupmembers-<?= $group->id ?>" value="1">
+ </td>
+<? endif ?>
+ <td>
+ <?= str_pad($i, 2, '0', STR_PAD_LEFT) ?>
+ </td>
+ <td>
+ <a href="<?= $controller->link_for('profile', ['username' => $m->username]) ?>">
+ <?= Avatar::getAvatar($m->user_id, $m->username)->getImageTag(Avatar::SMALL, [
+ 'style' => 'margin-right: 5px',
+ 'title' => $user_fullname,
+ ]) ?>
+ <?= htmlReady($user_fullname) ?>
+ <?php if ($user_id == $m->user_id && $m->visible == 'no') : ?>
+ (<?= _('unsichtbar') ?>)
+ <?php endif ?>
+ </a>
+ </td>
+<? if ($is_tutor) : ?>
+ <? if ($group->id !== 'nogroup'): ?>
+ <td>
+ <?= $m->mkdate ? strftime('%x %X', $m->mkdate) : '' ?>
+ </td>
+ <? endif; ?>
+ <td>
+ <?= $this->render_partial('course/members/_studycourse.php',
+ ['studycourses' => new SimpleCollection(UserStudyCourse::findByUser($m->user_id))]) ?>
+ </td>
+<? endif ?>
+ <td class="memberactions">
+ <? $actions = ActionMenu::get();
+ if ($is_tutor || $m->user_id !== $GLOBALS['user']->id) {
+ $actions->addLink(
+ $controller->url_for('messages/write', [
+ 'rec_uname' => $m->username,
+ 'default_subject' => $course_title,
+ ]),
+ _('Nachricht schicken'),
+ Icon::create('mail', 'clickable', [
+ 'title' => sprintf(_('Nachricht an %s schicken'), $user_fullname),
+ ]),
+ ['data-dialog' => 'size=auto']
+ );
+ }
+ if ($is_tutor) {
+ $actions->addLink(
+ $controller->url_for('course/statusgroups/move_member', $m->user_id, $group->id),
+ _('In eine andere Gruppe verschieben'),
+ Icon::create('person+move_right', 'clickable', [
+ 'title' => sprintf(
+ _('%s in eine andere Gruppe verschieben'),
+ $user_fullname
+ ),
+ ]),
+ ['data-dialog' => 'size=auto']
+ );
+ }
+ if ($group->id !== 'nogroup' && ($is_tutor || ($m->user_id === $GLOBALS['user']->id && $group->userMayLeave($GLOBALS['user']->id)))) {
+ $actions->addLink(
+ $controller->url_for('course/statusgroups/delete_member', $m->user_id, $group->id),
+ _('Aus der Gruppe entfernen'),
+ Icon::create('trash', 'clickable', [
+ 'title' => sprintf(
+ _('%s aus Gruppe %s entfernen'),
+ $user_fullname,
+ $group->name
+ ),
+ ]),
+ ['data-confirm' => sprintf(
+ _('Soll %s wirklich aus der Gruppe %s entfernt werden?'),
+ htmlReady($user_fullname),
+ htmlReady($group->name)
+ )]
+ );
+ }
+ echo $actions;
+ ?>
+ </td>
+</tr>
diff --git a/app/views/course/statusgroups/_move_members.php b/app/views/course/statusgroups/_move_members.php
new file mode 100644
index 0000000..e2ab7db
--- /dev/null
+++ b/app/views/course/statusgroups/_move_members.php
@@ -0,0 +1,25 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_move_members') ?>" method="post">
+ <label for="target_group">
+ <?= sprintf(ngettext(
+ 'In welche Gruppe soll die gewählte Person verschoben werden?',
+ 'In welche Gruppe sollen die %u gewählten Personen verschoben werden?',
+ count($members)),
+ count($members)) ?>
+ <select name="target_group">
+ <?php foreach ($target_groups as $g) : ?>
+ <option value="<?= $g->id ?>"><?= htmlReady($g->name) ?></option>
+ <?php endforeach ?>
+ </select>
+ </label>
+
+ <?php foreach ($members as $m) : ?>
+ <input type="hidden" name="members[]" value="<?= $m ?>"/>
+ <?php endforeach ?>
+ <input type="hidden" name="source" value="<?= $source_group ?>"/>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Verschieben'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/batch_action.php b/app/views/course/statusgroups/batch_action.php
new file mode 100644
index 0000000..10bec38
--- /dev/null
+++ b/app/views/course/statusgroups/batch_action.php
@@ -0,0 +1,28 @@
+<?php
+ if ($edit_size) {
+ echo $this->render_partial('course/statusgroups/_edit_groups_size', compact('groups'));
+ } elseif ($edit_selfassign) {
+ echo $this->render_partial('course/statusgroups/_edit_groups_selfassign', compact('groups'));
+ } elseif ($askdelete) {
+ echo $this->render_partial('course/statusgroups/_askdelete_groups', compact('groups'));
+ } elseif ($movemembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_move_members',
+ compact('target_groups', 'members', 'source_group')
+ );
+ } elseif ($copymembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_copy_members',
+ compact('target_groups', 'members', 'source_group')
+ );
+ } elseif ($deletemembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_askdelete_members',
+ compact('members', 'source_group')
+ );
+ } elseif ($cancelmembers) {
+ echo $this->render_partial(
+ 'course/statusgroups/_askcancel_members',
+ compact('members')
+ );
+ }
diff --git a/app/views/course/statusgroups/create_groups.php b/app/views/course/statusgroups/create_groups.php
new file mode 100644
index 0000000..c011b79
--- /dev/null
+++ b/app/views/course/statusgroups/create_groups.php
@@ -0,0 +1,146 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/batch_create') ?>"
+ method="post" data-secure>
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Wie sollen Gruppen angelegt werden?') ?>
+ </legend>
+ <section>
+ <label>
+ <input type="radio" name="mode" value="numbering" checked
+ onclick="$('.numbering-data').show();$('.course-data').hide();">
+ <?= _('Erzeuge beliebig viele Gruppen mit Namenspräfix') ?>
+ </label>
+ <label>
+ <input type="radio" name="mode" value="coursedata"
+ onclick="$('.numbering-data').hide();$('.course-data').show();">
+ <?= _('Lege Gruppen zu bestehenden Veranstaltungsdaten an') ?>
+ </label>
+ </section>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Lege folgende Gruppen an') ?>
+ </legend>
+ <section class="numbering-data">
+ <label>
+ <span class="required">
+ <?= _('Anzahl anzulegender Gruppen') ?>
+ </span>
+ <input type="number" name="number" value="5" min="1">
+ </label>
+ </section>
+ <section class="numbering-data">
+ <label>
+ <input type="radio" name="numbering_type" value="1" checked>
+ <?= _('Numerische Nummerierung')?>
+ </label>
+ <label>
+ <input type="radio" name="numbering_type" value="2">
+ <?= _('Alphabetische Nummerierung')?>
+ </label>
+ </section>
+ <section class="numbering-data">
+ <label>
+ <?= _('Beginne Nummerierung bei') ?>
+ <input type="number" name="startnumber" value="1" min="0">
+ </label>
+ </section>
+ <section class="numbering-data">
+ <label class="numbering-data">
+ <span class="required">
+ <?= _('Namenspräfix') ?>
+ </span>
+ <input type="text" name="prefix" maxlength="200" value="<?= _('Gruppe') ?>">
+ </label>
+ </section>
+ <? if ($has_paper_related_topics): ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="paper_related">
+ <?= _('Lege eine Gruppe pro Thema vom Typ "Hausarbeit/Referat" an') ?>
+ </label>
+ </section>
+ <? endif; ?>
+ <? if ($has_topics) : ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="topics">
+ <?= _('Lege eine Gruppe pro Thema an') ?>
+ </label>
+ </section>
+ <? endif ?>
+ <? if ($has_cycles || $has_singledates) : ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="dates">
+ <?= _('Lege eine Gruppe pro regelmäßiger Zeit/Einzeltermin an') ?>
+ </label>
+ </section>
+ <? endif ?>
+ <section class="course-data">
+ <label>
+ <input type="radio" name="createmode" value="lecturers">
+ <?= _('Lege eine Gruppe pro Lehrendem an') ?>
+ </label>
+ </section>
+ </fieldset>
+
+ <fieldset>
+ <legend>
+ <?= _('Voreinstellungen für alle anzulegenden Gruppen') ?>
+ </legend>
+ <section>
+ <label>
+ <?= _('Gruppengröße') ?>
+ <input type="number" name="size" value="0" min="0">
+ </label>
+ </section>
+ <section>
+ <label>
+ <input type="checkbox" name="makefolder" value="1">
+ <?= _('Dateiordner anlegen') ?>
+ </label>
+ </section>
+ <section>
+ <label>
+ <input type="checkbox" name="selfassign" value="1">
+ <?= _('Selbsteintrag') ?>
+ </label>
+ </section>
+ <section>
+ <label>
+ <input type="checkbox" name="exclusive" value="1">
+ <?= _('Selbsteintrag in nur eine Gruppe') ?>
+ </label>
+ </section>
+ <section class="col-3">
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt ab') ?>
+ <input type="text" data-datetime-picker id="selfassign_start" size="20"
+ name="selfassign_start" value="<?= date('d.m.Y H:i') ?>">
+ </label>
+ </section>
+ <section class="col-3">
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt bis') ?>
+ <input type="text" data-datetime-picker='{">":"#selfassign_start"}' size="20"
+ name="selfassign_end" value="">
+ </label>
+ </section>
+ </fieldset>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Anlegen'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript" language="JavaScript">
+ //<!--
+ $('.course-data').hide();
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/edit.php b/app/views/course/statusgroups/edit.php
new file mode 100644
index 0000000..2cc8577
--- /dev/null
+++ b/app/views/course/statusgroups/edit.php
@@ -0,0 +1,117 @@
+<form class="default collapsable" action="<?= $controller->url_for('course/statusgroups/save', $group->id) ?>" method="post" data-secure>
+ <?= CSRFProtection::tokenTag() ?>
+
+ <fieldset>
+ <legend>
+ <?= _('Einstellungen') ?>
+ </legend>
+
+ <label for="name" class="required">
+ <?= _('Name') ?>
+ </label>
+ <input type="text" name="name" size="75" maxlength="255" value="<?= htmlReady($group->name) ?>" required>
+
+ <label for="size">
+ <?= _('Gruppengröße') ?>
+ </label>
+ <input type="number" name="size" value="<?= intval($group->size) ?>" min="0">
+
+ <?php if ($group->isNew() || !$group->hasFolder()) : ?>
+ <label>
+ <input type="checkbox" name="makefolder" value="1">
+ <?= _('Dateiordner anlegen') ?>
+ </label>
+ <?php elseif ($group->hasFolder()) : ?>
+ <label>
+ <input type="checkbox" checked disabled>
+ <?= _('Zu dieser Gruppe gehört ein Dateiordner.') ?>
+ </label>
+ <?php endif ?>
+
+ <label>
+ <input type="checkbox" name="blubber" value="1"<?= BlubberStatusgruppeThread::findByStatusgruppe_id($group->id) ? " checked" : "" ?>>
+ <?= _('Blubber in der Gruppe erlauben') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="selfassign" value="1"<?= $group->selfassign ? ' checked' : '' ?>>
+ <?= _('Selbsteintrag erlaubt') ?>
+ </label>
+
+ <label>
+ <input type="checkbox" name="exclusive" value="1"<?= $group->selfassign == 2 ? ' checked' : '' ?>>
+ <?= _('Exklusiver Selbsteintrag (in nur eine Gruppe)') ?>
+ </label>
+
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt ab') ?>
+ <input class="size-s" type="text" size="20" name="selfassign_start" id="selfassign_start" value="<?= $group->selfassign_start ?
+ date('d.m.Y H:i', $group->selfassign_start) : '' ?>" data-datetime-picker>
+ </label>
+
+ <label class="col-3">
+ <?= _('Selbsteintrag erlaubt bis') ?>
+ <input class="size-s" type="text" size="20" name="selfassign_end" value="<?= $group->selfassign_end ?
+ date('d.m.Y H:i', $group->selfassign_end) : '' ?>" data-datetime-picker='{">":"#selfassign_start"}'>
+ </label>
+ </fieldset>
+
+ <h1>
+ <?= _('Zuordnung von Terminen') ?>
+ </h1>
+
+ <?php if ($cycles || $singledates) : ?>
+ <?php if ($cycles) : ?>
+ <fieldset class="collapsed">
+ <legend><?= _('Regelmäßige Zeiten') ?></legend>
+ <?php foreach ($cycles as $c) : ?>
+ <article class="<?= ContentBoxHelper::classes($c->id) ?>" id="<?= $c->id ?>">
+ <header>
+ <h1>
+ <a href="<?= ContentBoxHelper::href($c->id, ['contentbox_type' => 'news']) ?>">
+ <?= htmlReady($c->toString()) ?>
+ </a>
+ </h1>
+ </header>
+ <section>
+ <?php foreach ($c->dates as $d) : ?>
+ <label for="<?= $d->id ?>">
+ <input type="checkbox" name="dates[]" value="<?= $d->id ?>" id="<?= $d->id?>"
+ <?= $group->dates->find($d->id) ? ' checked' : '' ?>>
+ <?= htmlReady($d->getFullname()) ?>
+ </label>
+ <?php endforeach ?>
+ </section>
+ </article>
+ <?php endforeach ?>
+ </fieldset>
+ <?php endif ?>
+ <?php if ($singledates) : ?>
+ <fieldset class="collapsed">
+ <legend>
+ <?= _('Einzeltermine') ?>
+ </legend>
+ <?php foreach ($singledates as $s) : ?>
+ <label for="<?= $s->id ?>">
+ <input type="checkbox" name="dates[]" value="<?= $s->id ?>" id="<?= $s->id?>"
+ <?= $group->dates->find($s->id) ? ' checked' : '' ?>>
+ <?= htmlReady($s->getFullname()) ?>
+ </label>
+ <?php endforeach ?>
+ </fieldset>
+ <?php endif ?>
+ <?php else : ?>
+ <?= MessageBox::info(_('Diese Veranstaltung hat keine Termine.')); ?>
+ <?php endif ?>
+
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Speichern'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
+<script type="text/javascript">
+ //<!--
+ STUDIP.Statusgroups.initInputs();
+ //-->
+</script>
diff --git a/app/views/course/statusgroups/getgroup.php b/app/views/course/statusgroups/getgroup.php
new file mode 100644
index 0000000..426fca4
--- /dev/null
+++ b/app/views/course/statusgroups/getgroup.php
@@ -0,0 +1,134 @@
+<? if (count($members)) : ?>
+ <table class="default">
+ <colgroup>
+ <col width="20">
+ <? if($is_tutor) : ?>
+ <? $cols = $group->id !== 'nogroup' ? 5 : 4 ?>
+ <? if (!$is_locked) : ?>
+ <col width="20">
+ <? $cols = 6 ?>
+ <? endif ?>
+ <col>
+ <? if ($group->id !== 'nogroup'): ?>
+ <col width="15%">
+ <? endif; ?>
+ <col width="35%">
+ <? else : ?>
+ <col>
+ <? $cols = 3 ?>
+ <? endif ?>
+
+ <col width="80">
+ </colgroup>
+ <thead>
+ <tr class="sortable">
+ <? if ($is_tutor && !$is_locked) : ?>
+ <th>
+ <input aria-label="<?= sprintf(_('Alle Mitglieder dieser Gruppe auswählen')) ?>"
+ type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox.groupmembers-<?= $group->id ?>"
+ data-activates=".memberactions-<?= $group->id ?> select,.memberactions-<?= $group->id ?> button">
+ </th>
+ <? endif ?>
+ <th></th>
+ <th <?= ($sort_by == 'nachname' && $sort_group == $group->id) ?
+ sprintf('class="sort%s"', $order) : '' ?>>
+ <a href="<?= URLHelper::getLink('#' . $group->id,
+ [
+ 'sortby' => 'nachname',
+ 'sort_group' => $group->id,
+ 'order' => $group->id && $sort_by == 'nachname' ?
+ ($order == 'desc' ? 'asc' : 'desc') : 'desc',
+ 'contentbox_open' => $group->id
+ ]) ?>">
+ <?=_('Nachname, Vorname')?>
+ </a>
+ </th>
+ <? if ($is_tutor) :?>
+ <? if ($group->id !== 'nogroup'): ?>
+ <th <?= ($sort_by == 'mkdate' && $sort_group == $group->id) ? sprintf('class="sort%s"', $order) : '' ?>>
+ <a href="<?= URLHelper::getLink('#' . $group->id,
+ [
+ 'sortby' => 'mkdate',
+ 'sort_group' => $group->id,
+ 'order' => $group->id && $sort_by == 'mkdate' ?
+ ($order == 'desc' ? 'asc' : 'desc') : 'desc',
+ 'contentbox_open' => $group->id
+ ]) ?>">
+ <?= _('Anmeldedatum') ?>
+ </a>
+ </th>
+ <? endif; ?>
+ <th>
+ <?= _('Studiengang') ?>
+ </th>
+ <? endif ?>
+ <th><?= _('Aktion') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? $i = 1; foreach ($members as $m) : ?>
+ <?= $this->render_partial(
+ 'course/statusgroups/_member',
+ ['m' => $m, 'i' => $i++, 'is_tutor' => $is_tutor, 'is_locked' => $is_locked]) ?>
+ <? endforeach ?>
+ </tbody>
+ <tfoot>
+ <tr>
+ <? if ($is_tutor) : ?>
+ <td colspan="<?= $cols ?>">
+ <? if (!$is_locked) : ?>
+ <div class="memberselect">
+ <label>
+ <input aria-label="<?= sprintf(_('Alle Mitglieder dieser Gruppe auswählen')) ?>"
+ type="checkbox" name="all" value="1"
+ data-proxyfor=":checkbox.groupmembers-<?= $group->id ?>"
+ data-activates=".memberactions-<?= $group->id ?> select,.memberactions-<?= $group->id ?> button">
+ <?= _('Alle Mitglieder dieser Gruppe auswählen') ?>
+ </label>
+ </div>
+ <div class="memberactions memberactions-<?= $group->id ?>">
+ <label>
+ <select name="members_action[<?= $group->id ?>]"
+ id="members-action-<?= $group->id ?>">
+ <option value="move"><?= _('In andere Gruppe verschieben') ?></option>
+ <option value="copy"><?= _('In andere Gruppe kopieren') ?></option>
+ <? if ($group->id != 'nogroup') : ?>
+ <option value="delete"><?= _('Aus dieser Gruppe entfernen') ?></option>
+ <? endif ?>
+ <option value="cancel"><?= _('Austragen aus der Veranstaltung') ?></option>
+ </select>
+ </label>
+ <input type="hidden" name="source" value="<?= $group->id ?>">
+ <?= Studip\Button::create(
+ _('Ausführen'),
+ "batch_members[{$group->id}]",
+ ['data-dialog' => 'size=auto']
+ ) ?>
+ </div>
+ <? endif ?>
+ </td>
+ <? elseif (!$is_tutor) : ?>
+ <td colspan="<?= $cols ?>">
+ <?= sprintf(_('+ %u unsichtbare Personen'), $invisible) ?>
+ </td>
+ <? endif ?>
+ </tr>
+ </tfoot>
+ </table>
+<? elseif ($invisible > 0): ?>
+ <div class="statusgroup-no-members">
+ <?= sprintf(
+ ngettext(
+ 'Diese Gruppe hat %d unsichtbares Mitglied.',
+ 'Diese Gruppe hat %d unsichtbare Mitglieder.',
+ $invisible
+ ),
+ htmlReady($invisible)
+ ) ?>
+ </div>
+<? else : ?>
+ <div class="statusgroup-no-members">
+ <?= _('Diese Gruppe hat keine Mitglieder.') ?>
+ </div>
+<? endif ?>
diff --git a/app/views/course/statusgroups/groupinfo.php b/app/views/course/statusgroups/groupinfo.php
new file mode 100644
index 0000000..bbbf170
--- /dev/null
+++ b/app/views/course/statusgroups/groupinfo.php
@@ -0,0 +1,101 @@
+<header>
+ <h1><?= sprintf(_('Informationen zu %s'), htmlReady($group->name)) ?></h1>
+</header>
+<section>
+ <p>
+ <?= $group->size > 0 ?
+ formatReady(sprintf(_('Diese Gruppe ist auf **%u** Mitglieder beschränkt.'), $group->size)) :
+ formatReady(_('Die Größe dieser Gruppe ist **nicht beschränkt**.')) ?>
+ </p>
+
+ <?php if ($group->selfassign) : ?>
+ <?php if ($group->selfassign == 1) : ?>
+ <p>
+ <?= _('Die Teilnehmenden dieser Veranstaltung können sich ' .
+ 'selbst in beliebig viele der Gruppen eintragen, bei denen ' .
+ 'kein Exklusiveintrag aktiviert ist.') ?>
+ </p>
+ <?php elseif ($group->selfassign == 2) : ?>
+ <p>
+ <?= _('Die Teilnehmenden dieser Veranstaltung können sich ' .
+ 'in genau einer der Gruppen eintragen, bei denen der ' .
+ 'Exklusiveintrag aktiviert ist.') ?>
+ </p>
+ <?php endif ?>
+ <?php if ($group->selfassign_start && $group->selfassign_end) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Der Eintrag ist möglich **von %s bis %s**.'),
+ date('d.m.Y H:i', $group->selfassign_start),
+ date('d.m.Y H:i', $group->selfassign_end))) ?>
+ </p>
+ <?php elseif ($group->selfassign_start && !$group->selfassign_end) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Der Eintrag ist möglich **ab %s**.'),
+ date('d.m.Y H:i', $group->selfassign_start))) ?>
+ </p>
+ <?php elseif (!$group->selfassign_start && $group->selfassign_end) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Der Eintrag ist möglich **bis %s**.'),
+ date('d.m.Y H:i', $group->selfassign_end))) ?>
+ </p>
+ <?php endif ?>
+ <?php endif ?>
+
+ <?php if ($folder = $group->getFolder()) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Zu dieser Gruppe gehört ein [Dateiordner]%s .'),
+ URLHelper::getURL('dispatch.php/course/files/index/' . $folder->id, [
+ 'cid' => $course_id,
+ ]))) ?>
+ </p>
+ <?php endif ?>
+
+ <?php if ($thread = $group->blubberthread) : ?>
+ <p>
+ <?= formatReady(sprintf(_('Zu dieser Gruppe gehört ein [Blubberthread]%s .'),
+ URLHelper::getURL('plugins.php/blubber/messenger/course/' . $thread->id, [
+ 'cid' => $course_id,
+ ]))) ?>
+ </p>
+ <?php endif ?>
+
+ <?php if ($group->dates->count() > 0) : ?>
+ <p>
+ <?= _('Zugeordnete Termine:') ?>
+ <ul>
+ <?php foreach ($group->dates as $d) : ?>
+ <li>
+ <?= htmlReady($d->toString()) ?>
+ </li>
+ <?php endforeach ?>
+ </ul>
+ </p>
+ <?php endif ?>
+
+ <?php if ($topics = $group->findTopics()) : ?>
+ <p>
+ <?= _('Zugeordnete Themen:') ?>
+ <ul>
+ <?php foreach ($topics as $t) : ?>
+ <li><?= htmlReady($t->title) ?></li>
+ <?php endforeach ?>
+ </ul>
+ </p>
+ <?php endif ?>
+
+ <?php if ($lecturers = $group->findLecturers()) : ?>
+ <p>
+ <?= sprintf(_('Zugeordnete %s:'), htmlReady(get_title_for_status('dozent', 2))) ?>
+ <ul>
+ <?php foreach ($lecturers as $l) : ?>
+ <li><?= htmlReady($l->getFullname()) ?></li>
+ <?php endforeach ?>
+ </ul>
+ </p>
+ <?php endif ?>
+</section>
+
+<footer data-dialog-button>
+ <?= Studip\LinkButton::createCancel(_('Schließen'),
+ $controller->url_for('course/statusgroups')) ?>
+</footer>
diff --git a/app/views/course/statusgroups/index.php b/app/views/course/statusgroups/index.php
new file mode 100644
index 0000000..2f75624
--- /dev/null
+++ b/app/views/course/statusgroups/index.php
@@ -0,0 +1,43 @@
+<form action="<?= $controller->url_for('course/statusgroups/batch_action') ?>" method="post">
+<section class="contentbox course-statusgroups" <? if ($is_tutor && !$is_locked) echo 'data-sortable="' . $controller->url_for('course/statusgroups/order') . '"'; ?>>
+ <header>
+ <h1><?= _('Teilnehmende nach Gruppen') ?></h1>
+ </header>
+ <?php foreach ($groups as $group) : ?>
+ <?= $this->render_partial('course/statusgroups/_group', [
+ 'group' => $group['group'],
+ 'membercount' => $group['membercount'],
+ 'members' => $group['members'],
+ 'joinable' => $group['joinable'],
+ 'invisible' => $group['invisible_users'],
+ 'load' => $open_groups ? true : $group['load'],
+ 'order' => $order,
+ 'sort_by' => $sort_by,
+ 'open_group' => $open_groups,
+ ]) ?>
+ <?php endforeach ?>
+ <?php if ((count($groups) > $ungrouped_count ? 2 : 1) && $is_tutor && !$is_locked) : ?>
+ <footer>
+ <div class="groupselection">
+ <label>
+ <input aria-label="<?= sprintf(_('Alle Gruppen auswählen')) ?>"
+ type="checkbox" name="allgroups" value="1"
+ data-proxyfor=":checkbox.groupselector"
+ data-activates="select#batch-groups-action,#batch-groups-submit">
+ <?= _('Alle Gruppen auswählen') ?>
+ </label>
+ </div>
+ <div class="groupactions">
+ <label>
+ <select name="groups_action" id="batch-groups-action" disabled>
+ <option value="edit_size"><?= _('Gruppengröße bearbeiten') ?></option>
+ <option value="edit_selfassign"><?= _('Selbsteintrag bearbeiten') ?></option>
+ <option value="write_message"><?= _('Nachricht schreiben') ?></option>
+ <option value="delete"><?= _('Löschen') ?></option>
+ </select>
+ </label>
+ <?= Studip\Button::create(_('Ausführen'), 'batch_groups', ['data-dialog' => 'size=auto', 'disabled' => '', 'id' => 'batch-groups-submit']) ?>
+ </div>
+ </footer>
+ <?php endif ?>
+</section>
diff --git a/app/views/course/statusgroups/joinables.php b/app/views/course/statusgroups/joinables.php
new file mode 100644
index 0000000..0ef22c2
--- /dev/null
+++ b/app/views/course/statusgroups/joinables.php
@@ -0,0 +1,18 @@
+<form class="default" action="<?= $controller->url_for('course/statusgroups/join') ?>" method="post">
+ <section>
+ <label for="target_group">
+ <?= _('Welcher Gruppe möchten Sie beitreten?') ?>
+ <select name="target_group">
+ <?php foreach ($joinables as $g) : ?>
+ <option value="<?= $g->id ?>"><?= htmlReady($g->name) ?></option>
+ <?php endforeach ?>
+ </select>
+ </label>
+ </section>
+ <?= CSRFProtection::tokenTag() ?>
+ <footer data-dialog-button>
+ <?= Studip\Button::createAccept(_('Beitreten'), 'submit') ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'),
+ $controller->url_for('course/statusgroups')) ?>
+ </footer>
+</form>
diff --git a/app/views/course/statusgroups/move_member.php b/app/views/course/statusgroups/move_member.php
new file mode 100644
index 0000000..2cdd53a
--- /dev/null
+++ b/app/views/course/statusgroups/move_member.php
@@ -0,0 +1,2 @@
+<?= $this->render_partial('course/statusgroups/_move_members',
+ ['target_groups' => $target_groups, 'members' => $members, 'source_group' => $source_group]) ?>